Merge fe13982f10 into 69dc466605
This commit is contained in:
commit
49ae9c50d2
17 changed files with 2592 additions and 1431 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -4,6 +4,7 @@ CMakeCache.txt
|
|||
*.a
|
||||
cmake_install.cmake
|
||||
*~
|
||||
cmake-build-*
|
||||
CMakeFiles
|
||||
*.cfg
|
||||
*.cmake
|
||||
|
|
|
|||
11
.travis.yml
11
.travis.yml
|
|
@ -1,9 +1,12 @@
|
|||
language: cpp
|
||||
|
||||
sudo: true
|
||||
os:
|
||||
- linux
|
||||
- osx
|
||||
|
||||
dist: bionic
|
||||
osx_image: xcode12
|
||||
|
||||
compiler:
|
||||
- gcc
|
||||
- clang
|
||||
|
|
@ -14,9 +17,15 @@ addons:
|
|||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- cmake
|
||||
- libosmium2-dev
|
||||
homebrew:
|
||||
packages:
|
||||
- libosmium
|
||||
- boost
|
||||
|
||||
before_install:
|
||||
- export LD_LIBRARY_PATH=$(if [[ $CXX == "clang++" ]]; then echo -n '/usr/local/clang/lib'; fi)
|
||||
- git clone https://github.com/mapbox/protozero.git && cd protozero && cmake . -DINSTALL_GDALCPP=ON -DINSTALL_UTFCPP=ON && sudo make -j4 install && cd ..
|
||||
|
||||
before_script:
|
||||
- mkdir build
|
||||
|
|
|
|||
|
|
@ -17,6 +17,7 @@ enable_testing()
|
|||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/")
|
||||
set(EXECUTABLE_OUTPUT_PATH "${CMAKE_SOURCE_DIR}/build")
|
||||
|
||||
find_package(Osmium REQUIRED COMPONENTS pbf xml io)
|
||||
|
||||
find_package(OpenMP)
|
||||
if (OPENMP_FOUND)
|
||||
|
|
|
|||
357
cmake/FindOsmium.cmake
Normal file
357
cmake/FindOsmium.cmake
Normal file
|
|
@ -0,0 +1,357 @@
|
|||
#----------------------------------------------------------------------
|
||||
#
|
||||
# FindOsmium.cmake
|
||||
#
|
||||
# Find the Libosmium headers and, optionally, several components needed
|
||||
# for different Libosmium functions.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# Copy this file somewhere into your project directory, where cmake can
|
||||
# find it. Usually this will be a directory called "cmake" which you can
|
||||
# add to the CMake module search path with the following line in your
|
||||
# CMakeLists.txt:
|
||||
#
|
||||
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
#
|
||||
# Then add the following in your CMakeLists.txt:
|
||||
#
|
||||
# find_package(Osmium [version] REQUIRED COMPONENTS <XXX>)
|
||||
# include_directories(SYSTEM ${OSMIUM_INCLUDE_DIRS})
|
||||
#
|
||||
# The version number is optional. If it is not set, any version of
|
||||
# libosmium will do.
|
||||
#
|
||||
# For the <XXX> substitute a space separated list of one or more of the
|
||||
# following components:
|
||||
#
|
||||
# pbf - include libraries needed for PBF input and output
|
||||
# xml - include libraries needed for XML input and output
|
||||
# io - include libraries needed for any type of input/output
|
||||
# geos - include if you want to use any of the GEOS functions
|
||||
# gdal - include if you want to use any of the OGR functions
|
||||
# proj - include if you want to use any of the Proj.4 functions
|
||||
# sparsehash - include if you use the sparsehash index
|
||||
#
|
||||
# You can check for success with something like this:
|
||||
#
|
||||
# if(NOT OSMIUM_FOUND)
|
||||
# message(WARNING "Libosmium not found!\n")
|
||||
# endif()
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Variables:
|
||||
#
|
||||
# OSMIUM_FOUND - True if Osmium found.
|
||||
# OSMIUM_INCLUDE_DIRS - Where to find include files.
|
||||
# OSMIUM_XML_LIBRARIES - Libraries needed for XML I/O.
|
||||
# OSMIUM_PBF_LIBRARIES - Libraries needed for PBF I/O.
|
||||
# OSMIUM_IO_LIBRARIES - Libraries needed for XML or PBF I/O.
|
||||
# OSMIUM_LIBRARIES - All libraries Osmium uses somewhere.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# This is the list of directories where we look for osmium includes.
|
||||
set(_osmium_include_path
|
||||
../libosmium
|
||||
~/Library/Frameworks
|
||||
/Library/Frameworks
|
||||
/opt/local # DarwinPorts
|
||||
/opt
|
||||
)
|
||||
|
||||
# Look for the header file.
|
||||
find_path(OSMIUM_INCLUDE_DIR osmium/version.hpp
|
||||
PATH_SUFFIXES include
|
||||
PATHS ${_osmium_include_path}
|
||||
)
|
||||
|
||||
# Check libosmium version number
|
||||
if(Osmium_FIND_VERSION)
|
||||
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")
|
||||
if("${_libosmium_version_define}" MATCHES "#define LIBOSMIUM_VERSION_STRING \"([0-9.]+)\"")
|
||||
set(_libosmium_version "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
set(_libosmium_version "unknown")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set(OSMIUM_INCLUDE_DIRS "${OSMIUM_INCLUDE_DIR}")
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Check for optional components
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
if(Osmium_FIND_COMPONENTS)
|
||||
foreach(_component ${Osmium_FIND_COMPONENTS})
|
||||
string(TOUPPER ${_component} _component_uppercase)
|
||||
set(Osmium_USE_${_component_uppercase} TRUE)
|
||||
endforeach()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'io' is an alias for 'pbf' and 'xml'
|
||||
if(Osmium_USE_IO)
|
||||
set(Osmium_USE_PBF TRUE)
|
||||
set(Osmium_USE_XML TRUE)
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'ogr' is an alias for 'gdal'
|
||||
if(Osmium_USE_OGR)
|
||||
set(Osmium_USE_GDAL TRUE)
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'pbf'
|
||||
if(Osmium_USE_PBF)
|
||||
find_package(ZLIB)
|
||||
find_package(Threads)
|
||||
find_package(Protozero 1.6.3)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS ZLIB_FOUND Threads_FOUND PROTOZERO_INCLUDE_DIR)
|
||||
if(ZLIB_FOUND AND Threads_FOUND AND PROTOZERO_FOUND)
|
||||
list(APPEND OSMIUM_PBF_LIBRARIES
|
||||
${ZLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
${PROTOZERO_INCLUDE_DIR}
|
||||
)
|
||||
else()
|
||||
message(WARNING "Osmium: Can not find some libraries for PBF input/output, please install them or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'xml'
|
||||
if(Osmium_USE_XML)
|
||||
find_package(EXPAT)
|
||||
find_package(BZip2)
|
||||
find_package(ZLIB)
|
||||
find_package(Threads)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS EXPAT_FOUND BZIP2_FOUND ZLIB_FOUND Threads_FOUND)
|
||||
if(EXPAT_FOUND AND BZIP2_FOUND AND ZLIB_FOUND AND Threads_FOUND)
|
||||
list(APPEND OSMIUM_XML_LIBRARIES
|
||||
${EXPAT_LIBRARIES}
|
||||
${BZIP2_LIBRARIES}
|
||||
${ZLIB_LIBRARIES}
|
||||
${CMAKE_THREAD_LIBS_INIT}
|
||||
)
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS
|
||||
${EXPAT_INCLUDE_DIR}
|
||||
${BZIP2_INCLUDE_DIR}
|
||||
${ZLIB_INCLUDE_DIR}
|
||||
)
|
||||
else()
|
||||
message(WARNING "Osmium: Can not find some libraries for XML input/output, please install them or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
list(APPEND OSMIUM_IO_LIBRARIES
|
||||
${OSMIUM_PBF_LIBRARIES}
|
||||
${OSMIUM_XML_LIBRARIES}
|
||||
)
|
||||
|
||||
list(APPEND OSMIUM_LIBRARIES
|
||||
${OSMIUM_IO_LIBRARIES}
|
||||
)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'geos'
|
||||
if(Osmium_USE_GEOS)
|
||||
find_path(GEOS_INCLUDE_DIR geos/geom.h)
|
||||
find_library(GEOS_LIBRARY NAMES geos)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS GEOS_INCLUDE_DIR GEOS_LIBRARY)
|
||||
if(GEOS_INCLUDE_DIR AND GEOS_LIBRARY)
|
||||
SET(GEOS_FOUND 1)
|
||||
list(APPEND OSMIUM_LIBRARIES ${GEOS_LIBRARY})
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS ${GEOS_INCLUDE_DIR})
|
||||
else()
|
||||
message(WARNING "Osmium: GEOS library is required but not found, please install it or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'gdal' (alias 'ogr')
|
||||
if(Osmium_USE_GDAL)
|
||||
find_package(GDAL)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS GDAL_FOUND)
|
||||
if(GDAL_FOUND)
|
||||
list(APPEND OSMIUM_LIBRARIES ${GDAL_LIBRARIES})
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS ${GDAL_INCLUDE_DIRS})
|
||||
else()
|
||||
message(WARNING "Osmium: GDAL library is required but not found, please install it or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'proj'
|
||||
if(Osmium_USE_PROJ)
|
||||
find_path(PROJ_INCLUDE_DIR proj_api.h)
|
||||
find_library(PROJ_LIBRARY NAMES proj)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS PROJ_INCLUDE_DIR PROJ_LIBRARY)
|
||||
if(PROJ_INCLUDE_DIR AND PROJ_LIBRARY)
|
||||
set(PROJ_FOUND 1)
|
||||
list(APPEND OSMIUM_LIBRARIES ${PROJ_LIBRARY})
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS ${PROJ_INCLUDE_DIR})
|
||||
else()
|
||||
message(WARNING "Osmium: PROJ.4 library is required but not found, please install it or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
# Component 'sparsehash'
|
||||
if(Osmium_USE_SPARSEHASH)
|
||||
find_path(SPARSEHASH_INCLUDE_DIR google/sparsetable)
|
||||
|
||||
list(APPEND OSMIUM_EXTRA_FIND_VARS SPARSEHASH_INCLUDE_DIR)
|
||||
if(SPARSEHASH_INCLUDE_DIR)
|
||||
# Find size of sparsetable::size_type. This does not work on older
|
||||
# CMake versions because they can do this check only in C, not in C++.
|
||||
if(NOT CMAKE_VERSION VERSION_LESS 3.0)
|
||||
include(CheckTypeSize)
|
||||
set(CMAKE_REQUIRED_INCLUDES ${SPARSEHASH_INCLUDE_DIR})
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES "google/sparsetable")
|
||||
check_type_size("google::sparsetable<int>::size_type" SPARSETABLE_SIZE_TYPE LANGUAGE CXX)
|
||||
set(CMAKE_EXTRA_INCLUDE_FILES)
|
||||
set(CMAKE_REQUIRED_INCLUDES)
|
||||
else()
|
||||
set(SPARSETABLE_SIZE_TYPE ${CMAKE_SIZEOF_VOID_P})
|
||||
endif()
|
||||
|
||||
# Sparsetable::size_type must be at least 8 bytes (64bit), otherwise
|
||||
# OSM object IDs will not fit.
|
||||
if(SPARSETABLE_SIZE_TYPE GREATER 7)
|
||||
set(SPARSEHASH_FOUND 1)
|
||||
add_definitions(-DOSMIUM_WITH_SPARSEHASH=${SPARSEHASH_FOUND})
|
||||
list(APPEND OSMIUM_INCLUDE_DIRS ${SPARSEHASH_INCLUDE_DIR})
|
||||
else()
|
||||
message(WARNING "Osmium: Disabled Google SparseHash library on 32bit system (size_type=${SPARSETABLE_SIZE_TYPE}).")
|
||||
endif()
|
||||
else()
|
||||
message(WARNING "Osmium: Google SparseHash library is required but not found, please install it or configure the paths.")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
list(REMOVE_DUPLICATES OSMIUM_INCLUDE_DIRS)
|
||||
|
||||
if(OSMIUM_XML_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES OSMIUM_XML_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if(OSMIUM_PBF_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES OSMIUM_PBF_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if(OSMIUM_IO_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES OSMIUM_IO_LIBRARIES)
|
||||
endif()
|
||||
|
||||
if(OSMIUM_LIBRARIES)
|
||||
list(REMOVE_DUPLICATES OSMIUM_LIBRARIES)
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Check that all required libraries are available
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
if(OSMIUM_EXTRA_FIND_VARS)
|
||||
list(REMOVE_DUPLICATES OSMIUM_EXTRA_FIND_VARS)
|
||||
endif()
|
||||
# Handle the QUIETLY and REQUIRED arguments and the optional version check
|
||||
# and set OSMIUM_FOUND to TRUE if all listed variables are TRUE.
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Osmium
|
||||
REQUIRED_VARS OSMIUM_INCLUDE_DIR ${OSMIUM_EXTRA_FIND_VARS}
|
||||
VERSION_VAR _libosmium_version)
|
||||
unset(OSMIUM_EXTRA_FIND_VARS)
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# A function for setting the -pthread option in compilers/linkers
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
function(set_pthread_on_target _target)
|
||||
if(NOT MSVC)
|
||||
set_target_properties(${_target} PROPERTIES COMPILE_FLAGS "-pthread")
|
||||
if(NOT APPLE)
|
||||
set_target_properties(${_target} PROPERTIES LINK_FLAGS "-pthread")
|
||||
endif()
|
||||
endif()
|
||||
endfunction()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Add compiler flags
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
add_definitions(-D_LARGEFILE_SOURCE -D_FILE_OFFSET_BITS=64)
|
||||
|
||||
if(MSVC)
|
||||
add_definitions(-wd4996)
|
||||
|
||||
# Disable warning C4068: "unknown pragma" because we want it to ignore
|
||||
# pragmas for other compilers.
|
||||
add_definitions(-wd4068)
|
||||
|
||||
# Disable warning C4715: "not all control paths return a value" because
|
||||
# it generates too many false positives.
|
||||
add_definitions(-wd4715)
|
||||
|
||||
# Disable warning C4351: new behavior: elements of array '...' will be
|
||||
# default initialized. The new behaviour is correct and we don't support
|
||||
# old compilers anyway.
|
||||
add_definitions(-wd4351)
|
||||
|
||||
# Disable warning C4503: "decorated name length exceeded, name was truncated"
|
||||
# there are more than 150 of generated names in libosmium longer than 4096 symbols supported in MSVC
|
||||
add_definitions(-wd4503)
|
||||
|
||||
add_definitions(-DNOMINMAX -DWIN32_LEAN_AND_MEAN -D_CRT_SECURE_NO_WARNINGS)
|
||||
endif()
|
||||
|
||||
if(APPLE AND "${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
# following only available from cmake 2.8.12:
|
||||
# add_compile_options(-stdlib=libc++)
|
||||
# so using this instead:
|
||||
add_definitions(-stdlib=libc++)
|
||||
set(LDFLAGS ${LDFLAGS} -stdlib=libc++)
|
||||
endif()
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# This is a set of recommended warning options that can be added when compiling
|
||||
# libosmium code.
|
||||
if(MSVC)
|
||||
set(OSMIUM_WARNING_OPTIONS "/W3 /wd4514" CACHE STRING "Recommended warning options for libosmium")
|
||||
else()
|
||||
set(OSMIUM_WARNING_OPTIONS "-Wall -Wextra -pedantic -Wredundant-decls -Wdisabled-optimization -Wctor-dtor-privacy -Wnon-virtual-dtor -Woverloaded-virtual -Wsign-promo -Wold-style-cast" CACHE STRING "Recommended warning options for libosmium")
|
||||
endif()
|
||||
|
||||
set(OSMIUM_DRACONIC_CLANG_OPTIONS "-Wdocumentation -Wunused-exception-parameter -Wmissing-declarations -Weverything -Wno-c++98-compat -Wno-c++98-compat-pedantic -Wno-unused-macros -Wno-exit-time-destructors -Wno-global-constructors -Wno-padded -Wno-switch-enum -Wno-missing-prototypes -Wno-weak-vtables -Wno-cast-align -Wno-float-equal")
|
||||
|
||||
if(Osmium_DEBUG)
|
||||
message(STATUS "OSMIUM_XML_LIBRARIES=${OSMIUM_XML_LIBRARIES}")
|
||||
message(STATUS "OSMIUM_PBF_LIBRARIES=${OSMIUM_PBF_LIBRARIES}")
|
||||
message(STATUS "OSMIUM_IO_LIBRARIES=${OSMIUM_IO_LIBRARIES}")
|
||||
message(STATUS "OSMIUM_LIBRARIES=${OSMIUM_LIBRARIES}")
|
||||
message(STATUS "OSMIUM_INCLUDE_DIRS=${OSMIUM_INCLUDE_DIRS}")
|
||||
endif()
|
||||
|
||||
63
cmake/FindProtozero.cmake
Normal file
63
cmake/FindProtozero.cmake
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
#----------------------------------------------------------------------
|
||||
#
|
||||
# FindProtozero.cmake
|
||||
#
|
||||
# Find the protozero headers.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Usage:
|
||||
#
|
||||
# Copy this file somewhere into your project directory, where cmake can
|
||||
# find it. Usually this will be a directory called "cmake" which you can
|
||||
# add to the CMake module search path with the following line in your
|
||||
# CMakeLists.txt:
|
||||
#
|
||||
# list(APPEND CMAKE_MODULE_PATH "${CMAKE_SOURCE_DIR}/cmake")
|
||||
#
|
||||
# Then add the following in your CMakeLists.txt:
|
||||
#
|
||||
# find_package(Protozero [version] [REQUIRED])
|
||||
# include_directories(SYSTEM ${PROTOZERO_INCLUDE_DIR})
|
||||
#
|
||||
# The version number is optional. If it is not set, any version of
|
||||
# protozero will do.
|
||||
#
|
||||
# if(NOT PROTOZERO_FOUND)
|
||||
# message(WARNING "Protozero not found!\n")
|
||||
# endif()
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
#
|
||||
# Variables:
|
||||
#
|
||||
# PROTOZERO_FOUND - True if Protozero was found.
|
||||
# PROTOZERO_INCLUDE_DIR - Where to find include files.
|
||||
#
|
||||
#----------------------------------------------------------------------
|
||||
|
||||
# find include path
|
||||
find_path(PROTOZERO_INCLUDE_DIR protozero/version.hpp
|
||||
PATH_SUFFIXES include
|
||||
PATHS ${CMAKE_SOURCE_DIR}/../protozero
|
||||
)
|
||||
|
||||
# Check version number
|
||||
if(Protozero_FIND_VERSION)
|
||||
file(STRINGS "${PROTOZERO_INCLUDE_DIR}/protozero/version.hpp" _version_define REGEX "#define PROTOZERO_VERSION_STRING")
|
||||
if("${_version_define}" MATCHES "#define PROTOZERO_VERSION_STRING \"([0-9.]+)\"")
|
||||
set(_version "${CMAKE_MATCH_1}")
|
||||
else()
|
||||
set(_version "unknown")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
#set(PROTOZERO_INCLUDE_DIRS "${PROTOZERO_INCLUDE_DIR}")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
find_package_handle_standard_args(Protozero
|
||||
REQUIRED_VARS PROTOZERO_INCLUDE_DIR
|
||||
VERSION_VAR _version)
|
||||
|
||||
|
||||
#----------------------------------------------------------------------
|
||||
|
|
@ -120,6 +120,8 @@ function(cpplint_add_subdirectory DIR)
|
|||
COMMAND ${CPPLINT} "--extensions=${EXTENSIONS}"
|
||||
"--root=${CPPLINT_PROJECT_ROOT}"
|
||||
"--quiet"
|
||||
"--linelength=120"
|
||||
"--filter=-build/header_guard, -runtime/references, -whitespace/indent"
|
||||
${LIST_OF_FILES}
|
||||
DEPENDS ${LIST_OF_FILES}
|
||||
COMMENT "cpplint: Checking source code style"
|
||||
|
|
|
|||
|
|
@ -17,4 +17,12 @@ add_executable(pfaedle ${pfaedle_main})
|
|||
add_library(pfaedle_dep ${pfaedle_SRC})
|
||||
|
||||
include_directories(pfaedle_dep PUBLIC ${PROJECT_SOURCE_DIR}/src/cppgtfs/src)
|
||||
if (OSMIUM_FOUND)
|
||||
include_directories(${OSMIUM_INCLUDE_DIRS})
|
||||
target_link_libraries(pfaedle pfaedle_dep util configparser ad_cppgtfs -lpthread
|
||||
${OSMIUM_IO_LIBRARIES})
|
||||
message("linking with osmium")
|
||||
else ()
|
||||
target_link_libraries(pfaedle pfaedle_dep util configparser ad_cppgtfs -lpthread)
|
||||
endif()
|
||||
|
||||
|
|
|
|||
|
|
@ -1,18 +1,17 @@
|
|||
// Copyright 2018, University of Freiburg,
|
||||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include <limits.h>
|
||||
#include <pwd.h>
|
||||
#include <signal.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <climits>
|
||||
#include <csignal>
|
||||
#include <cstdio>
|
||||
#include <fstream>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "ad/cppgtfs/Parser.h"
|
||||
#include "ad/cppgtfs/Writer.h"
|
||||
#include "pfaedle/config/ConfigReader.h"
|
||||
|
|
@ -72,7 +71,7 @@ std::vector<std::string> getCfgPaths(const Config& cfg);
|
|||
// _____________________________________________________________________________
|
||||
int main(int argc, char** argv) {
|
||||
// disable output buffering for standard output
|
||||
setbuf(stdout, NULL);
|
||||
setbuf(stdout, nullptr);
|
||||
|
||||
// initialize randomness
|
||||
srand(time(NULL) + rand()); // NOLINT
|
||||
|
|
@ -80,8 +79,7 @@ int main(int argc, char** argv) {
|
|||
Config cfg;
|
||||
MotConfigReader motCfgReader;
|
||||
|
||||
ConfigReader cr;
|
||||
cr.read(&cfg, argc, argv);
|
||||
ConfigReader::read(&cfg, argc, argv);
|
||||
|
||||
std::vector<pfaedle::gtfs::Feed> gtfs(cfg.feedPaths.size());
|
||||
// feed containing the shapes in memory for evaluation
|
||||
|
|
@ -102,7 +100,7 @@ int main(int argc, char** argv) {
|
|||
exit(static_cast<int>(RetCode::NO_OSM_INPUT));
|
||||
}
|
||||
|
||||
if (motCfgReader.getConfigs().size() == 0) {
|
||||
if (motCfgReader.getConfigs().empty()) {
|
||||
LOG(ERROR) << "No MOT configurations specified and no implicit "
|
||||
"configurations found, see --help.";
|
||||
exit(static_cast<int>(RetCode::NO_MOT_CFG));
|
||||
|
|
@ -125,7 +123,7 @@ int main(int argc, char** argv) {
|
|||
exit(static_cast<int>(RetCode::GTFS_PARSE_ERR));
|
||||
}
|
||||
if (!cfg.writeOverpass) LOG(INFO) << "Done.";
|
||||
} else if (cfg.writeOsm.size() || cfg.writeOverpass) {
|
||||
} else if (!cfg.writeOsm.empty() || cfg.writeOverpass) {
|
||||
for (size_t i = 0; i < cfg.feedPaths.size(); i++) {
|
||||
if (!cfg.writeOverpass)
|
||||
LOG(INFO) << "Reading " << cfg.feedPaths[i] << " ...";
|
||||
|
|
@ -147,10 +145,10 @@ int main(int argc, char** argv) {
|
|||
LOG(DEBUG) << "Read " << motCfgReader.getConfigs().size()
|
||||
<< " unique MOT configs.";
|
||||
MOTs cmdCfgMots = cfg.mots;
|
||||
pfaedle::gtfs::Trip* singleTrip = 0;
|
||||
pfaedle::gtfs::Trip* singleTrip = nullptr;
|
||||
|
||||
if (cfg.shapeTripId.size()) {
|
||||
if (!cfg.feedPaths.size()) {
|
||||
if (!cfg.shapeTripId.empty()) {
|
||||
if (cfg.feedPaths.empty()) {
|
||||
std::cout << "No input feed specified, see --help" << std::endl;
|
||||
exit(static_cast<int>(RetCode::NO_INPUT_FEED));
|
||||
}
|
||||
|
|
@ -161,18 +159,16 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfg.writeOsm.size()) {
|
||||
if (!cfg.writeOsm.empty()) {
|
||||
LOG(INFO) << "Writing filtered XML to " << cfg.writeOsm << " ...";
|
||||
BBoxIdx box(BOX_PADDING);
|
||||
for (size_t i = 0; i < cfg.feedPaths.size(); i++) {
|
||||
ShapeBuilder::getGtfsBox(>fs[i], cmdCfgMots, cfg.shapeTripId, true,
|
||||
&box);
|
||||
ShapeBuilder::getGtfsBox(>fs[i], cmdCfgMots, cfg.shapeTripId, true, &box);
|
||||
}
|
||||
OsmBuilder osmBuilder;
|
||||
std::vector<pfaedle::osm::OsmReadOpts> opts;
|
||||
for (const auto& o : motCfgReader.getConfigs()) {
|
||||
if (std::find_first_of(o.mots.begin(), o.mots.end(), cmdCfgMots.begin(),
|
||||
cmdCfgMots.end()) != o.mots.end()) {
|
||||
if (std::find_first_of(o.mots.begin(), o.mots.end(), cmdCfgMots.begin(), cmdCfgMots.end()) != o.mots.end()) {
|
||||
opts.push_back(o.osmBuildOpts);
|
||||
}
|
||||
}
|
||||
|
|
@ -187,33 +183,34 @@ int main(int argc, char** argv) {
|
|||
} else if (cfg.writeOverpass) {
|
||||
BBoxIdx box(BOX_PADDING);
|
||||
for (size_t i = 0; i < cfg.feedPaths.size(); i++) {
|
||||
ShapeBuilder::getGtfsBox(>fs[i], cmdCfgMots, cfg.shapeTripId, true,
|
||||
&box);
|
||||
ShapeBuilder::getGtfsBox(>fs[i], cmdCfgMots, cfg.shapeTripId, true, &box);
|
||||
}
|
||||
OsmBuilder osmBuilder;
|
||||
std::vector<pfaedle::osm::OsmReadOpts> opts;
|
||||
for (const auto& o : motCfgReader.getConfigs()) {
|
||||
if (std::find_first_of(o.mots.begin(), o.mots.end(), cmdCfgMots.begin(),
|
||||
cmdCfgMots.end()) != o.mots.end()) {
|
||||
if (std::find_first_of(o.mots.begin(), o.mots.end(), cmdCfgMots.begin(), cmdCfgMots.end()) != o.mots.end()) {
|
||||
opts.push_back(o.osmBuildOpts);
|
||||
}
|
||||
}
|
||||
osmBuilder.overpassQryWrite(&std::cout, opts, box);
|
||||
exit(static_cast<int>(RetCode::SUCCESS));
|
||||
} else if (!cfg.feedPaths.size()) {
|
||||
} else if (cfg.feedPaths.empty()) {
|
||||
std::cout << "No input feed specified, see --help" << std::endl;
|
||||
exit(static_cast<int>(RetCode::NO_INPUT_FEED));
|
||||
}
|
||||
|
||||
std::vector<double> dfBins;
|
||||
auto dfBinStrings = util::split(std::string(cfg.evalDfBins), ',');
|
||||
for (auto st : dfBinStrings) dfBins.push_back(atof(st.c_str()));
|
||||
std::vector<double> dfBins(dfBinStrings.size());
|
||||
for (const auto& st : dfBinStrings) {
|
||||
dfBins.push_back(atof(st.c_str()));
|
||||
}
|
||||
Collector ecoll(cfg.evalPath, dfBins);
|
||||
|
||||
for (const auto& motCfg : motCfgReader.getConfigs()) {
|
||||
std::string filePost;
|
||||
auto usedMots = pfaedle::router::motISect(motCfg.mots, cmdCfgMots);
|
||||
if (!usedMots.size()) continue;
|
||||
if (usedMots.empty())
|
||||
continue;
|
||||
if (singleTrip && !usedMots.count(singleTrip->getRoute()->getType()))
|
||||
continue;
|
||||
if (motCfgReader.getConfigs().size() > 1)
|
||||
|
|
@ -234,9 +231,10 @@ int main(int argc, char** argv) {
|
|||
ShapeBuilder::getGtfsBox(>fs[0], cmdCfgMots, cfg.shapeTripId,
|
||||
cfg.dropShapes, &box);
|
||||
|
||||
if (fStops.size())
|
||||
if (!fStops.empty()) {
|
||||
osmBuilder.read(cfg.osmPath, motCfg.osmBuildOpts, &graph, box,
|
||||
cfg.gridSize, &fStops, &restr);
|
||||
}
|
||||
|
||||
// TODO(patrick): move this somewhere else
|
||||
for (auto& feedStop : fStops) {
|
||||
|
|
@ -249,13 +247,12 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
ShapeBuilder shapeBuilder(>fs[0], &evalFeed, cmdCfgMots, motCfg, &ecoll,
|
||||
&graph, &fStops, &restr, cfg);
|
||||
ShapeBuilder shapeBuilder(>fs[0], &evalFeed, cmdCfgMots, motCfg, &ecoll, &graph, &fStops, &restr, cfg);
|
||||
|
||||
if (cfg.writeGraph) {
|
||||
LOG(INFO) << "Outputting graph.json...";
|
||||
util::geo::output::GeoGraphJsonOutput out;
|
||||
mkdir(cfg.dbgOutputPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
mkdir(cfg.dbgOutputPath.c_str(), 775);
|
||||
std::ofstream fstr(cfg.dbgOutputPath + "/graph.json");
|
||||
out.printLatLng(*shapeBuilder.getGraph(), fstr);
|
||||
fstr.close();
|
||||
|
|
@ -263,7 +260,7 @@ int main(int argc, char** argv) {
|
|||
|
||||
if (singleTrip) {
|
||||
LOG(INFO) << "Outputting path.json...";
|
||||
mkdir(cfg.dbgOutputPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
mkdir(cfg.dbgOutputPath.c_str(), 775);
|
||||
std::ofstream pstr(cfg.dbgOutputPath + "/path.json");
|
||||
util::geo::output::GeoJsonOutput o(pstr);
|
||||
|
||||
|
|
@ -284,7 +281,7 @@ int main(int argc, char** argv) {
|
|||
if (cfg.buildTransitGraph) {
|
||||
util::geo::output::GeoGraphJsonOutput out;
|
||||
LOG(INFO) << "Outputting trgraph" + filePost + ".json...";
|
||||
mkdir(cfg.dbgOutputPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
mkdir(cfg.dbgOutputPath.c_str(), 775);
|
||||
std::ofstream fstr(cfg.dbgOutputPath + "/trgraph" + filePost + ".json");
|
||||
out.printLatLng(ng, fstr);
|
||||
fstr.close();
|
||||
|
|
@ -296,11 +293,12 @@ int main(int argc, char** argv) {
|
|||
}
|
||||
}
|
||||
|
||||
if (cfg.evaluate) ecoll.printStats(&std::cout);
|
||||
if (cfg.evaluate)
|
||||
ecoll.printStats(&std::cout);
|
||||
|
||||
if (cfg.feedPaths.size()) {
|
||||
if (!cfg.feedPaths.empty()) {
|
||||
try {
|
||||
mkdir(cfg.outputPath.c_str(), S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH);
|
||||
mkdir(cfg.outputPath.c_str(), 775);
|
||||
LOG(INFO) << "Writing output GTFS to " << cfg.outputPath << " ...";
|
||||
pfaedle::gtfs::Writer w;
|
||||
w.write(>fs[0], cfg.outputPath);
|
||||
|
|
@ -326,7 +324,9 @@ std::string getFileNameMotStr(const MOTs& mots) {
|
|||
|
||||
// _____________________________________________________________________________
|
||||
std::vector<std::string> getCfgPaths(const Config& cfg) {
|
||||
if (cfg.configPaths.size()) return cfg.configPaths;
|
||||
if (!cfg.configPaths.empty()) {
|
||||
return cfg.configPaths;
|
||||
}
|
||||
std::vector<std::string> ret;
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -19,8 +19,11 @@ using std::string;
|
|||
using std::exception;
|
||||
using std::vector;
|
||||
|
||||
static const char* YEAR = __DATE__ + 7;
|
||||
static const char* COPY =
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wstring-plus-int"
|
||||
static auto YEAR = __DATE__ + 7;
|
||||
#pragma clang diagnostic pop
|
||||
static auto COPY =
|
||||
"University of Freiburg - Chair of Algorithms and Data Structures";
|
||||
static const char* AUTHORS = "Patrick Brosi <brosi@informatik.uni-freiburg.de>";
|
||||
|
||||
|
|
@ -148,8 +151,7 @@ void ConfigReader::read(Config* cfg, int argc, char** argv) {
|
|||
{0, 0, 0, 0}};
|
||||
|
||||
char c;
|
||||
while ((c = getopt_long(argc, argv, ":o:hvi:c:x:Dm:g:X:T:d:p", ops, 0)) !=
|
||||
-1) {
|
||||
while ((c = getopt_long(argc, argv, ":o:hvi:c:x:Dm:g:X:T:d:p", ops, nullptr)) != -1) {
|
||||
switch (c) {
|
||||
case 1:
|
||||
cfg->writeGraph = true;
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@ typedef std::pair<std::string, std::string> Attr;
|
|||
typedef std::vector<osmid> OsmIdList;
|
||||
|
||||
struct OsmRel {
|
||||
OsmRel() : id(0) {}
|
||||
OsmRel() : id(0),
|
||||
keepFlags(0),
|
||||
dropFlags(0) {}
|
||||
osmid id;
|
||||
AttrMap attrs;
|
||||
std::vector<osmid> nodes;
|
||||
|
|
@ -35,7 +37,9 @@ struct OsmRel {
|
|||
};
|
||||
|
||||
struct OsmWay {
|
||||
OsmWay() : id(0) {}
|
||||
OsmWay() : id(0),
|
||||
keepFlags(0),
|
||||
dropFlags(0) {}
|
||||
osmid id;
|
||||
AttrMap attrs;
|
||||
std::vector<osmid> nodes;
|
||||
|
|
@ -45,7 +49,11 @@ struct OsmWay {
|
|||
};
|
||||
|
||||
struct OsmNode {
|
||||
OsmNode() : id(0) {}
|
||||
OsmNode() : id(0),
|
||||
lat(0.f),
|
||||
lng(0.f),
|
||||
keepFlags(0),
|
||||
dropFlags(0) {}
|
||||
osmid id;
|
||||
double lat;
|
||||
double lng;
|
||||
|
|
@ -57,6 +65,11 @@ struct OsmNode {
|
|||
|
||||
struct Restriction {
|
||||
osmid eFrom, eTo;
|
||||
Restriction() = default;
|
||||
Restriction(osmid from, osmid to):
|
||||
eFrom(from),
|
||||
eTo(to)
|
||||
{}
|
||||
};
|
||||
|
||||
typedef std::unordered_map<osmid, std::vector<Restriction>> RestrMap;
|
||||
|
|
|
|||
|
|
@ -2,7 +2,11 @@
|
|||
// Chair of Algorithms and Data Structures.
|
||||
// Authors: Patrick Brosi <brosi@informatik.uni-freiburg.de>
|
||||
|
||||
#include <float.h>
|
||||
#include <osmium/io/any_input.hpp>
|
||||
#include <osmium/geom/haversine.hpp>
|
||||
#include <osmium/visitor.hpp>
|
||||
#include <osmium/handler.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <exception>
|
||||
#include <iostream>
|
||||
|
|
@ -12,6 +16,7 @@
|
|||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "pfaedle/Def.h"
|
||||
#include "pfaedle/osm/BBoxIdx.h"
|
||||
#include "pfaedle/osm/Osm.h"
|
||||
|
|
@ -47,18 +52,705 @@ using pfaedle::osm::EqSearch;
|
|||
using pfaedle::osm::BlockSearch;
|
||||
using ad::cppgtfs::gtfs::Stop;
|
||||
|
||||
class Handler: public osmium::handler::Handler
|
||||
{
|
||||
public:
|
||||
Handler(const pfaedle::osm::AttrKeySet& attributes):
|
||||
_attributes(attributes)
|
||||
{}
|
||||
|
||||
protected:
|
||||
template<typename T>
|
||||
void parseTags(T& obj, const osmium::TagList& tags)
|
||||
{
|
||||
for (const auto& tag : tags) {
|
||||
if (_attributes.count(tag.key())) {
|
||||
obj.attrs[tag.key()] = tag.value();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const pfaedle::osm::AttrKeySet& _attributes;
|
||||
|
||||
};
|
||||
class NodeFilteringHandler : public osmium::handler::Handler
|
||||
{
|
||||
const pfaedle::osm::OsmFilter &_filter;
|
||||
const pfaedle::osm::BBoxIdx &_bbox;
|
||||
pfaedle::osm::OsmIdSet &_bboxNodes;
|
||||
pfaedle::osm::OsmIdSet &_noHupNodes;
|
||||
|
||||
public:
|
||||
NodeFilteringHandler(const pfaedle::osm::OsmFilter &filter,
|
||||
const pfaedle::osm::BBoxIdx &bbox,
|
||||
pfaedle::osm::OsmIdSet &bboxNodes,
|
||||
pfaedle::osm::OsmIdSet &noHupNodes) :
|
||||
_filter(filter),
|
||||
_bbox(bbox),
|
||||
_bboxNodes(bboxNodes),
|
||||
_noHupNodes(noHupNodes) {}
|
||||
|
||||
void node(const osmium::Node &node)
|
||||
{
|
||||
bool ignored = false;
|
||||
|
||||
for (const auto &tag : node.tags()) {
|
||||
if (_filter.nohup(tag.key(), tag.value())) {
|
||||
_noHupNodes.add(node.id());
|
||||
ignored = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!ignored) {
|
||||
Point<double> point{node.location().lon(), node.location().lat()};
|
||||
if (_bbox.contains(point)) {
|
||||
_bboxNodes.add(node.id());
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class RelationHandler: public osmium::handler::Handler {
|
||||
const pfaedle::osm::OsmFilter& _filter;
|
||||
const pfaedle::osm::BBoxIdx& _bbox;
|
||||
const pfaedle::osm::AttrKeySet& _keepAttrs;
|
||||
pfaedle::osm::RelLst& _rels;
|
||||
pfaedle::osm::RelMap& _nodeRels;
|
||||
pfaedle::osm::RelMap& _wayRels;
|
||||
pfaedle::osm::Restrictions& _restrictions;
|
||||
|
||||
public:
|
||||
RelationHandler(const pfaedle::osm::OsmFilter& filter,
|
||||
const pfaedle::osm::BBoxIdx& bbox,
|
||||
const pfaedle::osm::AttrKeySet& keepAttrs,
|
||||
pfaedle::osm::RelLst& rels,
|
||||
pfaedle::osm::RelMap& nodeRels,
|
||||
pfaedle::osm::RelMap& wayRels,
|
||||
pfaedle::osm::Restrictions& restrictions) :
|
||||
_filter(filter),
|
||||
_bbox(bbox),
|
||||
_keepAttrs(keepAttrs),
|
||||
_rels(rels),
|
||||
_nodeRels(nodeRels),
|
||||
_wayRels(wayRels),
|
||||
_restrictions(restrictions)
|
||||
{}
|
||||
|
||||
void relation(const osmium::Relation &relation) {
|
||||
OsmRel rel;
|
||||
rel.id = relation.id();
|
||||
|
||||
if (rel.id == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (const auto& tag : relation.tags()) {
|
||||
if (_keepAttrs.count(tag.key())) {
|
||||
rel.attrs[tag.key()] = tag.value();
|
||||
}
|
||||
}
|
||||
|
||||
for (const auto& member : relation.members()) {
|
||||
using osmium::item_type;
|
||||
auto& obj = member.get_object();
|
||||
if (member.type() == item_type::node) {
|
||||
rel.nodes.push_back(obj.id());
|
||||
rel.nodeRoles.emplace_back(member.role());
|
||||
} else if (member.type() == item_type::way) {
|
||||
rel.ways.push_back(obj.id());
|
||||
rel.wayRoles.emplace_back(member.role());
|
||||
}
|
||||
}
|
||||
for (auto id : rel.nodes) {
|
||||
_nodeRels[id].push_back(_rels.rels.size() - 1);
|
||||
}
|
||||
|
||||
for (auto id : rel.ways) {
|
||||
_wayRels[id].push_back(_rels.rels.size() - 1);
|
||||
}
|
||||
|
||||
uint64_t keepFlags = _filter.keep(rel.attrs, pfaedle::osm::OsmFilter::REL);
|
||||
uint64_t dropFlags = _filter.drop(rel.attrs, pfaedle::osm::OsmFilter::REL);
|
||||
|
||||
if (rel.id && !rel.attrs.empty() && keepFlags && !dropFlags) {
|
||||
rel.keepFlags = keepFlags;
|
||||
rel.dropFlags = dropFlags;
|
||||
}
|
||||
|
||||
_rels.rels.push_back(rel.attrs);
|
||||
if (rel.keepFlags & pfaedle::osm::REL_NO_DOWN) {
|
||||
_rels.flat.insert(_rels.rels.size() - 1);
|
||||
}
|
||||
|
||||
// more processing
|
||||
{
|
||||
if (!rel.attrs.count("type")) return;
|
||||
if (rel.attrs.find("type")->second != "restriction") return;
|
||||
|
||||
bool pos = _filter.posRestr(rel.attrs);
|
||||
bool neg = _filter.negRestr(rel.attrs);
|
||||
|
||||
if (!pos && !neg) return;
|
||||
|
||||
uint64_t from = 0;
|
||||
uint64_t to = 0;
|
||||
uint64_t via = 0;
|
||||
|
||||
for (size_t i = 0; i < rel.ways.size(); i++) {
|
||||
if (rel.wayRoles[i] == "from") {
|
||||
if (from) return; // only one from member supported
|
||||
from = rel.ways[i];
|
||||
}
|
||||
if (rel.wayRoles[i] == "to") {
|
||||
if (to) return; // only one to member supported
|
||||
to = rel.ways[i];
|
||||
}
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < rel.nodes.size(); i++) {
|
||||
if (rel.nodeRoles[i] == "via") {
|
||||
via = rel.nodes[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (from && to && via) {
|
||||
if (pos) {
|
||||
_restrictions.pos[via].emplace_back(from, to);
|
||||
} else if (neg) {
|
||||
_restrictions.neg[via].emplace_back(from, to);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class WayHandler: public osmium::handler::Handler {
|
||||
pfaedle::trgraph::Graph& _graph;
|
||||
const pfaedle::osm::RelLst& _rels;
|
||||
const pfaedle::osm::RelMap& _wayRels;
|
||||
const pfaedle::osm::OsmFilter& _filter;
|
||||
const pfaedle::osm::OsmIdSet& _bBoxNodes;
|
||||
pfaedle::osm::NIdMap& _nodes;
|
||||
pfaedle::osm::NIdMultMap& _multiNodes;
|
||||
const pfaedle::osm::OsmIdSet& _noHupNodes;
|
||||
const pfaedle::osm::AttrKeySet& _keepAttrs;
|
||||
const pfaedle::osm::Restrictions& _restrictions;
|
||||
pfaedle::osm::Restrictor& _restrictor;
|
||||
const pfaedle::osm::FlatRels& _fl;
|
||||
pfaedle::osm::EdgTracks& _eTracks;
|
||||
const pfaedle::osm::OsmReadOpts& _opts;
|
||||
|
||||
|
||||
std::map<TransitEdgeLine, TransitEdgeLine *> _lines;
|
||||
std::map<size_t, TransitEdgeLine *> _relLines;
|
||||
|
||||
public:
|
||||
WayHandler(pfaedle::trgraph::Graph &g,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const pfaedle::osm::RelMap &wayRels,
|
||||
const pfaedle::osm::OsmFilter &filter,
|
||||
const pfaedle::osm::OsmIdSet &bBoxNodes,
|
||||
pfaedle::osm::NIdMap &nodes,
|
||||
pfaedle::osm::NIdMultMap &multiNodes,
|
||||
const pfaedle::osm::OsmIdSet &noHupNodes,
|
||||
const pfaedle::osm::AttrKeySet &keepAttrs,
|
||||
const pfaedle::osm::Restrictions &rawRests,
|
||||
pfaedle::osm::Restrictor &restor,
|
||||
const pfaedle::osm::FlatRels &fl,
|
||||
pfaedle::osm::EdgTracks &eTracks,
|
||||
const pfaedle::osm::OsmReadOpts &opts) :
|
||||
_graph(g),
|
||||
_rels(rels),
|
||||
_wayRels(wayRels),
|
||||
_filter(filter),
|
||||
_bBoxNodes(bBoxNodes),
|
||||
_nodes(nodes),
|
||||
_multiNodes(multiNodes),
|
||||
_noHupNodes(noHupNodes),
|
||||
_keepAttrs(keepAttrs),
|
||||
_restrictions(rawRests),
|
||||
_restrictor(restor),
|
||||
_fl(fl),
|
||||
_eTracks(eTracks),
|
||||
_opts(opts)
|
||||
{}
|
||||
|
||||
void way(const osmium::Way &way) {
|
||||
OsmWay w;
|
||||
w.id = way.id();
|
||||
for (const auto &node : way.nodes()) {
|
||||
w.nodes.emplace_back(node.ref());
|
||||
}
|
||||
for (const auto &tag : way.tags()) {
|
||||
if (_keepAttrs.count(tag.key())) {
|
||||
w.attrs[tag.key()] = tag.value();
|
||||
}
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
if (w.id && w.nodes.size() > 1 &&
|
||||
(relKeep(w.id, _wayRels, _fl) || _filter.keep(w.attrs, pfaedle::osm::OsmFilter::WAY)) &&
|
||||
!_filter.drop(w.attrs, pfaedle::osm::OsmFilter::WAY)) {
|
||||
for (auto nid : w.nodes) {
|
||||
if (_bBoxNodes.has(nid)) {
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (valid) {
|
||||
Node *last = nullptr;
|
||||
std::vector<TransitEdgeLine *> lines;
|
||||
if (_wayRels.count(w.id)) {
|
||||
lines = getLines(_wayRels.find(w.id)->second, _rels, _opts);
|
||||
}
|
||||
std::string track =
|
||||
getAttrByFirstMatch(_opts.edgePlatformRules, w.id, w.attrs, _wayRels, _rels, _opts.trackNormzer);
|
||||
|
||||
uint64_t lastnid = 0;
|
||||
|
||||
for (auto nid : w.nodes) {
|
||||
Node *n = nullptr;
|
||||
|
||||
if (_noHupNodes.has(nid)) {
|
||||
n = _graph.addNd();
|
||||
_multiNodes[nid].insert(n);
|
||||
} else if (!_nodes.count(nid)) {
|
||||
if (!_bBoxNodes.has(nid)) {
|
||||
continue;
|
||||
}
|
||||
n = _graph.addNd();
|
||||
_nodes[nid] = n;
|
||||
} else {
|
||||
n = _nodes[nid];
|
||||
}
|
||||
|
||||
if (last) {
|
||||
auto e = _graph.addEdg(last, n, EdgePL());
|
||||
if (!e)
|
||||
continue;
|
||||
|
||||
processRestrictor(nid, w.id, _restrictions, e, n, &_restrictor);
|
||||
processRestrictor(lastnid, w.id, _restrictions, e, last, &_restrictor);
|
||||
|
||||
e->pl().addLines(lines);
|
||||
e->pl().setLvl(_filter.level(w.attrs));
|
||||
if (!track.empty()) {
|
||||
_eTracks[e] = track;
|
||||
}
|
||||
|
||||
if (_filter.oneway(w.attrs))
|
||||
e->pl().setOneWay(1);
|
||||
if (_filter.onewayrev(w.attrs))
|
||||
e->pl().setOneWay(2);
|
||||
}
|
||||
lastnid = nid;
|
||||
last = n;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static bool relKeep(uint64_t id, const pfaedle::osm::RelMap &rels, const pfaedle::osm::FlatRels &fl) {
|
||||
auto it = rels.find(id);
|
||||
|
||||
if (it == rels.end())
|
||||
return false;
|
||||
|
||||
return std::any_of(it->second.begin(), it->second.end(), [fl](decltype(*it->second.begin()) relId){
|
||||
return !fl.count(relId);
|
||||
});
|
||||
}
|
||||
|
||||
std::vector<TransitEdgeLine *> getLines(const std::vector<size_t> &edgeRels,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const pfaedle::osm::OsmReadOpts &ops)
|
||||
{
|
||||
std::vector<TransitEdgeLine *> ret;
|
||||
for (size_t relId : edgeRels) {
|
||||
TransitEdgeLine* transitEdgeLinePointer = nullptr;
|
||||
|
||||
if (_relLines.count(relId)) {
|
||||
transitEdgeLinePointer = _relLines[relId];
|
||||
} else {
|
||||
TransitEdgeLine transitEdgeLine;
|
||||
|
||||
bool found = false;
|
||||
for (const auto &r : ops.relLinerules.sNameRule) {
|
||||
for (const auto &relAttr : rels.rels[relId]) {
|
||||
if (relAttr.first == r) {
|
||||
transitEdgeLine.shortName = ops.lineNormzer(pfxml::file::decode(relAttr.second));
|
||||
if (!transitEdgeLine.shortName.empty()) found = true;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
found = false;
|
||||
for (const auto &r : ops.relLinerules.fromNameRule) {
|
||||
for (const auto &relAttr : rels.rels[relId]) {
|
||||
if (relAttr.first == r) {
|
||||
transitEdgeLine.fromStr = ops.statNormzer(pfxml::file::decode(relAttr.second));
|
||||
if (!transitEdgeLine.fromStr.empty()) found = true;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
found = false;
|
||||
for (const auto &r : ops.relLinerules.toNameRule) {
|
||||
for (const auto &relAttr : rels.rels[relId]) {
|
||||
if (relAttr.first == r) {
|
||||
transitEdgeLine.toStr = ops.statNormzer(pfxml::file::decode(relAttr.second));
|
||||
if (!transitEdgeLine.toStr.empty()) found = true;
|
||||
}
|
||||
}
|
||||
if (found) break;
|
||||
}
|
||||
|
||||
if (transitEdgeLine.shortName.empty() && transitEdgeLine.fromStr.empty() &&
|
||||
transitEdgeLine.toStr.empty())
|
||||
continue;
|
||||
|
||||
if (_lines.count(transitEdgeLine)) {
|
||||
transitEdgeLinePointer = _lines[transitEdgeLine];
|
||||
_relLines[relId] = transitEdgeLinePointer;
|
||||
} else {
|
||||
transitEdgeLinePointer = new TransitEdgeLine(transitEdgeLine);
|
||||
_lines[transitEdgeLine] = transitEdgeLinePointer;
|
||||
_relLines[relId] = transitEdgeLinePointer;
|
||||
}
|
||||
}
|
||||
ret.push_back(transitEdgeLinePointer);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void processRestrictor(uint64_t nid, uint64_t wid,
|
||||
const pfaedle::osm::Restrictions &rawRests,
|
||||
Edge *e,
|
||||
Node *n,
|
||||
pfaedle::osm::Restrictor *restor) {
|
||||
if (rawRests.pos.count(nid)) {
|
||||
for (const auto &kv : rawRests.pos.find(nid)->second) {
|
||||
if (kv.eFrom == wid) {
|
||||
e->pl().setRestricted();
|
||||
restor->add(e, kv.eTo, n, true);
|
||||
} else if (kv.eTo == wid) {
|
||||
e->pl().setRestricted();
|
||||
restor->relax(wid, n, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rawRests.neg.count(nid)) {
|
||||
for (const auto &kv : rawRests.neg.find(nid)->second) {
|
||||
if (kv.eFrom == wid) {
|
||||
e->pl().setRestricted();
|
||||
restor->add(e, kv.eTo, n, false);
|
||||
} else if (kv.eTo == wid) {
|
||||
e->pl().setRestricted();
|
||||
restor->relax(wid, n, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static std::string getAttr(const pfaedle::osm::DeepAttrRule &s, uint64_t id,
|
||||
const pfaedle::osm::AttrMap &attrs,
|
||||
const pfaedle::osm::RelMap &entRels,
|
||||
const pfaedle::osm::RelLst &rels) {
|
||||
if (s.relRule.kv.first.empty()) {
|
||||
if (attrs.find(s.attr) != attrs.end()) {
|
||||
return attrs.find(s.attr)->second;
|
||||
}
|
||||
} else {
|
||||
if (entRels.count(id)) {
|
||||
for (const auto &relId : entRels.find(id)->second) {
|
||||
if (pfaedle::osm::OsmFilter::contained(rels.rels[relId], s.relRule.kv)) {
|
||||
if (rels.rels[relId].count(s.attr)) {
|
||||
return rels.rels[relId].find(s.attr)->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
static std::string getAttrByFirstMatch(const pfaedle::osm::DeepAttrLst &rule, uint64_t id,
|
||||
const pfaedle::osm::AttrMap &attrs,
|
||||
const pfaedle::osm::RelMap &entRels,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const Normalizer &norm) {
|
||||
std::string ret;
|
||||
for (const auto &s : rule) {
|
||||
ret = norm(pfxml::file::decode(getAttr(s, id, attrs, entRels, rels)));
|
||||
if (!ret.empty()) return ret;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
class NodeHandler: public osmium::handler::Handler {
|
||||
pfaedle::trgraph::Graph& _graph;
|
||||
const pfaedle::osm::RelLst& rels;
|
||||
const pfaedle::osm::RelMap& nodeRels;
|
||||
const pfaedle::osm::OsmFilter& _filter;
|
||||
const pfaedle::osm::OsmIdSet& bBoxNodes;
|
||||
pfaedle::osm::NIdMap& nodes;
|
||||
pfaedle::osm::NIdMultMap& multNodes;
|
||||
pfaedle::osm::NodeSet& orphanStations;
|
||||
const pfaedle::osm::AttrKeySet& keepAttrs;
|
||||
const pfaedle::osm::FlatRels& fl;
|
||||
const pfaedle::osm::OsmReadOpts& opts;
|
||||
|
||||
public:
|
||||
NodeHandler(Graph &g,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const pfaedle::osm::RelMap &nodeRels,
|
||||
const pfaedle::osm::OsmFilter &filter,
|
||||
const pfaedle::osm::OsmIdSet &bBoxNodes,
|
||||
pfaedle::osm::NIdMap &nodes,
|
||||
pfaedle::osm::NIdMultMap &multNodes,
|
||||
pfaedle::osm::NodeSet &orphanStations,
|
||||
const pfaedle::osm::AttrKeySet &keepAttrs,
|
||||
const pfaedle::osm::FlatRels &fl,
|
||||
const pfaedle::osm::OsmReadOpts &opts) :
|
||||
_graph(g),
|
||||
rels(rels),
|
||||
nodeRels(nodeRels),
|
||||
_filter(filter),
|
||||
bBoxNodes(bBoxNodes),
|
||||
nodes(nodes),
|
||||
multNodes(multNodes),
|
||||
orphanStations(orphanStations),
|
||||
keepAttrs(keepAttrs),
|
||||
fl(fl),
|
||||
opts(opts)
|
||||
{}
|
||||
|
||||
void node(const osmium::Node &node) {
|
||||
OsmNode nd;
|
||||
nd.id = node.id();
|
||||
nd.lat = node.location().lat();
|
||||
nd.lng = node.location().lon();
|
||||
|
||||
for (const auto &tag : node.tags()) {
|
||||
if (keepAttrs.count(tag.key()))
|
||||
nd.attrs[tag.key()] = tag.value();
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
if (nd.id &&
|
||||
(nodes.count(nd.id) || multNodes.count(nd.id) ||
|
||||
relKeep(nd.id, nodeRels, fl) || _filter.keep(nd.attrs, pfaedle::osm::OsmFilter::NODE)) &&
|
||||
(nodes.count(nd.id) || bBoxNodes.has(nd.id)) &&
|
||||
(nodes.count(nd.id) || multNodes.count(nd.id) ||
|
||||
!_filter.drop(nd.attrs, pfaedle::osm::OsmFilter::NODE))) {
|
||||
valid = true;
|
||||
}
|
||||
|
||||
pfaedle::osm::StAttrGroups attrGroups;
|
||||
if (valid) {
|
||||
Node *n = nullptr;
|
||||
auto pos = util::geo::latLngToWebMerc<PFAEDLE_PRECISION>(nd.lat, nd.lng);
|
||||
|
||||
if (nodes.count(nd.id)) {
|
||||
n = nodes[nd.id];
|
||||
n->pl().setGeom(pos);
|
||||
|
||||
if (_filter.station(nd.attrs)) {
|
||||
auto si = getStatInfo(n, nd.id, pos, nd.attrs, &attrGroups, nodeRels, rels, opts);
|
||||
|
||||
if (!si.isNull())
|
||||
n->pl().setSI(si);
|
||||
} else if (_filter.blocker(nd.attrs)) {
|
||||
n->pl().setBlocker();
|
||||
}
|
||||
} else if (multNodes.count(nd.id)) {
|
||||
for (auto *n : multNodes[nd.id]) {
|
||||
n->pl().setGeom(pos);
|
||||
if (_filter.station(nd.attrs)) {
|
||||
auto si = getStatInfo(n, nd.id, pos, nd.attrs, &attrGroups, nodeRels, rels, opts);
|
||||
|
||||
if (!si.isNull())
|
||||
n->pl().setSI(si);
|
||||
} else if (_filter.blocker(nd.attrs)) {
|
||||
n->pl().setBlocker();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// these are nodes without any connected edges
|
||||
if (_filter.station(nd.attrs)) {
|
||||
auto tmp = _graph.addNd(NodePL(pos));
|
||||
auto si = getStatInfo(tmp, nd.id, pos, nd.attrs, &attrGroups, nodeRels, rels, opts);
|
||||
|
||||
if (!si.isNull())
|
||||
tmp->pl().setSI(si);
|
||||
|
||||
if (tmp->pl().getSI()) {
|
||||
tmp->pl().getSI()->setIsFromOsm(false);
|
||||
orphanStations.insert(tmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static bool relKeep(uint64_t id, const pfaedle::osm::RelMap &rels, const pfaedle::osm::FlatRels &fl) {
|
||||
auto it = rels.find(id);
|
||||
|
||||
if (it == rels.end())
|
||||
return false;
|
||||
|
||||
for (uint64_t relId : it->second) {
|
||||
// as soon as any of this entities relations is not flat, return true
|
||||
if (!fl.count(relId))
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static Nullable<StatInfo> getStatInfo(Node *node, uint64_t nid,
|
||||
const POINT &pos,
|
||||
const pfaedle::osm::AttrMap &m,
|
||||
pfaedle::osm::StAttrGroups *groups,
|
||||
const pfaedle::osm::RelMap &nodeRels,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const pfaedle::osm::OsmReadOpts &ops) {
|
||||
std::vector<std::string> names =
|
||||
getAttrMatchRanked(ops.statAttrRules.nameRule, nid, m, nodeRels, rels, ops.statNormzer);
|
||||
std::string platform =
|
||||
getAttrByFirstMatch(ops.statAttrRules.platformRule, nid, m, nodeRels, rels, ops.trackNormzer);
|
||||
|
||||
if (names.empty()) {
|
||||
return Nullable<StatInfo>();
|
||||
}
|
||||
|
||||
auto ret = StatInfo(names[0], platform, true);
|
||||
|
||||
#ifdef PFAEDLE_STATION_IDS
|
||||
ret.setId(getAttrByFirstMatch(ops.statAttrRules.idRule, nid, m, nodeRels, rels, ops.idNormzer));
|
||||
#endif
|
||||
|
||||
for (size_t i = 1; i < names.size(); i++) {
|
||||
ret.addAltName(names[i]);
|
||||
}
|
||||
bool groupFound = false;
|
||||
|
||||
for (const auto &rule : ops.statGroupNAttrRules) {
|
||||
if (groupFound) break;
|
||||
std::string ruleVal = getAttr(rule.attr, nid, m, nodeRels, rels);
|
||||
if (!ruleVal.empty()) {
|
||||
// check if a matching group exists
|
||||
for (auto *group : (*groups)[rule.attr.attr][ruleVal]) {
|
||||
if (groupFound) break;
|
||||
for (const auto *member : group->getNodes()) {
|
||||
if (webMercMeterDist(*member->pl().getGeom(), pos) <= rule.maxDist) {
|
||||
// ok, group is matching
|
||||
groupFound = true;
|
||||
if (node) group->addNode(node);
|
||||
ret.setGroup(group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!groupFound) {
|
||||
for (const auto &rule : ops.statGroupNAttrRules) {
|
||||
std::string ruleVal = getAttr(rule.attr, nid, m, nodeRels, rels);
|
||||
if (!ruleVal.empty()) {
|
||||
// add new group
|
||||
auto *group = new StatGroup();
|
||||
if (node) group->addNode(node);
|
||||
ret.setGroup(group);
|
||||
(*groups)[rule.attr.attr][ruleVal].push_back(group);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string getAttrByFirstMatch(const pfaedle::osm::DeepAttrLst &rule,
|
||||
uint64_t id,
|
||||
const pfaedle::osm::AttrMap &attrs,
|
||||
const pfaedle::osm::RelMap &entRels,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const Normalizer &norm) {
|
||||
std::string ret;
|
||||
for (const auto &s : rule) {
|
||||
ret = norm(pfxml::file::decode(getAttr(s, id, attrs, entRels, rels)));
|
||||
if (!ret.empty()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::vector<std::string> getAttrMatchRanked(const pfaedle::osm::DeepAttrLst &rule,
|
||||
uint64_t id,
|
||||
const pfaedle::osm::AttrMap &attrs,
|
||||
const pfaedle::osm::RelMap &entRels,
|
||||
const pfaedle::osm::RelLst &rels,
|
||||
const Normalizer &norm) {
|
||||
std::vector<std::string> ret;
|
||||
for (const auto &s : rule) {
|
||||
std::string tmp = norm(pfxml::file::decode(getAttr(s, id, attrs, entRels, rels)));
|
||||
if (!tmp.empty()) {
|
||||
ret.push_back(tmp);
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static std::string getAttr(const pfaedle::osm::DeepAttrRule &s,
|
||||
uint64_t id,
|
||||
const pfaedle::osm::AttrMap &attrs,
|
||||
const pfaedle::osm::RelMap &entRels,
|
||||
const pfaedle::osm::RelLst &rels) {
|
||||
if (s.relRule.kv.first.empty()) {
|
||||
if (attrs.find(s.attr) != attrs.end()) {
|
||||
return attrs.find(s.attr)->second;
|
||||
}
|
||||
} else {
|
||||
if (entRels.count(id)) {
|
||||
for (const auto &relId : entRels.find(id)->second) {
|
||||
if (pfaedle::osm::OsmFilter::contained(rels.rels[relId], s.relRule.kv)) {
|
||||
if (rels.rels[relId].count(s.attr)) {
|
||||
return rels.rels[relId].find(s.attr)->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
// _____________________________________________________________________________
|
||||
bool EqSearch::operator()(const Node* cand, const StatInfo* si) const {
|
||||
if (orphanSnap && cand->pl().getSI() &&
|
||||
(!cand->pl().getSI()->getGroup() ||
|
||||
cand->pl().getSI()->getGroup()->getStops().size() == 0)) {
|
||||
(!cand->pl().getSI()->getGroup() || cand->pl().getSI()->getGroup()->getStops().empty())) {
|
||||
return true;
|
||||
}
|
||||
return cand->pl().getSI() && cand->pl().getSI()->simi(si) > minSimi;
|
||||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
OsmBuilder::OsmBuilder() {}
|
||||
OsmBuilder::OsmBuilder() = default;
|
||||
|
||||
// _____________________________________________________________________________
|
||||
void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
||||
|
|
@ -85,7 +777,22 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
|
||||
OsmFilter filter(opts);
|
||||
|
||||
pfxml::file xml(path);
|
||||
osmium::io::Reader reader {path,
|
||||
osmium::osm_entity_bits::node |
|
||||
osmium::osm_entity_bits::way |
|
||||
osmium::osm_entity_bits::relation};
|
||||
osmium::io::Reader reader_nodes{path,
|
||||
osmium::osm_entity_bits::node};
|
||||
|
||||
NodeFilteringHandler filteringHandler(filter, bbox, bboxNodes, noHupNodes);
|
||||
RelationHandler relationHandler(filter, bbox, attrKeys[2], intmRels, nodeRels, wayRels, rawRests);
|
||||
WayHandler wayHandler(*g, intmRels, wayRels, filter, bboxNodes, nodes, multNodes, noHupNodes,
|
||||
attrKeys[1], rawRests, *res, intmRels.flat, eTracks, opts);
|
||||
|
||||
osmium::apply(reader, filteringHandler, relationHandler, wayHandler);
|
||||
NodeHandler nodeHandler(*g, intmRels, nodeRels, filter, bboxNodes, nodes, multNodes, orphanStations,
|
||||
attrKeys[0], intmRels.flat, opts);
|
||||
osmium::apply(reader_nodes, nodeHandler);
|
||||
|
||||
// we do four passes of the file here to be as memory creedy as possible:
|
||||
// - the first pass collects all node IDs which are
|
||||
|
|
@ -100,28 +807,6 @@ void OsmBuilder::read(const std::string& path, const OsmReadOpts& opts,
|
|||
// * collected as node ids in pass 1
|
||||
// * match the filter criteria
|
||||
// * have been used in a way in pass 3
|
||||
|
||||
LOG(VDEBUG) << "Reading bounding box nodes...";
|
||||
skipUntil(&xml, "node");
|
||||
pfxml::parser_state nodeBeg = xml.state();
|
||||
pfxml::parser_state edgesBeg =
|
||||
readBBoxNds(&xml, &bboxNodes, &noHupNodes, filter, bbox);
|
||||
|
||||
LOG(VDEBUG) << "Reading relations...";
|
||||
skipUntil(&xml, "relation");
|
||||
readRels(&xml, &intmRels, &nodeRels, &wayRels, filter, attrKeys[2],
|
||||
&rawRests);
|
||||
|
||||
LOG(VDEBUG) << "Reading edges...";
|
||||
xml.set_state(edgesBeg);
|
||||
readEdges(&xml, g, intmRels, wayRels, filter, bboxNodes, &nodes, &multNodes,
|
||||
noHupNodes, attrKeys[1], rawRests, res, intmRels.flat, &eTracks,
|
||||
opts);
|
||||
|
||||
LOG(VDEBUG) << "Reading kept nodes...";
|
||||
xml.set_state(nodeBeg);
|
||||
readNodes(&xml, g, intmRels, nodeRels, filter, bboxNodes, &nodes,
|
||||
&multNodes, &orphanStations, attrKeys[0], intmRels.flat, opts);
|
||||
}
|
||||
|
||||
LOG(VDEBUG) << "OSM ID set lookups: " << osm::OsmIdSet::LOOKUPS
|
||||
|
|
@ -361,7 +1046,7 @@ void OsmBuilder::readWriteRels(pfxml::file* i, util::xml::XmlWriter* o,
|
|||
}
|
||||
}
|
||||
|
||||
if (realNodes.size() || realWays.size()) {
|
||||
if (!realNodes.empty() || !realWays.empty()) {
|
||||
o->openTag("relation", "id", std::to_string(rel.id));
|
||||
|
||||
for (size_t j = 0; j < realNodes.size(); j++) {
|
||||
|
|
@ -425,8 +1110,7 @@ void OsmBuilder::readWriteWays(pfxml::file* i, util::xml::XmlWriter* o,
|
|||
NodePL OsmBuilder::plFromGtfs(const Stop* s, const OsmReadOpts& ops) {
|
||||
NodePL ret(
|
||||
util::geo::latLngToWebMerc<PFAEDLE_PRECISION>(s->getLat(), s->getLng()),
|
||||
StatInfo(ops.statNormzer(s->getName()),
|
||||
ops.trackNormzer(s->getPlatformCode()), false));
|
||||
StatInfo(ops.statNormzer(s->getName()), ops.trackNormzer(s->getPlatformCode()), false));
|
||||
|
||||
#ifdef PFAEDLE_STATION_IDS
|
||||
// debug feature, store station id from GTFS
|
||||
|
|
@ -464,7 +1148,8 @@ pfxml::parser_state OsmBuilder::readBBoxNds(pfxml::file* xml, OsmIdSet* nodes,
|
|||
|
||||
if (inNodeBlock) {
|
||||
// block ended
|
||||
if (strcmp(cur.name, "node")) return xml->state();
|
||||
if (strcmp(cur.name, "node") != 0)
|
||||
return xml->state();
|
||||
double y = util::atof(cur.attrs.find("lat")->second, 7);
|
||||
double x = util::atof(cur.attrs.find("lon")->second, 7);
|
||||
|
||||
|
|
@ -486,7 +1171,7 @@ OsmWay OsmBuilder::nextWayWithId(pfxml::file* xml, osmid wid,
|
|||
do {
|
||||
const pfxml::tag& cur = xml->get();
|
||||
if (xml->level() == 2 || xml->level() == 0) {
|
||||
if (w.id || strcmp(cur.name, "way")) return w;
|
||||
if (w.id || strcmp(cur.name, "way") != 0) return w;
|
||||
|
||||
osmid id = util::atoul(cur.attrs.find("id")->second);
|
||||
if (id == wid) w.id = id;
|
||||
|
|
@ -509,7 +1194,7 @@ OsmWay OsmBuilder::nextWayWithId(pfxml::file* xml, osmid wid,
|
|||
|
||||
// _____________________________________________________________________________
|
||||
void OsmBuilder::skipUntil(pfxml::file* xml, const std::string& s) const {
|
||||
while (xml->next() && strcmp(xml->get().name, s.c_str())) {
|
||||
while (xml->next() && strcmp(xml->get().name, s.c_str()) != 0) {
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -538,8 +1223,11 @@ OsmWay OsmBuilder::nextWay(pfxml::file* xml, const RelMap& wayRels,
|
|||
do {
|
||||
const pfxml::tag& cur = xml->get();
|
||||
if (xml->level() == 2 || xml->level() == 0) {
|
||||
if (keepWay(w, wayRels, filter, bBoxNodes, fl)) return w;
|
||||
if (strcmp(cur.name, "way")) return OsmWay();
|
||||
if (keepWay(w, wayRels, filter, bBoxNodes, fl))
|
||||
return w;
|
||||
|
||||
if (strcmp(cur.name, "way") != 0)
|
||||
return OsmWay();
|
||||
|
||||
w.id = util::atoul(cur.attrs.find("id")->second);
|
||||
w.nodes.clear();
|
||||
|
|
@ -551,13 +1239,16 @@ OsmWay OsmBuilder::nextWay(pfxml::file* xml, const RelMap& wayRels,
|
|||
osmid nid = util::atoul(cur.attrs.find("ref")->second);
|
||||
w.nodes.push_back(nid);
|
||||
} else if (strcmp(cur.name, "tag") == 0) {
|
||||
if (keepAttrs.count(cur.attrs.find("k")->second))
|
||||
if (keepAttrs.count(cur.attrs.find("k")->second)) {
|
||||
w.attrs[cur.attrs.find("k")->second] = cur.attrs.find("v")->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
} while (xml->next());
|
||||
|
||||
if (keepWay(w, wayRels, filter, bBoxNodes, fl)) return w;
|
||||
if (keepWay(w, wayRels, filter, bBoxNodes, fl))
|
||||
return w;
|
||||
|
||||
return OsmWay();
|
||||
}
|
||||
|
||||
|
|
@ -587,7 +1278,7 @@ void OsmBuilder::readEdges(pfxml::file* xml, const RelMap& wayRels,
|
|||
while ((w = nextWay(xml, wayRels, filter, bBoxNodes, keepAttrs, flat)).id) {
|
||||
ret->push_back(w.id);
|
||||
for (auto n : w.nodes) {
|
||||
(*nodes)[n] = 0;
|
||||
(*nodes)[n] = nullptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -603,7 +1294,7 @@ void OsmBuilder::readEdges(pfxml::file* xml, Graph* g, const RelLst& rels,
|
|||
const OsmReadOpts& opts) {
|
||||
OsmWay w;
|
||||
while ((w = nextWay(xml, wayRels, filter, bBoxNodes, keepAttrs, fl)).id) {
|
||||
Node* last = 0;
|
||||
Node* last = nullptr;
|
||||
std::vector<TransitEdgeLine*> lines;
|
||||
if (wayRels.count(w.id)) {
|
||||
lines = getLines(wayRels.find(w.id)->second, rels, opts);
|
||||
|
|
@ -614,7 +1305,7 @@ void OsmBuilder::readEdges(pfxml::file* xml, Graph* g, const RelLst& rels,
|
|||
|
||||
osmid lastnid = 0;
|
||||
for (osmid nid : w.nodes) {
|
||||
Node* n = 0;
|
||||
Node* n = nullptr;
|
||||
if (noHupNodes.has(nid)) {
|
||||
n = g->addNd();
|
||||
(*multiNodes)[nid].insert(n);
|
||||
|
|
@ -808,7 +1499,7 @@ OsmRel OsmBuilder::nextRel(pfxml::file* xml, const OsmFilter& filter,
|
|||
if (xml->level() == 2 || xml->level() == 0) {
|
||||
uint64_t keepFlags = 0;
|
||||
uint64_t dropFlags = 0;
|
||||
if (rel.id && rel.attrs.size() &&
|
||||
if (rel.id && !rel.attrs.empty() &&
|
||||
(keepFlags = filter.keep(rel.attrs, OsmFilter::REL)) &&
|
||||
!(dropFlags = filter.drop(rel.attrs, OsmFilter::REL))) {
|
||||
rel.keepFlags = keepFlags;
|
||||
|
|
@ -817,7 +1508,9 @@ OsmRel OsmBuilder::nextRel(pfxml::file* xml, const OsmFilter& filter,
|
|||
}
|
||||
|
||||
// block ended
|
||||
if (strcmp(cur.name, "relation")) return OsmRel();
|
||||
if (strcmp(cur.name, "relation") != 0) {
|
||||
return OsmRel();
|
||||
}
|
||||
|
||||
rel.attrs.clear();
|
||||
rel.nodes.clear();
|
||||
|
|
@ -837,20 +1530,22 @@ OsmRel OsmBuilder::nextRel(pfxml::file* xml, const OsmFilter& filter,
|
|||
// the bounding box!!!!
|
||||
rel.nodes.push_back(id);
|
||||
if (cur.attrs.count("role")) {
|
||||
rel.nodeRoles.push_back(cur.attrs.find("role")->second);
|
||||
rel.nodeRoles.emplace_back(cur.attrs.find("role")->second);
|
||||
} else {
|
||||
rel.nodeRoles.push_back("");
|
||||
rel.nodeRoles.emplace_back("");
|
||||
}
|
||||
}
|
||||
|
||||
if (strcmp(cur.attrs.find("type")->second, "way") == 0) {
|
||||
osmid id = util::atoul(cur.attrs.find("ref")->second);
|
||||
rel.ways.push_back(id);
|
||||
if (cur.attrs.count("role")) {
|
||||
rel.wayRoles.push_back(cur.attrs.find("role")->second);
|
||||
rel.wayRoles.emplace_back(cur.attrs.find("role")->second);
|
||||
} else {
|
||||
rel.wayRoles.push_back("");
|
||||
rel.wayRoles.emplace_back("");
|
||||
}
|
||||
}
|
||||
|
||||
} else if (strcmp(cur.name, "tag") == 0) {
|
||||
if (keepAttrs.count(cur.attrs.find("k")->second))
|
||||
rel.attrs[cur.attrs.find("k")->second] = cur.attrs.find("v")->second;
|
||||
|
|
@ -861,7 +1556,7 @@ OsmRel OsmBuilder::nextRel(pfxml::file* xml, const OsmFilter& filter,
|
|||
// dont forget last relation
|
||||
uint64_t keepFlags = 0;
|
||||
uint64_t dropFlags = 0;
|
||||
if (rel.id && rel.attrs.size() &&
|
||||
if (rel.id && !rel.attrs.empty() &&
|
||||
(keepFlags = filter.keep(rel.attrs, OsmFilter::REL)) &&
|
||||
!(dropFlags = filter.drop(rel.attrs, OsmFilter::REL))) {
|
||||
rel.keepFlags = keepFlags;
|
||||
|
|
|
|||
|
|
@ -16,7 +16,7 @@ namespace osm {
|
|||
class OsmFilter {
|
||||
public:
|
||||
enum Type : uint64_t { NODE = 16, WAY = 8, REL = 4, ALL = 0 };
|
||||
OsmFilter() {}
|
||||
OsmFilter() = default;
|
||||
OsmFilter(const MultAttrMap& keep, const MultAttrMap& drop);
|
||||
explicit OsmFilter(const OsmReadOpts& o);
|
||||
uint64_t keep(const AttrMap& attrs, Type t) const;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,8 @@ size_t OsmIdSet::FLOOKUPS = 0;
|
|||
|
||||
// _____________________________________________________________________________
|
||||
OsmIdSet::OsmIdSet()
|
||||
: _closed(false),
|
||||
: _element_size(0),
|
||||
_closed(false),
|
||||
_sorted(true),
|
||||
_last(0),
|
||||
_smallest(-1),
|
||||
|
|
@ -50,6 +51,7 @@ void OsmIdSet::add(osmid id) {
|
|||
if (_closed) throw std::exception();
|
||||
diskAdd(id);
|
||||
|
||||
_element_size++;
|
||||
if (_last > id) _sorted = false;
|
||||
_last = id;
|
||||
if (id < _smallest) _smallest = id;
|
||||
|
|
|
|||
|
|
@ -42,11 +42,16 @@ class OsmIdSet {
|
|||
// Check if an OSM id is contained
|
||||
bool has(osmid id) const;
|
||||
|
||||
size_t size() const {
|
||||
return _element_size;
|
||||
}
|
||||
|
||||
// Count the number of lookups and file lookups for debugging
|
||||
static size_t LOOKUPS;
|
||||
static size_t FLOOKUPS;
|
||||
|
||||
private:
|
||||
mutable size_t _element_size;
|
||||
std::string _tmpPath;
|
||||
mutable bool _closed;
|
||||
mutable int _file;
|
||||
|
|
|
|||
|
|
@ -15,6 +15,7 @@
|
|||
#include <stdexcept>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <random>
|
||||
#include "ad/cppgtfs/gtfs/Feed.h"
|
||||
#include "pfaedle/Def.h"
|
||||
#include "pfaedle/eval/Collector.h"
|
||||
|
|
@ -191,7 +192,9 @@ void ShapeBuilder::shape(pfaedle::netgraph::Graph* ng) {
|
|||
}
|
||||
|
||||
// to avoid unfair load balance on threads
|
||||
std::random_shuffle(clusters.begin(), clusters.end());
|
||||
std::random_device rd;
|
||||
std::mt19937 g(rd());
|
||||
std::shuffle(clusters.begin(), clusters.end(), g);
|
||||
|
||||
size_t iters = EDijkstra::ITERS;
|
||||
size_t totiters = EDijkstra::ITERS;
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ GeoJsonOutput::GeoJsonOutput(std::ostream& str) : _wr(&str, 10, true) {
|
|||
}
|
||||
|
||||
// _____________________________________________________________________________
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str, json::Val attrs)
|
||||
GeoJsonOutput::GeoJsonOutput(std::ostream& str, const json::Val& attrs)
|
||||
: _wr(&str, 10, true) {
|
||||
_wr.obj();
|
||||
_wr.keyVal("type", "FeatureCollection");
|
||||
|
|
|
|||
|
|
@ -19,7 +19,7 @@ namespace output {
|
|||
class GeoJsonOutput {
|
||||
public:
|
||||
GeoJsonOutput(std::ostream& str);
|
||||
GeoJsonOutput(std::ostream& str, json::Val attrs);
|
||||
GeoJsonOutput(std::ostream& str, const json::Val& attrs);
|
||||
~GeoJsonOutput();
|
||||
|
||||
template <typename T>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue