├── .clang-tidy ├── .github ├── actions │ ├── build │ │ └── action.yml │ ├── cmake │ │ └── action.yml │ ├── install-from-git │ │ └── action.yml │ ├── install-macos │ │ └── action.yml │ └── install-ubuntu │ │ └── action.yml └── workflows │ └── ci.yml ├── .gitignore ├── .ycm_extra_conf.py ├── CMakeLists.txt ├── LICENSE.txt ├── README.md ├── cmake ├── FindLZ4.cmake ├── FindOsmium.cmake └── FindProtozero.cmake └── src ├── CMakeLists.txt ├── osm_gis_export_overview.cpp ├── osmium_toogr.cpp ├── osmium_toogr2.cpp └── osmium_toogr2_exp.cpp /.clang-tidy: -------------------------------------------------------------------------------- 1 | --- 2 | Checks: '*,-abseil-*,-altera-*,-fuchsia-*,-cppcoreguidelines-avoid-magic-numbers,-google-runtime-references,-readability-implicit-bool-conversion,-readability-magic-numbers' 3 | # 4 | # For a list of check options, see: 5 | # https://clang.llvm.org/extra/clang-tidy/checks/list.html 6 | # 7 | # Disabled checks: 8 | # 9 | # abseil-* 10 | # We are not using abseil. 11 | # 12 | # altera-* 13 | # Doesn't apply. 14 | # 15 | # cppcoreguidelines-avoid-magic-numbers 16 | # readability-magic-numbers 17 | # Generally good advice, but there are too many places where this is 18 | # useful, for instance in tests. 19 | # 20 | # fuchsia-* 21 | # Much too strict. 22 | # 23 | # google-runtime-references 24 | # This is just a matter of preference. 25 | # 26 | # readability-implicit-bool-conversion 27 | # I don't think this makes the code more readable. 28 | # 29 | #WarningsAsErrors: '*' 30 | ... 31 | -------------------------------------------------------------------------------- /.github/actions/build/action.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Build 7 | run: make VERBOSE=1 8 | shell: bash 9 | working-directory: build 10 | 11 | -------------------------------------------------------------------------------- /.github/actions/cmake/action.yml: -------------------------------------------------------------------------------- 1 | name: CMake 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Create build directory 7 | run: mkdir build 8 | shell: bash 9 | - name: Configure 10 | run: | 11 | cmake -LA .. \ 12 | -DCMAKE_BUILD_TYPE=${BUILD_TYPE} 13 | shell: bash 14 | working-directory: build 15 | 16 | -------------------------------------------------------------------------------- /.github/actions/install-from-git/action.yml: -------------------------------------------------------------------------------- 1 | name: Install Prerequisites from git 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Install from git 7 | run: | 8 | git clone --quiet --depth 1 https://github.com/osmcode/libosmium.git ../libosmium 9 | git clone --quiet --depth 1 https://github.com/mapbox/protozero.git ../protozero 10 | shell: bash 11 | 12 | -------------------------------------------------------------------------------- /.github/actions/install-macos/action.yml: -------------------------------------------------------------------------------- 1 | name: Install homebrew packages on macOS 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Install homebrew packages 7 | run: | 8 | brew install \ 9 | boost \ 10 | gdal \ 11 | spatialite-tools 12 | shell: bash 13 | 14 | -------------------------------------------------------------------------------- /.github/actions/install-ubuntu/action.yml: -------------------------------------------------------------------------------- 1 | name: Install apt packages on Ubuntu/Debian 2 | 3 | runs: 4 | using: composite 5 | steps: 6 | - name: Install packages 7 | run: | 8 | sudo apt-get update -qq 9 | sudo apt-get install -yq \ 10 | libboost-dev \ 11 | libboost-program-options-dev \ 12 | libbz2-dev \ 13 | libgdal-dev 14 | shell: bash 15 | 16 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: [ push, pull_request ] 4 | 5 | jobs: 6 | linux: 7 | runs-on: ubuntu-latest 8 | timeout-minutes: 40 9 | strategy: 10 | fail-fast: false 11 | matrix: 12 | name: [Ubuntu-20, Ubuntu-22, Ubuntu-24, Debian-11, Debian-12, Debian-Testing, Debian-Experimental, Fedora-37, Fedora-38, Fedora-39, Fedora-40] 13 | build_type: [Dev] 14 | cpp_compiler: [g++] 15 | cpp_version: [c++11] 16 | include: 17 | - name: Ubuntu-20 18 | # Uses gcc 9.3.0, clang 10.0.0, cmake 3.16.3 19 | image: "ubuntu:20.04" 20 | ubuntu: 20 21 | - name: Ubuntu-22 22 | # Uses gcc 12.2.0, clang 15.0.7, cmake 3.24.2 23 | image: "ubuntu:22.04" 24 | ubuntu: 22 25 | CXXFLAGS: -Wno-stringop-overread 26 | - name: Ubuntu-24 27 | # Uses gcc 14.2.0, clang 18.1.3, cmake 3.28.3 28 | image: "ubuntu:24.04" 29 | ubuntu: 22 30 | CXXFLAGS: -Wno-stringop-overread 31 | - name: Debian-11 32 | # Uses gcc 10.2.1, clang 11.0.1, cmake 3.18.4 33 | image: "debian:bullseye" 34 | - name: Debian-11 35 | image: "debian:bullseye" 36 | cpp_version: c++17 37 | - name: Debian-11 38 | image: "debian:bullseye" 39 | cpp_version: c++20 40 | - name: Debian-11 41 | image: "debian:bullseye" 42 | c_compiler: clang 43 | cpp_compiler: clang++ 44 | - name: Debian-11 45 | image: "debian:bullseye" 46 | c_compiler: clang 47 | cpp_compiler: clang++ 48 | cpp_version: c++17 49 | - name: Debian-11 50 | image: "debian:bullseye" 51 | c_compiler: clang 52 | cpp_compiler: clang++ 53 | cpp_version: c++20 54 | - name: Debian-11 55 | image: "debian:bullseye" 56 | build_type: RelWithDebInfo 57 | - name: Debian-12 58 | # Uses gcc 12.2.0, clang 15.0.6, cmake 3.25.1 59 | image: "debian:bookworm" 60 | CXXFLAGS: -Wno-stringop-overread 61 | - name: Debian-12 62 | image: "debian:bookworm" 63 | cpp_version: c++17 64 | CXXFLAGS: -Wno-stringop-overread 65 | - name: Debian-12 66 | image: "debian:bookworm" 67 | cpp_version: c++20 68 | CXXFLAGS: -Wno-stringop-overread 69 | - name: Debian-12 70 | image: "debian:bookworm" 71 | c_compiler: clang 72 | cpp_compiler: clang++ 73 | - name: Debian-12 74 | image: "debian:bookworm" 75 | c_compiler: clang 76 | cpp_compiler: clang++ 77 | cpp_version: c++17 78 | - name: Debian-12 79 | image: "debian:bookworm" 80 | c_compiler: clang 81 | cpp_compiler: clang++ 82 | cpp_version: c++20 83 | - name: Debian-12 84 | image: "debian:bookworm" 85 | build_type: RelWithDebInfo 86 | CXXFLAGS: -Wno-stringop-overread 87 | - name: Debian-Testing 88 | image: "debian:testing" 89 | CXXFLAGS: -Wno-stringop-overread 90 | - name: Debian-Testing 91 | image: "debian:testing" 92 | c_compiler: clang 93 | cpp_compiler: clang++ 94 | - name: Debian-Experimental 95 | image: "debian:experimental" 96 | CXXFLAGS: -Wno-stringop-overread 97 | - name: Debian-Experimental 98 | image: "debian:experimental" 99 | c_compiler: clang 100 | cpp_compiler: clang++ 101 | - name: Fedora-37 102 | # Uses gcc 12.3.1, clang 15.0.7, cmake 3.26.4 103 | image: "fedora:37" 104 | CXXFLAGS: -Wno-stringop-overread 105 | - name: Fedora-38 106 | # Uses gcc 13.0.1, clang 16.0.5, cmake 3.26.4 107 | image: "fedora:38" 108 | CXXFLAGS: -Wno-stringop-overread 109 | - name: Fedora-39 110 | image: "fedora:39" 111 | CXXFLAGS: -Wno-stringop-overread 112 | - name: Fedora-40 113 | image: "fedora:40" 114 | CXXFLAGS: -Wno-stringop-overread 115 | container: 116 | image: ${{ matrix.image }} 117 | env: 118 | LANG: en_US.UTF-8 119 | BUILD_TYPE: ${{ matrix.build_type }} 120 | CC: ${{ matrix.c_compiler }} 121 | CXX: ${{ matrix.cpp_compiler }} 122 | CXXFLAGS: ${{ matrix.CXXFLAGS }} 123 | LDFLAGS: ${{ matrix.LDFLAGS }} 124 | CPP_VERSION: ${{ matrix.cpp_version }} 125 | APT_LISTCHANGES_FRONTEND: none 126 | DEBIAN_FRONTEND: noninteractive 127 | steps: 128 | - name: Prepare container (apt) 129 | shell: bash 130 | if: startsWith(matrix.image, 'debian:') || startsWith(matrix.image, 'ubuntu:') 131 | run: | 132 | apt-get update -qq 133 | apt-get install -yq \ 134 | clang \ 135 | cmake \ 136 | g++ \ 137 | git \ 138 | libboost-dev \ 139 | libboost-program-options-dev \ 140 | libbz2-dev \ 141 | libexpat1-dev \ 142 | libgdal-dev \ 143 | libsqlite3-dev \ 144 | make \ 145 | zlib1g-dev 146 | - name: Prepare container (dnf) 147 | shell: bash 148 | if: startsWith(matrix.image, 'fedora:') 149 | run: | 150 | dnf install --quiet --assumeyes \ 151 | boost-devel \ 152 | bzip2-devel \ 153 | cmake \ 154 | expat-devel \ 155 | gcc-c++ \ 156 | gdal-devel \ 157 | git \ 158 | make \ 159 | sqlite-devel \ 160 | zlib-devel 161 | - uses: actions/checkout@v4 162 | - uses: ./.github/actions/install-from-git 163 | - uses: ./.github/actions/cmake 164 | - uses: ./.github/actions/build 165 | 166 | ubuntu-latest: 167 | runs-on: ubuntu-24.04 168 | env: 169 | CC: clang-18 170 | CXX: clang++-18 171 | BUILD_TYPE: Dev 172 | steps: 173 | - uses: actions/checkout@v4 174 | - uses: ./.github/actions/install-ubuntu 175 | - uses: ./.github/actions/install-from-git 176 | - uses: ./.github/actions/cmake 177 | - uses: ./.github/actions/build 178 | 179 | macos: 180 | strategy: 181 | fail-fast: false 182 | matrix: 183 | os: 184 | - "macos-14" 185 | - "macos-15" 186 | build_type: [Dev] 187 | include: 188 | - os: "macos-14" 189 | build_type: Release 190 | runs-on: ${{ matrix.os }} 191 | env: 192 | CC: clang 193 | CXX: clang++ 194 | BUILD_TYPE: ${{ matrix.build_type }} 195 | steps: 196 | - uses: actions/checkout@v4 197 | - uses: ./.github/actions/install-macos 198 | - uses: ./.github/actions/install-from-git 199 | - uses: ./.github/actions/cmake 200 | - uses: ./.github/actions/build 201 | 202 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .*.swp 2 | .ycm_extra_conf.pyc 3 | /build 4 | /libosmium-deps 5 | -------------------------------------------------------------------------------- /.ycm_extra_conf.py: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # 3 | # Configuration for YouCompleteMe Vim plugin 4 | # 5 | # https://valloric.github.io/YouCompleteMe/ 6 | # 7 | #----------------------------------------------------------------------------- 8 | 9 | from os.path import realpath, dirname 10 | 11 | basedir = dirname(realpath(__file__)) 12 | 13 | # some default flags 14 | # for more information install clang-3.2-doc package and 15 | # check UsersManual.html 16 | flags = [ 17 | '-Werror', 18 | '-Wall', 19 | '-Wextra', 20 | '-pedantic', 21 | '-Wno-return-type', 22 | '-Wno-unused-parameter', 23 | '-Wno-unused-variable', 24 | 25 | '-std=c++11', 26 | 27 | # '-x' and 'c++' also required 28 | # use 'c' for C projects 29 | '-x', 30 | 'c++', 31 | 32 | # workaround for https://github.com/Valloric/YouCompleteMe/issues/303 33 | # also see https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=800618 34 | '-isystem', 35 | '/usr/lib/ycmd/clang_includes/', 36 | 37 | # libosmium include dirs 38 | '-I%s/../libosmium/include' % basedir, 39 | '-I/usr/include/gdal', 40 | 41 | ] 42 | 43 | # youcompleteme is calling this function to get flags 44 | # You can also set database for flags. Check: JSONCompilationDatabase.html in 45 | # clang-3.2-doc package 46 | def FlagsForFile( filename ): 47 | return { 48 | 'flags': flags, 49 | 'do_cache': True 50 | } 51 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # 3 | # CMake Config 4 | # 5 | # OSM GIS Export 6 | # 7 | #----------------------------------------------------------------------------- 8 | 9 | cmake_minimum_required(VERSION 3.10 FATAL_ERROR) 10 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 11 | 12 | 13 | #----------------------------------------------------------------------------- 14 | # 15 | # Project version 16 | # 17 | #----------------------------------------------------------------------------- 18 | 19 | # It is important that this setting remains before the "project" call. 20 | set(CMAKE_CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo;MinSizeRel;Dev" 21 | CACHE STRING 22 | "List of available configuration types" 23 | FORCE) 24 | 25 | project(osm-gis-export) 26 | 27 | set(OSM_GIS_EXPORT_VERSION_MAJOR 0) 28 | set(OSM_GIS_EXPORT_VERSION_MINOR 0) 29 | set(OSM_GIS_EXPORT_VERSION_PATCH 1) 30 | 31 | set(OSM_GIS_EXPORT_VERSION 32 | ${OSM_GIS_EXPORT_VERSION_MAJOR}.${OSM_GIS_EXPORT_VERSION_MINOR}.${OSM_GIS_EXPORT_VERSION_PATCH}) 33 | 34 | set(AUTHOR "Jochen Topf ") 35 | 36 | set(CMAKE_EXPORT_COMPILE_COMMANDS ON) 37 | 38 | 39 | #----------------------------------------------------------------------------- 40 | # 41 | # Find external dependencies 42 | # 43 | #----------------------------------------------------------------------------- 44 | 45 | find_package(Boost 1.55.0 REQUIRED COMPONENTS program_options) 46 | include_directories(SYSTEM ${Boost_INCLUDE_DIRS}) 47 | 48 | find_package(Osmium 2.13.1 REQUIRED COMPONENTS io ogr) 49 | include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS}) 50 | 51 | if(MSVC) 52 | find_path(GETOPT_INCLUDE_DIR getopt.h) 53 | find_library(GETOPT_LIBRARY NAMES wingetopt) 54 | if(GETOPT_INCLUDE_DIR AND GETOPT_LIBRARY) 55 | include_directories(SYSTEM ${GETOPT_INCLUDE_DIR}) 56 | list(APPEND OSMIUM_LIBRARIES ${GETOPT_LIBRARY}) 57 | else() 58 | set(GETOPT_MISSING 1) 59 | endif() 60 | endif() 61 | 62 | #----------------------------------------------------------------------------- 63 | # 64 | # Optional "cppcheck" target that checks C++ code 65 | # 66 | #----------------------------------------------------------------------------- 67 | message(STATUS "Looking for cppcheck") 68 | find_program(CPPCHECK cppcheck) 69 | 70 | if(CPPCHECK) 71 | message(STATUS "Looking for cppcheck - found") 72 | set(CPPCHECK_OPTIONS --enable=all) 73 | 74 | # cpp doesn't find system includes for some reason, suppress that report 75 | set(CPPCHECK_OPTIONS ${CPPCHECK_OPTIONS} --suppress=missingIncludeSystem) 76 | 77 | add_custom_target(cppcheck ${CPPCHECK} --std=c++14 ${CPPCHECK_OPTIONS} ${CMAKE_SOURCE_DIR}/src/*pp) 78 | else() 79 | message(STATUS "Looking for cppcheck - not found") 80 | message(STATUS " Build target 'cppcheck' will not be available") 81 | endif() 82 | 83 | 84 | #----------------------------------------------------------------------------- 85 | # 86 | # Optional "clang-tidy" target 87 | # 88 | #----------------------------------------------------------------------------- 89 | message(STATUS "Looking for clang-tidy") 90 | find_program(CLANG_TIDY NAMES clang-tidy clang-tidy-20 clang-tidy-19 clang-tidy-18 clang-tidy-17 clang-tidy-16 clang-tidy-15 clang-tidy-14) 91 | 92 | if(CLANG_TIDY) 93 | message(STATUS "Looking for clang-tidy - found ${CLANG_TIDY}") 94 | 95 | add_custom_target(clang-tidy 96 | ${CLANG_TIDY} 97 | -p ${CMAKE_BINARY_DIR} 98 | osm_gis_export_overview.cpp 99 | osmium_toogr.cpp 100 | osmium_toogr2.cpp 101 | osmium_toogr2_exp.cpp 102 | WORKING_DIRECTORY "${CMAKE_SOURCE_DIR}/src" 103 | ) 104 | else() 105 | message(STATUS "Looking for clang-tidy - not found") 106 | message(STATUS " Build target 'clang-tidy' will not be available.") 107 | endif() 108 | 109 | 110 | #----------------------------------------------------------------------------- 111 | # 112 | # Optional "iwyu" target to check headers 113 | # https://include-what-you-use.org/ 114 | # 115 | #----------------------------------------------------------------------------- 116 | find_program(IWYU_TOOL iwyu_tool.py) 117 | 118 | if(IWYU_TOOL) 119 | message(STATUS "Looking for iwyu_tool.py - found") 120 | add_custom_target(iwyu ${IWYU_TOOL} -p ${CMAKE_BINARY_DIR}) 121 | else() 122 | message(STATUS "Looking for iwyu_tool.py - not found") 123 | message(STATUS " Make target 'iwyu' will not be available") 124 | endif() 125 | 126 | 127 | #----------------------------------------------------------------------------- 128 | # 129 | # Decide which C++ version to use (Minimum/default: C++14). 130 | # 131 | #----------------------------------------------------------------------------- 132 | if(NOT MSVC) 133 | if(NOT USE_CPP_VERSION) 134 | set(USE_CPP_VERSION c++14) 135 | endif() 136 | message(STATUS "Use C++ version: ${USE_CPP_VERSION}") 137 | # following only available from cmake 2.8.12: 138 | # add_compile_options(-std=${USE_CPP_VERSION}) 139 | # so using this instead: 140 | add_definitions(-std=${USE_CPP_VERSION}) 141 | endif() 142 | 143 | 144 | #----------------------------------------------------------------------------- 145 | # 146 | # Compiler and Linker flags 147 | # 148 | #----------------------------------------------------------------------------- 149 | if(MSVC) 150 | set(DEV_COMPILE_OPTIONS "/Ox") 151 | set(RWD_COMPILE_OPTIONS "/Ox /DNDEBUG") 152 | else() 153 | set(DEV_COMPILE_OPTIONS "-O3 -g") 154 | set(RWD_COMPILE_OPTIONS "-O3 -g -DNDEBUG") 155 | endif() 156 | 157 | if(WIN32) 158 | add_definitions(-DWIN32 -D_WIN32 -DMSWIN32 -DBGDWIN32 159 | -DWINVER=0x0500 -D_WIN32_WINNT=0x0500 -D_WIN32_IE=0x0600) 160 | endif() 161 | 162 | set(CMAKE_CXX_FLAGS_DEV "${DEV_COMPILE_OPTIONS}" 163 | CACHE STRING "Flags used by the compiler during developer builds." 164 | FORCE) 165 | 166 | set(CMAKE_EXE_LINKER_FLAGS_DEV "" 167 | CACHE STRING "Flags used by the linker during developer builds." 168 | FORCE) 169 | mark_as_advanced( 170 | CMAKE_CXX_FLAGS_DEV 171 | CMAKE_EXE_LINKER_FLAGS_DEV 172 | ) 173 | 174 | set(CMAKE_CXX_FLAGS_RELWITHDEBINFO "${RWD_COMPILE_OPTIONS}" 175 | CACHE STRING "Flags used by the compiler during RELWITHDEBINFO builds." 176 | FORCE) 177 | 178 | 179 | #----------------------------------------------------------------------------- 180 | # 181 | # Build Type 182 | # 183 | #----------------------------------------------------------------------------- 184 | 185 | # In 'Dev' mode: compile with very strict warnings and turn them into errors. 186 | if(CMAKE_BUILD_TYPE STREQUAL "Dev") 187 | if(NOT MSVC) 188 | add_definitions(-Werror -fno-omit-frame-pointer) 189 | endif() 190 | add_definitions(${OSMIUM_WARNING_OPTIONS}) 191 | endif() 192 | 193 | # Force RelWithDebInfo build type if none was given 194 | if(CMAKE_BUILD_TYPE) 195 | set(build_type ${CMAKE_BUILD_TYPE}) 196 | else() 197 | set(build_type "RelWithDebInfo") 198 | endif() 199 | 200 | set(CMAKE_BUILD_TYPE ${build_type} 201 | CACHE STRING 202 | "Choose the type of build, options are: ${CMAKE_CONFIGURATION_TYPES}." 203 | FORCE) 204 | 205 | 206 | #----------------------------------------------------------------------------- 207 | 208 | add_definitions(${OSMIUM_WARNING_OPTIONS}) 209 | 210 | add_subdirectory(src) 211 | 212 | 213 | #----------------------------------------------------------------------------- 214 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Boost Software License - Version 1.0 - August 17th, 2003 2 | 3 | Permission is hereby granted, free of charge, to any person or organization 4 | obtaining a copy of the software and accompanying documentation covered by 5 | this license (the "Software") to use, reproduce, display, distribute, 6 | execute, and transmit the Software, and to prepare derivative works of the 7 | Software, and to permit third-parties to whom the Software is furnished to 8 | do so, all subject to the following: 9 | 10 | The copyright notices in the Software and this entire statement, including 11 | the above license grant, this restriction and the following disclaimer, 12 | must be included in all copies of the Software, in whole or in part, and 13 | all derivative works of the Software, unless such copies or derivative 14 | works are solely in the form of machine-executable object code generated by 15 | a source language processor. 16 | 17 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 18 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 19 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT 20 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE 21 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, 22 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 23 | DEALINGS IN THE SOFTWARE. 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | # OSM GIS Export 3 | 4 | This is some older code, not really maintained, but could be useful, so we 5 | keep it here. 6 | 7 | A bunch of programs to export OSM data into GIS formats such as Shapefiles, 8 | PostgreSQL or Spatialite. 9 | 10 | [![Build Status](https://github.com/osmcode/osm-gis-export/actions/workflows/ci.yml/badge.svg)](https://github.com/osmcode/osm-gis-export/actions) 11 | 12 | Sorry, do docs yet. You have to look at the source code and change it according 13 | to your needs. This software can be used as basis for your own experiments, but 14 | you need to understand C++ for that. There is no one-size-fits-all solution 15 | here. Use `osmium_toogr` as a basis if you only need nodes or ways, no 16 | (multi)polygons. Use `osmium_toogr2` as basis if you also need multipolygon 17 | support. 18 | 19 | 20 | ## Requires 21 | 22 | You need a C++14 compliant compiler. You also need the following libraries: 23 | 24 | Osmium Library 25 | Need at least version 2.13.1 26 | https://osmcode.org/libosmium 27 | Debian/Ubuntu: libosmium2-dev 28 | 29 | Protozero 30 | Need at least version 1.5.1 31 | https://github.com/mapbox/protozero 32 | Debian/Ubuntu: libprotozero-dev 33 | 34 | gdalcpp 35 | https://github.com/joto/gdalcpp 36 | Included in the libosmium repository. 37 | 38 | bz2lib (for reading and writing bzipped files) 39 | http://www.bzip.org/ 40 | Debian/Ubuntu: libbz2-dev 41 | 42 | CMake (for building) 43 | https://www.cmake.org/ 44 | Debian/Ubuntu: cmake 45 | 46 | Expat (for parsing XML files) 47 | https://libexpat.github.io 48 | Debian/Ubuntu: libexpat1-dev 49 | openSUSE: libexpat-devel 50 | 51 | GDAL/OGR 52 | https://gdal.org/ 53 | Debian/Ubuntu: libgdal-dev 54 | 55 | zlib (for PBF support) 56 | https://www.zlib.net/ 57 | Debian/Ubuntu: zlib1g-dev 58 | openSUSE: zlib-devel 59 | 60 | ## Installing dependencies 61 | 62 | ### On Debian/Ubuntu 63 | 64 | apt-get install cmake libosmium2-dev libgdal-dev libproj-dev 65 | 66 | In addition you might want to look at https://github.com/osmcode/osmium-proj if 67 | you are using PROJ 6 or above. 68 | 69 | ## Building 70 | 71 | [CMake](https://www.cmake.org) is used for building. 72 | 73 | To build run: 74 | 75 | mkdir build 76 | cd build 77 | cmake .. 78 | make 79 | 80 | 81 | ## License 82 | 83 | OSM GIS Export is available under the Boost Software License. See LICENSE.txt. 84 | 85 | 86 | ## Authors 87 | 88 | OSM GIS Export was mainly written and is maintained by Jochen Topf 89 | (jochen@topf.org). See the git commit log for other authors. 90 | 91 | 92 | ## Contact 93 | 94 | Bug reports, questions etc. should be directed to the 95 | [issue tracker](https://github.com/osmcode/osm-gis-export). 96 | 97 | 98 | -------------------------------------------------------------------------------- /cmake/FindLZ4.cmake: -------------------------------------------------------------------------------- 1 | find_path(LZ4_INCLUDE_DIR 2 | NAMES lz4.h 3 | DOC "lz4 include directory") 4 | mark_as_advanced(LZ4_INCLUDE_DIR) 5 | find_library(LZ4_LIBRARY 6 | NAMES lz4 liblz4 7 | DOC "lz4 library") 8 | mark_as_advanced(LZ4_LIBRARY) 9 | 10 | if (LZ4_INCLUDE_DIR) 11 | file(STRINGS "${LZ4_INCLUDE_DIR}/lz4.h" _lz4_version_lines 12 | REGEX "#define[ \t]+LZ4_VERSION_(MAJOR|MINOR|RELEASE)") 13 | string(REGEX REPLACE ".*LZ4_VERSION_MAJOR *\([0-9]*\).*" "\\1" _lz4_version_major "${_lz4_version_lines}") 14 | string(REGEX REPLACE ".*LZ4_VERSION_MINOR *\([0-9]*\).*" "\\1" _lz4_version_minor "${_lz4_version_lines}") 15 | string(REGEX REPLACE ".*LZ4_VERSION_RELEASE *\([0-9]*\).*" "\\1" _lz4_version_release "${_lz4_version_lines}") 16 | set(LZ4_VERSION "${_lz4_version_major}.${_lz4_version_minor}.${_lz4_version_release}") 17 | unset(_lz4_version_major) 18 | unset(_lz4_version_minor) 19 | unset(_lz4_version_release) 20 | unset(_lz4_version_lines) 21 | endif () 22 | 23 | include(FindPackageHandleStandardArgs) 24 | find_package_handle_standard_args(LZ4 25 | REQUIRED_VARS LZ4_LIBRARY LZ4_INCLUDE_DIR 26 | VERSION_VAR LZ4_VERSION) 27 | 28 | if (LZ4_FOUND) 29 | set(LZ4_INCLUDE_DIRS "${LZ4_INCLUDE_DIR}") 30 | set(LZ4_LIBRARIES "${LZ4_LIBRARY}") 31 | 32 | if (NOT TARGET LZ4::LZ4) 33 | add_library(LZ4::LZ4 UNKNOWN IMPORTED) 34 | set_target_properties(LZ4::LZ4 PROPERTIES 35 | IMPORTED_LOCATION "${LZ4_LIBRARY}" 36 | INTERFACE_INCLUDE_DIRECTORIES "${LZ4_INCLUDE_DIR}") 37 | endif () 38 | endif () 39 | -------------------------------------------------------------------------------- /cmake/FindOsmium.cmake: -------------------------------------------------------------------------------- 1 | #---------------------------------------------------------------------- 2 | # 3 | # FindOsmium.cmake 4 | # 5 | # Find the Libosmium headers and, optionally, several components needed 6 | # for different Libosmium functions. 7 | # 8 | #---------------------------------------------------------------------- 9 | # 10 | # Usage: 11 | # 12 | # Copy this file somewhere into your project directory, where cmake can 13 | # find it. Usually this will be a directory called "cmake" which you can 14 | # add to the CMake module search path with the following line in your 15 | # CMakeLists.txt: 16 | # 17 | # list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 18 | # 19 | # Then add the following in your CMakeLists.txt: 20 | # 21 | # find_package(Osmium [version] REQUIRED COMPONENTS ) 22 | # include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS}) 23 | # 24 | # The version number is optional. If it is not set, any version of 25 | # libosmium will do. 26 | # 27 | # For the substitute a space separated list of one or more of the 28 | # following components: 29 | # 30 | # pbf - include libraries needed for PBF input and output 31 | # xml - include libraries needed for XML input and output 32 | # io - include libraries needed for any type of input/output 33 | # geos - include if you want to use any of the GEOS functions 34 | # gdal - include if you want to use any of the OGR functions 35 | # proj - include if you want to use any of the Proj.4 functions 36 | # sparsehash - include if you use the sparsehash index (deprecated!) 37 | # lz4 - include support for LZ4 compression of PBF files 38 | # 39 | # You can check for success with something like this: 40 | # 41 | # if(NOT OSMIUM_FOUND) 42 | # message(WARNING "Libosmium not found!\n") 43 | # endif() 44 | # 45 | #---------------------------------------------------------------------- 46 | # 47 | # Variables: 48 | # 49 | # OSMIUM_FOUND - True if Osmium found. 50 | # OSMIUM_INCLUDE_DIRS - Where to find include files. 51 | # OSMIUM_XML_LIBRARIES - Libraries needed for XML I/O. 52 | # OSMIUM_PBF_LIBRARIES - Libraries needed for PBF I/O. 53 | # OSMIUM_IO_LIBRARIES - Libraries needed for XML or PBF I/O. 54 | # OSMIUM_LIBRARIES - All libraries Osmium uses somewhere. 55 | # 56 | #---------------------------------------------------------------------- 57 | 58 | # This is the list of directories where we look for osmium includes. 59 | set(_osmium_include_path 60 | ../libosmium 61 | ~/Library/Frameworks 62 | /Library/Frameworks 63 | /opt/local # DarwinPorts 64 | /opt 65 | ) 66 | 67 | # Look for the header file. 68 | find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp 69 | PATH_SUFFIXES include 70 | PATHS ${_osmium_include_path} 71 | ) 72 | 73 | # Check libosmium version number 74 | if(Osmium_FIND_VERSION) 75 | if(NOT EXISTS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp") 76 | 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.") 77 | endif() 78 | file(STRINGS "${OSMIUM_INCLUDE_DIR}/osmium/version.hpp" _libosmium_version_define REGEX "#define LIBOSMIUM_VERSION_STRING") 79 | if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"") 80 | set(_libosmium_version "${CMAKE_MATCH_1}") 81 | else() 82 | set(_libosmium_version "unknown") 83 | endif() 84 | endif() 85 | 86 | set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}") 87 | 88 | #---------------------------------------------------------------------- 89 | # 90 | # Check for optional components 91 | # 92 | #---------------------------------------------------------------------- 93 | if(Osmium_FIND_COMPONENTS) 94 | foreach(_component ${Osmium_FIND_COMPONENTS}) 95 | string(TOUPPER ${_component} _component_uppercase) 96 | set(Osmium_USE_${_component_uppercase} TRUE) 97 | endforeach() 98 | endif() 99 | 100 | #---------------------------------------------------------------------- 101 | # Component 'io' is an alias for 'pbf' and 'xml' 102 | if(Osmium_USE_IO) 103 | set(Osmium_USE_PBF TRUE) 104 | set(Osmium_USE_XML TRUE) 105 | endif() 106 | 107 | #---------------------------------------------------------------------- 108 | # Component 'ogr' is an alias for 'gdal' 109 | if(Osmium_USE_OGR) 110 | set(Osmium_USE_GDAL TRUE) 111 | endif() 112 | 113 | #---------------------------------------------------------------------- 114 | # Component 'pbf' 115 | if(Osmium_USE_PBF) 116 | find_package(ZLIB) 117 | find_package(Threads) 118 | find_package(Protozero 1.6.3) 119 | 120 | if(Osmium_USE_LZ4) 121 | find_package(LZ4 REQUIRED) 122 | add_definitions(-DOSMIUM_WITH_LZ4) 123 | endif() 124 | 125 | list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR) 126 | if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_FOUND) 127 | list(APPEND OSMIUM_PBF_LIBRARIES 128 | ${ZLIB_LIBRARIES} 129 | ${LZ4_LIBRARIES} 130 | ${CMAKE_THREAD_LIBS_INIT} 131 | ) 132 | list(APPEND OSMIUM_INCLUDE_DIRS 133 | ${ZLIB_INCLUDE_DIR} 134 | ${LZ4_INCLUDE_DIRS} 135 | ${PROTOZERO_INCLUDE_DIR} 136 | ) 137 | else() 138 | message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.") 139 | endif() 140 | endif() 141 | 142 | #---------------------------------------------------------------------- 143 | # Component 'xml' 144 | if(Osmium_USE_XML) 145 | find_package(EXPAT) 146 | find_package(BZip2) 147 | find_package(ZLIB) 148 | find_package(Threads) 149 | 150 | list(APPEND OSMIUM_EXTRA_FIND_VARS EXPAT_FOUND BZIP2_FOUND ZLIB_FOUND Threads_FOUND) 151 | if(EXPAT_FOUND AND BZIP2_FOUND AND ZLIB_FOUND AND Threads_FOUND) 152 | list(APPEND OSMIUM_XML_LIBRARIES 153 | ${EXPAT_LIBRARIES} 154 | ${BZIP2_LIBRARIES} 155 | ${ZLIB_LIBRARIES} 156 | ${CMAKE_THREAD_LIBS_INIT} 157 | ) 158 | list(APPEND OSMIUM_INCLUDE_DIRS 159 | ${EXPAT_INCLUDE_DIR} 160 | ${BZIP2_INCLUDE_DIR} 161 | ${ZLIB_INCLUDE_DIR} 162 | ) 163 | else() 164 | message(WARNING "Osmium: Can not find some libraries for XML input/output, please install them or configure the paths.") 165 | endif() 166 | endif() 167 | 168 | #---------------------------------------------------------------------- 169 | list(APPEND OSMIUM_IO_LIBRARIES 170 | ${OSMIUM_PBF_LIBRARIES} 171 | ${OSMIUM_XML_LIBRARIES} 172 | ) 173 | 174 | list(APPEND OSMIUM_LIBRARIES 175 | ${OSMIUM_IO_LIBRARIES} 176 | ) 177 | 178 | #---------------------------------------------------------------------- 179 | # Component 'geos' 180 | if(Osmium_USE_GEOS) 181 | find_path(GEOS_INCLUDE_DIR geos/geom.h) 182 | find_library(GEOS_LIBRARY NAMES geos) 183 | 184 | list(APPEND OSMIUM_EXTRA_FIND_VARS GEOS_INCLUDE_DIR GEOS_LIBRARY) 185 | if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY) 186 | SET(GEOS_FOUND 1) 187 | list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY}) 188 | list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR}) 189 | else() 190 | message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.") 191 | endif() 192 | endif() 193 | 194 | #---------------------------------------------------------------------- 195 | # Component 'gdal' (alias 'ogr') 196 | if(Osmium_USE_GDAL) 197 | find_package(GDAL) 198 | 199 | list(APPEND OSMIUM_EXTRA_FIND_VARS GDAL_FOUND) 200 | if(GDAL_FOUND) 201 | list(APPEND OSMIUM_LIBRARIES ${GDAL_LIBRARIES}) 202 | list(APPEND OSMIUM_INCLUDE_DIRS ${GDAL_INCLUDE_DIRS}) 203 | else() 204 | message(WARNING "Osmium: GDAL library is required but not found, please install it or configure the paths.") 205 | endif() 206 | endif() 207 | 208 | #---------------------------------------------------------------------- 209 | # Component 'proj' 210 | if(Osmium_USE_PROJ) 211 | find_path(PROJ_INCLUDE_DIR proj_api.h) 212 | find_library(PROJ_LIBRARY NAMES proj) 213 | 214 | list(APPEND OSMIUM_EXTRA_FIND_VARS PROJ_INCLUDE_DIR PROJ_LIBRARY) 215 | if(PROJ_INCLUDE_DIR AND PROJ_LIBRARY) 216 | set(PROJ_FOUND 1) 217 | list(APPEND OSMIUM_LIBRARIES ${PROJ_LIBRARY}) 218 | list(APPEND OSMIUM_INCLUDE_DIRS ${PROJ_INCLUDE_DIR}) 219 | else() 220 | message(WARNING "Osmium: PROJ.4 library is required but not found, please install it or configure the paths.") 221 | endif() 222 | endif() 223 | 224 | #---------------------------------------------------------------------- 225 | # Component 'sparsehash' 226 | if(Osmium_USE_SPARSEHASH) 227 | message(WARNING "Osmium: Use of Google SparseHash is deprecated. Please switch to a different index type.") 228 | find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable) 229 | 230 | list(APPEND OSMIUM_EXTRA_FIND_VARS SPARSEHASH_INCLUDE_DIR) 231 | if(SPARSEHASH_INCLUDE_DIR) 232 | # Find size of sparsetable::size_type. This does not work on older 233 | # CMake versions because they can do this check only in C, not in C++. 234 | if(NOT CMAKE_VERSION VERSION_LESS 3.0) 235 | include(CheckTypeSize) 236 | set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR}) 237 | set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable") 238 | check_type_size("google::sparsetable::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX) 239 | set(CMAKE_EXTRA_INCLUDE_FILES) 240 | set(CMAKE_REQUIRED_INCLUDES) 241 | else() 242 | set(SPARSETABLE_SIZE_TYPE ${CMAKE_SIZEOF_VOID_P}) 243 | endif() 244 | 245 | # Sparsetable::size_type must be at least 8 bytes (64bit), otherwise 246 | # OSM object IDs will not fit. 247 | if(SPARSETABLE_SIZE_TYPE GREATER 7) 248 | set(SPARSEHASH_FOUND 1) 249 | add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND}) 250 | list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR}) 251 | else() 252 | message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).") 253 | endif() 254 | else() 255 | message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.") 256 | endif() 257 | endif() 258 | 259 | #---------------------------------------------------------------------- 260 | 261 | list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS) 262 | 263 | if(OSMIUM_XML_LIBRARIES) 264 | list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES) 265 | endif() 266 | 267 | if(OSMIUM_PBF_LIBRARIES) 268 | list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES) 269 | endif() 270 | 271 | if(OSMIUM_IO_LIBRARIES) 272 | list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES) 273 | endif() 274 | 275 | if(OSMIUM_LIBRARIES) 276 | list(REMOVE_DUPLICATES OSMIUM_LIBRARIES) 277 | endif() 278 | 279 | #---------------------------------------------------------------------- 280 | # 281 | # Check that all required libraries are available 282 | # 283 | #---------------------------------------------------------------------- 284 | if(OSMIUM_EXTRA_FIND_VARS) 285 | list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS) 286 | endif() 287 | # Handle the QUIETLY and REQUIRED arguments and the optional version check 288 | # and set OSMIUM_FOUND to TRUE if all listed variables are TRUE. 289 | include(FindPackageHandleStandardArgs) 290 | find_package_handle_standard_args(Osmium 291 | REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS} 292 | VERSION_VAR _libosmium_version) 293 | unset(OSMIUM_EXTRA_FIND_VARS) 294 | 295 | #---------------------------------------------------------------------- 296 | # 297 | # A function for setting the -pthread option in compilers/linkers 298 | # 299 | #---------------------------------------------------------------------- 300 | function(set_pthread_on_target _target) 301 | if(NOT MSVC) 302 | set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "-pthread") 303 | if(NOT APPLE) 304 | set_target_properties(${_target} PROPERTIES LINK_FLAGS "-pthread") 305 | endif() 306 | endif() 307 | endfunction() 308 | 309 | #---------------------------------------------------------------------- 310 | # 311 | # Add compiler flags 312 | # 313 | #---------------------------------------------------------------------- 314 | add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64) 315 | 316 | if(MSVC) 317 | add_definitions(-wd4996) 318 | 319 | # Disable warning C4068: "unknown pragma" because we want it to ignore 320 | # pragmas for other compilers. 321 | add_definitions(-wd4068) 322 | 323 | # Disable warning C4715: "not all control paths return a value" because 324 | # it generates too many false positives. 325 | add_definitions(-wd4715) 326 | 327 | # Disable warning C4351: new behavior: elements of array '...' will be 328 | # default initialized. The new behaviour is correct and we don't support 329 | # old compilers anyway. 330 | add_definitions(-wd4351) 331 | 332 | # Disable warning C4503: "decorated name length exceeded, name was truncated" 333 | # there are more than 150 of generated names in libosmium longer than 4096 symbols supported in MSVC 334 | add_definitions(-wd4503) 335 | 336 | add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS) 337 | endif() 338 | 339 | if(APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang") 340 | # following only available from cmake 2.8.12: 341 | # add_compile_options(-stdlib=libc++) 342 | # so using this instead: 343 | add_definitions(-stdlib=libc++) 344 | set(LDFLAGS ${LDFLAGS} -stdlib=libc++) 345 | endif() 346 | 347 | #---------------------------------------------------------------------- 348 | 349 | # This is a set of recommended warning options that can be added when compiling 350 | # libosmium code. 351 | if(MSVC) 352 | set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium") 353 | else() 354 | set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast" CACHE STRING "Recommended warning options for libosmium") 355 | endif() 356 | 357 | set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal") 358 | 359 | if(Osmium_DEBUG) 360 | message(STATUS "OSMIUM_XML_LIBRARIES=${OSMIUM_XML_LIBRARIES}") 361 | message(STATUS "OSMIUM_PBF_LIBRARIES=${OSMIUM_PBF_LIBRARIES}") 362 | message(STATUS "OSMIUM_IO_LIBRARIES=${OSMIUM_IO_LIBRARIES}") 363 | message(STATUS "OSMIUM_LIBRARIES=${OSMIUM_LIBRARIES}") 364 | message(STATUS "OSMIUM_INCLUDE_DIRS=${OSMIUM_INCLUDE_DIRS}") 365 | endif() 366 | 367 | -------------------------------------------------------------------------------- /cmake/FindProtozero.cmake: -------------------------------------------------------------------------------- 1 | #---------------------------------------------------------------------- 2 | # 3 | # FindProtozero.cmake 4 | # 5 | # Find the protozero headers. 6 | # 7 | #---------------------------------------------------------------------- 8 | # 9 | # Usage: 10 | # 11 | # Copy this file somewhere into your project directory, where cmake can 12 | # find it. Usually this will be a directory called "cmake" which you can 13 | # add to the CMake module search path with the following line in your 14 | # CMakeLists.txt: 15 | # 16 | # list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake") 17 | # 18 | # Then add the following in your CMakeLists.txt: 19 | # 20 | # find_package(Protozero [version] [REQUIRED]) 21 | # include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR}) 22 | # 23 | # The version number is optional. If it is not set, any version of 24 | # protozero will do. 25 | # 26 | # if(NOT PROTOZERO_FOUND) 27 | # message(WARNING "Protozero not found!\n") 28 | # endif() 29 | # 30 | #---------------------------------------------------------------------- 31 | # 32 | # Variables: 33 | # 34 | # PROTOZERO_FOUND - True if Protozero was found. 35 | # PROTOZERO_INCLUDE_DIR - Where to find include files. 36 | # 37 | #---------------------------------------------------------------------- 38 | 39 | # find include path 40 | find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp 41 | PATH_SUFFIXES include 42 | PATHS ${CMAKE_SOURCE_DIR}/../protozero 43 | ) 44 | 45 | # Check version number 46 | if(Protozero_FIND_VERSION) 47 | file(STRINGS "${PROTOZERO_INCLUDE_DIR}/protozero/version.hpp" _version_define REGEX "#define PROTOZERO_VERSION_STRING") 48 | if("${_version_define}" MATCHES "#define PROTOZERO_VERSION_STRING \"([0-9.]+)\"") 49 | set(_version "${CMAKE_MATCH_1}") 50 | else() 51 | set(_version "unknown") 52 | endif() 53 | endif() 54 | 55 | #set(PROTOZERO_INCLUDE_DIRS "${PROTOZERO_INCLUDE_DIR}") 56 | 57 | include(FindPackageHandleStandardArgs) 58 | find_package_handle_standard_args(Protozero 59 | REQUIRED_VARS PROTOZERO_INCLUDE_DIR 60 | VERSION_VAR _version) 61 | 62 | 63 | #---------------------------------------------------------------------- 64 | -------------------------------------------------------------------------------- /src/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | #----------------------------------------------------------------------------- 2 | # 3 | # CMake Config 4 | # 5 | #----------------------------------------------------------------------------- 6 | 7 | add_executable(osm_gis_export_overview osm_gis_export_overview.cpp) 8 | target_link_libraries(osm_gis_export_overview ${OSMIUM_LIBRARIES} ${Boost_LIBRARIES}) 9 | set_pthread_on_target(osm_gis_export_overview) 10 | install(TARGETS osm_gis_export_overview DESTINATION bin) 11 | 12 | add_executable(osmium_toogr osmium_toogr.cpp) 13 | target_link_libraries(osmium_toogr ${OSMIUM_LIBRARIES}) 14 | set_pthread_on_target(osmium_toogr) 15 | install(TARGETS osmium_toogr DESTINATION bin) 16 | 17 | add_executable(osmium_toogr2 osmium_toogr2.cpp) 18 | target_link_libraries(osmium_toogr2 ${OSMIUM_LIBRARIES}) 19 | set_pthread_on_target(osmium_toogr2) 20 | install(TARGETS osmium_toogr2 DESTINATION bin) 21 | 22 | add_executable(osmium_toogr2_exp osmium_toogr2_exp.cpp) 23 | target_link_libraries(osmium_toogr2_exp ${OSMIUM_LIBRARIES}) 24 | set_pthread_on_target(osmium_toogr2_exp) 25 | install(TARGETS osmium_toogr2_exp DESTINATION bin) 26 | 27 | -------------------------------------------------------------------------------- /src/osm_gis_export_overview.cpp: -------------------------------------------------------------------------------- 1 | 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #include 9 | 10 | #include 11 | 12 | #include 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include // IWYU pragma: keep 19 | #include // IWYU pragma: keep 20 | #include 21 | #include 22 | #include 23 | 24 | using index_type = osmium::index::map::FlexMem; 25 | using location_handler_type = osmium::handler::NodeLocationsForWays; 26 | 27 | struct config { 28 | bool add_untagged_nodes = false; 29 | bool add_metadata = false; 30 | bool verbose = false; 31 | }; 32 | 33 | template 34 | class MyOGRHandler : public osmium::handler::Handler { 35 | 36 | static const std::size_t max_length_tags = 200; 37 | 38 | config m_cfg; 39 | 40 | gdalcpp::Dataset& m_dataset; 41 | gdalcpp::Layer m_layer_point; 42 | gdalcpp::Layer m_layer_linestring; 43 | gdalcpp::Layer m_layer_multipolygon; 44 | 45 | osmium::geom::OGRFactory& m_factory; 46 | 47 | void add_metadata_fields(gdalcpp::Layer& layer) { 48 | layer.add_field("version", OFTInteger, 7); 49 | layer.add_field("changeset", OFTInteger, 7); 50 | layer.add_field("timestamp", OFTString, 20); 51 | layer.add_field("uid", OFTInteger, 7); 52 | layer.add_field("user", OFTString, 256); 53 | } 54 | 55 | static void add_metadata(gdalcpp::Feature& feature, const osmium::OSMObject& object) { 56 | feature.set_field("version", int32_t(object.version())); 57 | feature.set_field("changeset", int32_t(object.changeset())); 58 | feature.set_field("timestamp", object.timestamp().to_iso().c_str()); 59 | feature.set_field("uid", int32_t(object.uid())); 60 | feature.set_field("user", object.user()); 61 | } 62 | 63 | static void add_tags(gdalcpp::Feature& feature, const osmium::OSMObject& object) { 64 | std::string tags; 65 | for (const auto& tag : object.tags()) { 66 | tags += tag.key(); 67 | tags += "="; 68 | tags += tag.value(); 69 | tags += ","; 70 | } 71 | if (!tags.empty()) { 72 | tags.pop_back(); 73 | } 74 | feature.set_field("tags", tags.c_str()); 75 | } 76 | 77 | void add_feature(gdalcpp::Feature& feature, const osmium::OSMObject& object) { 78 | if (m_cfg.add_metadata) { 79 | add_metadata(feature, object); 80 | } 81 | add_tags(feature, object); 82 | feature.add_to_layer(); 83 | } 84 | 85 | public: 86 | 87 | MyOGRHandler(gdalcpp::Dataset& dataset, osmium::geom::OGRFactory& factory, const config& cfg) : 88 | m_cfg(cfg), 89 | m_dataset(dataset), 90 | m_layer_point(dataset, "points", wkbPoint, {"SPATIAL_INDEX=NO"}), 91 | m_layer_linestring(dataset, "lines", wkbLineString, {"SPATIAL_INDEX=NO"}), 92 | m_layer_multipolygon(dataset, "areas", wkbMultiPolygon, {"SPATIAL_INDEX=NO"}), 93 | m_factory(factory) { 94 | 95 | m_layer_point.add_field("id", OFTReal, 10); 96 | m_layer_linestring.add_field("id", OFTInteger, 7); 97 | m_layer_multipolygon.add_field("id", OFTInteger, 7); 98 | 99 | m_layer_point.add_field("tags", OFTString, max_length_tags); 100 | m_layer_linestring.add_field("tags", OFTString, max_length_tags); 101 | m_layer_multipolygon.add_field("tags", OFTString, max_length_tags); 102 | 103 | if (m_cfg.add_metadata) { 104 | add_metadata_fields(m_layer_point); 105 | add_metadata_fields(m_layer_linestring); 106 | add_metadata_fields(m_layer_multipolygon); 107 | } 108 | } 109 | 110 | void node(const osmium::Node& node) { 111 | if (m_cfg.add_untagged_nodes || !node.tags().empty()) { 112 | gdalcpp::Feature feature{m_layer_point, m_factory.create_point(node)}; 113 | feature.set_field("id", double(node.id())); 114 | add_feature(feature, node); 115 | } 116 | } 117 | 118 | void way(const osmium::Way& way) { 119 | try { 120 | gdalcpp::Feature feature{m_layer_linestring, m_factory.create_linestring(way)}; 121 | feature.set_field("id", int32_t(way.id())); 122 | add_feature(feature, way); 123 | } catch (const osmium::geometry_error&) { 124 | std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; 125 | } 126 | } 127 | 128 | void area(const osmium::Area& area) { 129 | try { 130 | gdalcpp::Feature feature{m_layer_multipolygon, m_factory.create_multipolygon(area)}; 131 | feature.set_field("id", int32_t(area.id())); 132 | add_feature(feature, area); 133 | } catch (const osmium::geometry_error&) { 134 | std::cerr << "Ignoring illegal geometry for area " 135 | << area.id() 136 | << " created from " 137 | << (area.from_way() ? "way" : "relation") 138 | << " with id=" 139 | << area.orig_id() << ".\n"; 140 | } 141 | } 142 | 143 | }; 144 | 145 | /* ================================================== */ 146 | 147 | namespace po = boost::program_options; 148 | 149 | void print_help(const po::options_description& desc) { 150 | std::cout << "osm_gis_export_overview [OPTIONS] OSM-FILE\n\n" 151 | << "If OSM-FILE is not used, stdin is assumed.\n\n" 152 | << desc << "\n"; 153 | } 154 | 155 | int main(int argc, char* argv[]) { 156 | try { 157 | po::options_description desc("OPTIONS"); 158 | desc.add_options() 159 | ("help,h", "Print usage information") 160 | ("verbose,v", "Enable verbose output") 161 | ("output,o", po::value(), "Output file name") 162 | ("output-format,f", po::value()->default_value("SQLite"), "Output OGR format (Default: 'SQLite')") 163 | ("add-untagged-nodes", "Add untagged nodes to point layer") 164 | ("add-metadata", "Add columns for version, changeset, timestamp, uid, and user") 165 | ("features-per-transaction", po::value()->default_value(100000), "Number of features to add per transaction") 166 | ; 167 | 168 | po::options_description hidden; 169 | hidden.add_options() 170 | ("input-filename", po::value(), "OSM input file") 171 | ; 172 | 173 | po::options_description parsed_options; 174 | parsed_options.add(desc).add(hidden); 175 | 176 | po::positional_options_description positional; 177 | positional.add("input-filename", 1); 178 | 179 | po::variables_map vm; 180 | po::store(po::command_line_parser(argc, argv).options(parsed_options).positional(positional).run(), vm); 181 | po::notify(vm); 182 | 183 | std::string input_filename; 184 | std::string output_filename; 185 | std::string output_format{"SQLite"}; 186 | bool debug = false; 187 | 188 | config cfg; 189 | 190 | if (vm.count("help")) { 191 | print_help(desc); 192 | return 0; 193 | } 194 | 195 | if (vm.count("verbose")) { 196 | cfg.verbose = true; 197 | } 198 | 199 | if (vm.count("output-format")) { 200 | output_format = vm["output-format"].as(); 201 | } 202 | 203 | if (vm.count("input-filename")) { 204 | input_filename = vm["input-filename"].as(); 205 | } 206 | 207 | if (vm.count("output")) { 208 | output_filename = vm["output"].as(); 209 | } else { 210 | auto slash = input_filename.rfind('/'); 211 | if (slash == std::string::npos) { 212 | slash = 0; 213 | } else { 214 | ++slash; 215 | } 216 | output_filename = input_filename.substr(slash); 217 | auto dot = output_filename.find('.'); 218 | if (dot != std::string::npos) { 219 | output_filename.erase(dot); 220 | } 221 | output_filename.append(".db"); 222 | } 223 | 224 | int features_per_transaction = 0; 225 | if (vm.count("features-per-transaction")) { 226 | features_per_transaction = vm["features-per-transaction"].as(); 227 | } 228 | 229 | if (vm.count("add-untagged-nodes")) { 230 | cfg.add_untagged_nodes = true; 231 | } 232 | 233 | if (vm.count("add-metadata")) { 234 | cfg.add_metadata = true; 235 | } 236 | 237 | osmium::util::VerboseOutput vout{cfg.verbose}; 238 | vout << "Writing to '" << output_filename << "'\n"; 239 | 240 | osmium::io::File input_file{input_filename}; 241 | 242 | osmium::area::Assembler::config_type assembler_config; 243 | if (debug) { 244 | assembler_config.debug_level = 1; 245 | } 246 | osmium::area::MultipolygonManager mp_manager{assembler_config}; 247 | 248 | vout << "Pass 1...\n"; 249 | osmium::relations::read_relations(input_file, mp_manager); 250 | vout << "Pass 1 done\n"; 251 | 252 | index_type index_pos; 253 | location_handler_type location_handler{index_pos}; 254 | location_handler.ignore_errors(); 255 | 256 | osmium::geom::OGRFactory<> factory {}; 257 | 258 | CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF"); 259 | gdalcpp::Dataset dataset{output_format, output_filename, gdalcpp::SRS{factory.proj_string()}, { "SPATIALITE=TRUE", "INIT_WITH_EPSG=no" }}; 260 | dataset.exec("PRAGMA journal_mode = OFF;"); 261 | if (features_per_transaction) { 262 | dataset.enable_auto_transactions(features_per_transaction); 263 | } 264 | 265 | MyOGRHandler ogr_handler(dataset, factory, cfg); 266 | 267 | vout << "Pass 2...\n"; 268 | osmium::io::Reader reader{input_file}; 269 | 270 | osmium::apply(reader, location_handler, ogr_handler, mp_manager.handler([&ogr_handler](const osmium::memory::Buffer& area_buffer) { 271 | osmium::apply(area_buffer, ogr_handler); 272 | })); 273 | 274 | reader.close(); 275 | vout << "Pass 2 done\n"; 276 | 277 | std::vector incomplete_relations_ids; 278 | mp_manager.for_each_incomplete_relation([&](const osmium::relations::RelationHandle& handle){ 279 | incomplete_relations_ids.push_back(handle->id()); 280 | }); 281 | if (!incomplete_relations_ids.empty()) { 282 | std::cerr << "Warning! Some member ways missing for these multipolygon relations:"; 283 | for (const auto id : incomplete_relations_ids) { 284 | std::cerr << " " << id; 285 | } 286 | std::cerr << "\n"; 287 | } 288 | 289 | osmium::MemoryUsage memory; 290 | if (memory.peak()) { 291 | vout << "Memory used: " << memory.peak() << " MBytes\n"; 292 | } 293 | } catch (const std::exception& e) { 294 | std::cerr << "Error: " << e.what() << '\n'; 295 | return 1; 296 | } 297 | 298 | return 0; 299 | } 300 | 301 | -------------------------------------------------------------------------------- /src/osmium_toogr.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an example tool that converts OSM data to some output format 4 | like Spatialite or Shapefiles using the OGR library. 5 | 6 | */ 7 | 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | #include // IWYU pragma: keep 14 | #include // IWYU pragma: keep 15 | #include 16 | 17 | #include 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include 26 | 27 | #ifndef _MSC_VER 28 | # include 29 | #endif 30 | 31 | using index_type = osmium::index::map::Map; 32 | using location_handler_type = osmium::handler::NodeLocationsForWays; 33 | 34 | class MyOGRHandler : public osmium::handler::Handler { 35 | 36 | gdalcpp::Layer m_layer_point; 37 | gdalcpp::Layer m_layer_linestring; 38 | 39 | osmium::geom::OGRFactory<> m_factory; 40 | 41 | public: 42 | 43 | explicit MyOGRHandler(gdalcpp::Dataset& dataset) : 44 | m_layer_point(dataset, "postboxes", wkbPoint), 45 | m_layer_linestring(dataset, "roads", wkbLineString) { 46 | 47 | m_layer_point.add_field("id", OFTReal, 10); 48 | m_layer_point.add_field("operator", OFTString, 30); 49 | 50 | m_layer_linestring.add_field("id", OFTReal, 10); 51 | m_layer_linestring.add_field("type", OFTString, 30); 52 | } 53 | 54 | void node(const osmium::Node& node) { 55 | const char* amenity = node.tags().get_value_by_key("amenity"); 56 | if (amenity && !std::strcmp(amenity, "post_box")) { 57 | gdalcpp::Feature feature{m_layer_point, m_factory.create_point(node)}; 58 | feature.set_field("id", static_cast(node.id())); 59 | feature.set_field("operator", node.tags().get_value_by_key("operator")); 60 | feature.add_to_layer(); 61 | } 62 | } 63 | 64 | void way(const osmium::Way& way) { 65 | const char* highway = way.tags().get_value_by_key("highway"); 66 | if (highway) { 67 | try { 68 | gdalcpp::Feature feature{m_layer_linestring, m_factory.create_linestring(way)}; 69 | feature.set_field("id", static_cast(way.id())); 70 | feature.set_field("type", highway); 71 | feature.add_to_layer(); 72 | } catch (const osmium::geometry_error&) { 73 | std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; 74 | } 75 | } 76 | } 77 | 78 | }; 79 | 80 | /* ================================================== */ 81 | 82 | void print_help() { 83 | std::cout << "osmium_toogr [OPTIONS] [INFILE [OUTFILE]]\n\n" \ 84 | << "If INFILE is not given stdin is assumed.\n" \ 85 | << "If OUTFILE is not given 'ogr_out' is used.\n" \ 86 | << "\nOptions:\n" \ 87 | << " -h, --help This help message\n" \ 88 | << " -l, --location_store=TYPE Set location store\n" \ 89 | << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n" \ 90 | << " -L See available location stores\n"; 91 | } 92 | 93 | int main(int argc, char* argv[]) { 94 | try { 95 | const auto& map_factory = osmium::index::MapFactory::instance(); 96 | 97 | static struct option long_options[] = { 98 | {"help", no_argument, nullptr, 'h'}, 99 | {"format", required_argument, nullptr, 'f'}, 100 | {"location_store", required_argument, nullptr, 'l'}, 101 | {"list_location_stores", no_argument, nullptr, 'L'}, 102 | {nullptr, 0, nullptr, 0} 103 | }; 104 | 105 | std::string output_format{"SQLite"}; 106 | std::string location_store{"flex_mem"}; 107 | 108 | while (true) { 109 | const int c = getopt_long(argc, argv, "hf:l:L", long_options, nullptr); 110 | if (c == -1) { 111 | break; 112 | } 113 | 114 | switch (c) { 115 | case 'h': 116 | print_help(); 117 | return 0; 118 | case 'f': 119 | output_format = optarg; 120 | break; 121 | case 'l': 122 | location_store = optarg; 123 | break; 124 | case 'L': 125 | std::cout << "Available map types:\n"; 126 | for (const auto& map_type : map_factory.map_types()) { 127 | std::cout << " " << map_type << "\n"; 128 | } 129 | return 0; 130 | default: 131 | return 1; 132 | } 133 | } 134 | 135 | std::string input_filename; 136 | std::string output_filename{"ogr_out"}; 137 | const int remaining_args = argc - optind; 138 | if (remaining_args > 2) { 139 | std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n"; 140 | return 1; 141 | } 142 | 143 | if (remaining_args == 2) { 144 | input_filename = argv[optind]; 145 | output_filename = argv[optind+1]; 146 | } else if (remaining_args == 1) { 147 | input_filename = argv[optind]; 148 | } else { 149 | input_filename = "-"; 150 | } 151 | 152 | osmium::io::Reader reader{input_filename}; 153 | 154 | std::unique_ptr index = map_factory.create_map(location_store); 155 | location_handler_type location_handler{*index}; 156 | location_handler.ignore_errors(); 157 | 158 | CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF"); 159 | gdalcpp::Dataset dataset{output_format, output_filename, gdalcpp::SRS{}, { "SPATIALITE=TRUE", "INIT_WITH_EPSG=no" }}; 160 | MyOGRHandler ogr_handler{dataset}; 161 | 162 | osmium::apply(reader, location_handler, ogr_handler); 163 | reader.close(); 164 | 165 | /* 166 | const int locations_fd = ::open("locations.dump", O_WRONLY | O_CREAT, 0644); 167 | if (locations_fd < 0) { 168 | throw std::system_error{errno, std::system_category(), "Open failed"}; 169 | } 170 | index->dump_as_list(locations_fd); 171 | ::close(locations_fd); 172 | */ 173 | } catch (const std::exception& e) { 174 | std::cerr << "Error: " << e.what() << '\n'; 175 | return 1; 176 | } 177 | 178 | return 0; 179 | } 180 | 181 | -------------------------------------------------------------------------------- /src/osmium_toogr2.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an example tool that converts OSM data to some output format 4 | like Spatialite or Shapefiles using the OGR library. 5 | 6 | This version does multipolygon handling (in contrast to the osmium_toogr 7 | example which doesn't). 8 | 9 | */ 10 | 11 | #include 12 | 13 | #include 14 | #include 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include // IWYU pragma: keep 20 | #include // IWYU pragma: keep 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | using index_type = osmium::index::map::FlexMem; 33 | using location_handler_type = osmium::handler::NodeLocationsForWays; 34 | 35 | template 36 | class MyOGRHandler : public osmium::handler::Handler { 37 | 38 | gdalcpp::Layer m_layer_point; 39 | gdalcpp::Layer m_layer_linestring; 40 | gdalcpp::Layer m_layer_polygon; 41 | 42 | osmium::geom::OGRFactory& m_factory; 43 | 44 | public: 45 | 46 | MyOGRHandler(gdalcpp::Dataset& dataset, osmium::geom::OGRFactory& factory) : 47 | m_layer_point(dataset, "postboxes", wkbPoint), 48 | m_layer_linestring(dataset, "roads", wkbLineString), 49 | m_layer_polygon(dataset, "buildings", wkbMultiPolygon), 50 | m_factory(factory) { 51 | 52 | m_layer_point.add_field("id", OFTReal, 10); 53 | m_layer_point.add_field("operator", OFTString, 30); 54 | 55 | m_layer_linestring.add_field("id", OFTReal, 10); 56 | m_layer_linestring.add_field("type", OFTString, 30); 57 | 58 | m_layer_polygon.add_field("id", OFTReal, 10); 59 | m_layer_polygon.add_field("type", OFTString, 30); 60 | } 61 | 62 | void node(const osmium::Node& node) { 63 | const char* amenity = node.tags()["amenity"]; 64 | if (amenity && !std::strcmp(amenity, "post_box")) { 65 | gdalcpp::Feature feature{m_layer_point, m_factory.create_point(node)}; 66 | feature.set_field("id", static_cast(node.id())); 67 | feature.set_field("operator", node.tags().get_value_by_key("operator")); 68 | feature.add_to_layer(); 69 | } 70 | } 71 | 72 | void way(const osmium::Way& way) { 73 | const char* highway = way.tags()["highway"]; 74 | if (highway) { 75 | try { 76 | gdalcpp::Feature feature{m_layer_linestring, m_factory.create_linestring(way)}; 77 | feature.set_field("id", static_cast(way.id())); 78 | feature.set_field("type", highway); 79 | feature.add_to_layer(); 80 | } catch (const osmium::geometry_error&) { 81 | std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; 82 | } 83 | } 84 | } 85 | 86 | void area(const osmium::Area& area) { 87 | const char* building = area.tags()["building"]; 88 | if (building) { 89 | try { 90 | gdalcpp::Feature feature{m_layer_polygon, m_factory.create_multipolygon(area)}; 91 | feature.set_field("id", static_cast(area.id())); 92 | feature.set_field("type", building); 93 | feature.add_to_layer(); 94 | } catch (const osmium::geometry_error&) { 95 | std::cerr << "Ignoring illegal geometry for area " 96 | << area.id() 97 | << " created from " 98 | << (area.from_way() ? "way" : "relation") 99 | << " with id=" 100 | << area.orig_id() << ".\n"; 101 | } 102 | } 103 | } 104 | 105 | }; 106 | 107 | /* ================================================== */ 108 | 109 | void print_help() { 110 | std::cout << "osmium_toogr2 [OPTIONS] [INFILE [OUTFILE]]\n\n" \ 111 | << "If INFILE is not given stdin is assumed.\n" \ 112 | << "If OUTFILE is not given 'ogr_out' is used.\n" \ 113 | << "\nOptions:\n" \ 114 | << " -h, --help This help message\n" \ 115 | << " -d, --debug Enable debug output\n" \ 116 | << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n"; 117 | } 118 | 119 | int main(int argc, char* argv[]) { 120 | try { 121 | static struct option long_options[] = { 122 | {"help", no_argument, nullptr, 'h'}, 123 | {"debug", no_argument, nullptr, 'd'}, 124 | {"format", required_argument, nullptr, 'f'}, 125 | {nullptr, 0, nullptr, 0} 126 | }; 127 | 128 | std::string output_format{"SQLite"}; 129 | bool debug = false; 130 | 131 | while (true) { 132 | const int c = getopt_long(argc, argv, "hdf:", long_options, nullptr); 133 | if (c == -1) { 134 | break; 135 | } 136 | 137 | switch (c) { 138 | case 'h': 139 | print_help(); 140 | return 0; 141 | case 'd': 142 | debug = true; 143 | break; 144 | case 'f': 145 | output_format = optarg; 146 | break; 147 | default: 148 | return 1; 149 | } 150 | } 151 | 152 | std::string input_filename; 153 | std::string output_filename{"ogr_out"}; 154 | const int remaining_args = argc - optind; 155 | if (remaining_args > 2) { 156 | std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n"; 157 | return 1; 158 | } 159 | 160 | if (remaining_args == 2) { 161 | input_filename = argv[optind]; 162 | output_filename = argv[optind+1]; 163 | } else if (remaining_args == 1) { 164 | input_filename = argv[optind]; 165 | } else { 166 | input_filename = "-"; 167 | } 168 | 169 | osmium::io::File input_file{input_filename}; 170 | 171 | osmium::area::Assembler::config_type assembler_config; 172 | if (debug) { 173 | assembler_config.debug_level = 1; 174 | } 175 | osmium::area::MultipolygonManager mp_manager{assembler_config}; 176 | 177 | std::cerr << "Pass 1...\n"; 178 | osmium::relations::read_relations(input_file, mp_manager); 179 | std::cerr << "Pass 1 done\n"; 180 | 181 | index_type index; 182 | location_handler_type location_handler{index}; 183 | location_handler.ignore_errors(); 184 | 185 | // Choose one of the following: 186 | 187 | // 1. Use WGS84, do not project coordinates. 188 | //osmium::geom::OGRFactory<> factory {}; 189 | 190 | // 2. Project coordinates into "Web Mercator". 191 | osmium::geom::OGRFactory factory; 192 | 193 | CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF"); 194 | gdalcpp::Dataset dataset{output_format, output_filename, gdalcpp::SRS{factory.proj_string()}, { "SPATIALITE=TRUE", "INIT_WITH_EPSG=no" }}; 195 | MyOGRHandler ogr_handler{dataset, factory}; 196 | 197 | std::cerr << "Pass 2...\n"; 198 | osmium::io::Reader reader{input_file}; 199 | 200 | osmium::apply(reader, location_handler, ogr_handler, mp_manager.handler([&ogr_handler](const osmium::memory::Buffer& area_buffer) { 201 | osmium::apply(area_buffer, ogr_handler); 202 | })); 203 | 204 | reader.close(); 205 | std::cerr << "Pass 2 done\n"; 206 | 207 | std::vector incomplete_relations_ids; 208 | mp_manager.for_each_incomplete_relation([&](const osmium::relations::RelationHandle& handle){ 209 | incomplete_relations_ids.push_back(handle->id()); 210 | }); 211 | if (!incomplete_relations_ids.empty()) { 212 | std::cerr << "Warning! Some member ways missing for these multipolygon relations:"; 213 | for (const auto id : incomplete_relations_ids) { 214 | std::cerr << " " << id; 215 | } 216 | std::cerr << "\n"; 217 | } 218 | 219 | osmium::MemoryUsage memory; 220 | if (memory.peak()) { 221 | std::cerr << "Memory used: " << memory.peak() << " MBytes\n"; 222 | } 223 | } catch (const std::exception& e) { 224 | std::cerr << "Error: " << e.what() << '\n'; 225 | return 1; 226 | } 227 | 228 | return 0; 229 | } 230 | 231 | -------------------------------------------------------------------------------- /src/osmium_toogr2_exp.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | This is an example tool that converts OSM data to some output format 4 | like Spatialite or Shapefiles using the OGR library. 5 | 6 | This version does multipolygon handling (in contrast to the osmium_toogr 7 | example which doesn't). 8 | 9 | This version (..._exp) uses a new experimental unsupported interface. 10 | 11 | */ 12 | 13 | #include 14 | 15 | #include 16 | #include 17 | #include 18 | #include 19 | #include // IWYU pragma: keep 20 | #include // IWYU pragma: keep 21 | #include 22 | 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | 31 | using index_type = osmium::index::map::SparseMemArray; 32 | using location_handler_type = osmium::handler::NodeLocationsForWays; 33 | 34 | template 35 | class MyOGRHandler : public osmium::handler::Handler { 36 | 37 | gdalcpp::Layer m_layer_point; 38 | gdalcpp::Layer m_layer_linestring; 39 | gdalcpp::Layer m_layer_polygon; 40 | 41 | osmium::geom::OGRFactory& m_factory; 42 | 43 | public: 44 | 45 | MyOGRHandler(gdalcpp::Dataset& dataset, osmium::geom::OGRFactory& factory) : 46 | m_layer_point(dataset, "postboxes", wkbPoint), 47 | m_layer_linestring(dataset, "roads", wkbLineString), 48 | m_layer_polygon(dataset, "buildings", wkbMultiPolygon), 49 | m_factory(factory) { 50 | 51 | m_layer_point.add_field("id", OFTReal, 10); 52 | m_layer_point.add_field("operator", OFTString, 30); 53 | 54 | m_layer_linestring.add_field("id", OFTReal, 10); 55 | m_layer_linestring.add_field("type", OFTString, 30); 56 | 57 | m_layer_polygon.add_field("id", OFTReal, 10); 58 | m_layer_polygon.add_field("type", OFTString, 30); 59 | } 60 | 61 | void node(const osmium::Node& node) { 62 | const char* amenity = node.tags()["amenity"]; 63 | if (amenity && !std::strcmp(amenity, "post_box")) { 64 | gdalcpp::Feature feature{m_layer_point, m_factory.create_point(node)}; 65 | feature.set_field("id", static_cast(node.id())); 66 | feature.set_field("operator", node.tags().get_value_by_key("operator")); 67 | feature.add_to_layer(); 68 | } 69 | } 70 | 71 | void way(const osmium::Way& way) { 72 | const char* highway = way.tags()["highway"]; 73 | if (highway) { 74 | try { 75 | gdalcpp::Feature feature{m_layer_linestring, m_factory.create_linestring(way)}; 76 | feature.set_field("id", static_cast(way.id())); 77 | feature.set_field("type", highway); 78 | feature.add_to_layer(); 79 | } catch (const osmium::geometry_error&) { 80 | std::cerr << "Ignoring illegal geometry for way " << way.id() << ".\n"; 81 | } 82 | } 83 | } 84 | 85 | void area(const osmium::Area& area) { 86 | const char* building = area.tags()["building"]; 87 | if (building) { 88 | try { 89 | gdalcpp::Feature feature{m_layer_polygon, m_factory.create_multipolygon(area)}; 90 | feature.set_field("id", static_cast(area.id())); 91 | feature.set_field("type", building); 92 | feature.add_to_layer(); 93 | } catch (const osmium::geometry_error&) { 94 | std::cerr << "Ignoring illegal geometry for area " 95 | << area.id() 96 | << " created from " 97 | << (area.from_way() ? "way" : "relation") 98 | << " with id=" 99 | << area.orig_id() << ".\n"; 100 | } 101 | } 102 | } 103 | 104 | }; 105 | 106 | /* ================================================== */ 107 | 108 | void print_help() { 109 | std::cout << "osmium_toogr2_exp [OPTIONS] [INFILE [OUTFILE]]\n\n" \ 110 | << "If INFILE is not given stdin is assumed.\n" \ 111 | << "If OUTFILE is not given 'ogr_out' is used.\n" \ 112 | << "\nOptions:\n" \ 113 | << " -h, --help This help message\n" \ 114 | << " -f, --format=FORMAT Output OGR format (Default: 'SQLite')\n"; 115 | } 116 | 117 | int main(int argc, char* argv[]) { 118 | try { 119 | static struct option long_options[] = { 120 | {"help", no_argument, nullptr, 'h'}, 121 | {"format", required_argument, nullptr, 'f'}, 122 | {nullptr, 0, nullptr, 0} 123 | }; 124 | 125 | std::string output_format{"SQLite"}; 126 | 127 | while (true) { 128 | const int c = getopt_long(argc, argv, "hf:", long_options, nullptr); 129 | if (c == -1) { 130 | break; 131 | } 132 | 133 | switch (c) { 134 | case 'h': 135 | print_help(); 136 | return 0; 137 | case 'f': 138 | output_format = optarg; 139 | break; 140 | default: 141 | return 1; 142 | } 143 | } 144 | 145 | std::string input_filename; 146 | std::string output_filename{"ogr_out"}; 147 | const int remaining_args = argc - optind; 148 | if (remaining_args > 2) { 149 | std::cerr << "Usage: " << argv[0] << " [OPTIONS] [INFILE [OUTFILE]]\n"; 150 | return 1; 151 | } 152 | 153 | if (remaining_args == 2) { 154 | input_filename = argv[optind]; 155 | output_filename = argv[optind+1]; 156 | } else if (remaining_args == 1) { 157 | input_filename = argv[optind]; 158 | } else { 159 | input_filename = "-"; 160 | } 161 | 162 | index_type index; 163 | location_handler_type location_handler{index}; 164 | osmium::experimental::FlexReader exr{input_filename, location_handler, osmium::osm_entity_bits::object}; 165 | 166 | // Choose one of the following: 167 | 168 | // 1. Use WGS84, do not project coordinates. 169 | //osmium::geom::OGRFactory<> factory {}; 170 | 171 | // 2. Project coordinates into "Web Mercator". 172 | osmium::geom::OGRFactory factory; 173 | 174 | CPLSetConfigOption("OGR_SQLITE_SYNCHRONOUS", "OFF"); 175 | gdalcpp::Dataset dataset{output_format, output_filename, gdalcpp::SRS{factory.proj_string()}, { "SPATIALITE=TRUE", "INIT_WITH_EPSG=no" }}; 176 | MyOGRHandler ogr_handler{dataset, factory}; 177 | 178 | while (auto buffer = exr.read()) { 179 | osmium::apply(buffer, ogr_handler); 180 | } 181 | 182 | exr.close(); 183 | 184 | std::vector incomplete_relations = exr.collector().get_incomplete_relations(); 185 | if (!incomplete_relations.empty()) { 186 | std::cerr << "Warning! Some member ways missing for these multipolygon relations:"; 187 | for (const auto* relation : incomplete_relations) { 188 | std::cerr << " " << relation->id(); 189 | } 190 | std::cerr << "\n"; 191 | } 192 | } catch (const std::exception& e) { 193 | std::cerr << "Error: " << e.what() << '\n'; 194 | return 1; 195 | } 196 | 197 | return 0; 198 | } 199 | 200 | --------------------------------------------------------------------------------