Moved OSM2ODR to a different repo
This commit is contained in:
parent
f6b85cb48a
commit
be76107b44
|
@ -13,8 +13,12 @@ END
|
|||
|
||||
REMOVE_INTERMEDIATE=false
|
||||
BUILD_OSM2ODR=false
|
||||
GIT_PULL=true
|
||||
CURRENT_OSM2ODR_COMMIT=f05c86588f797922758f1a7a50585a3aa969c17a
|
||||
OSM2ODR_BRANCH=carla_osm2odr
|
||||
OSM2ODR_REPO=https://github.com/carla-simulator/sumo.git
|
||||
|
||||
OPTS=`getopt -o h --long help,rebuild,build,clean,carsim -n 'parse-options' -- "$@"`
|
||||
OPTS=`getopt -o h --long help,rebuild,build,clean,carsim,no-pull -n 'parse-options' -- "$@"`
|
||||
|
||||
eval set -- "$OPTS"
|
||||
|
||||
|
@ -27,6 +31,9 @@ while [[ $# -gt 0 ]]; do
|
|||
--build )
|
||||
BUILD_OSM2ODR=true;
|
||||
shift ;;
|
||||
--no-pull )
|
||||
GIT_PULL=false
|
||||
shift ;;
|
||||
--clean )
|
||||
REMOVE_INTERMEDIATE=true;
|
||||
shift ;;
|
||||
|
@ -44,7 +51,7 @@ source $(dirname "$0")/Environment.sh
|
|||
|
||||
function get_source_code_checksum {
|
||||
local EXCLUDE='*__pycache__*'
|
||||
find "${OSM2ODR_ROOT_FOLDER}"/* \! -path "${EXCLUDE}" -print0 | sha1sum | awk '{print $1}'
|
||||
find "${OSM2ODR_SOURCE_FOLDER}"/* \! -path "${EXCLUDE}" -print0 | sha1sum | awk '{print $1}'
|
||||
}
|
||||
|
||||
if ! { ${REMOVE_INTERMEDIATE} || ${BUILD_OSM2ODR}; }; then
|
||||
|
@ -69,17 +76,29 @@ fi
|
|||
|
||||
if ${BUILD_OSM2ODR} ; then
|
||||
log "Building OSM2ODR."
|
||||
[ ! -d ${OSM2ODR_BUILD_FOLDER} ] && mkdir ${OSM2ODR_BUILD_FOLDER}
|
||||
# [ ! -d ${OSM2ODR_BUILD_FOLDER} ] && mkdir ${OSM2ODR_BUILD_FOLDER}
|
||||
if ${GIT_PULL} ; then
|
||||
if [ ! -d ${OSM2ODR_SOURCE_FOLDER} ] ; then
|
||||
git clone -b ${OSM2ODR_BRANCH} ${OSM2ODR_REPO} ${OSM2ODR_SOURCE_FOLDER}
|
||||
fi
|
||||
cd ${OSM2ODR_SOURCE_FOLDER}
|
||||
git fetch
|
||||
git checkout ${CURRENT_OSM2ODR_COMMIT}
|
||||
fi
|
||||
|
||||
mkdir -p ${OSM2ODR_BUILD_FOLDER}
|
||||
cd ${OSM2ODR_BUILD_FOLDER}
|
||||
# define clang compiler
|
||||
export CC=/usr/bin/clang-8
|
||||
export CXX=/usr/bin/clang++-8
|
||||
|
||||
cmake ${OSM2ODR_ROOT_FOLDER} \
|
||||
cmake ${OSM2ODR_SOURCE_FOLDER} \
|
||||
-G "Eclipse CDT4 - Ninja" \
|
||||
-DCMAKE_INSTALL_PREFIX=${LIBCARLA_INSTALL_CLIENT_FOLDER} \
|
||||
-DPROJ_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/proj-install/include \
|
||||
-DPROJ_LIBRARY=${CARLA_BUILD_FOLDER}/proj-install/lib/libproj.a
|
||||
-DPROJ_LIBRARY=${CARLA_BUILD_FOLDER}/proj-install/lib/libproj.a \
|
||||
-DXercesC_INCLUDE_DIR=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install/include \
|
||||
-DXercesC_LIBRARY=${CARLA_BUILD_FOLDER}/xerces-c-3.2.3-install/lib/libxerces-c.a
|
||||
|
||||
ninja osm2odr
|
||||
ninja install
|
||||
|
|
|
@ -149,4 +149,4 @@ build.utils: PythonAPI
|
|||
@${CARLA_BUILD_TOOLS_FOLDER}/BuildUtilsDocker.sh
|
||||
|
||||
osm2odr:
|
||||
@${CARLA_BUILD_TOOLS_FOLDER}/BuildOSM2ODR.sh --build
|
||||
@${CARLA_BUILD_TOOLS_FOLDER}/BuildOSM2ODR.sh --build $(ARGS)
|
||||
|
|
|
@ -19,8 +19,8 @@ LIBCARLA_BUILD_CLIENT_FOLDER=${CARLA_BUILD_FOLDER}/libcarla-client-build
|
|||
LIBCARLA_INSTALL_SERVER_FOLDER=${CARLAUE4_PLUGIN_ROOT_FOLDER}/CarlaDependencies
|
||||
LIBCARLA_INSTALL_CLIENT_FOLDER=${CARLA_PYTHONAPI_SOURCE_FOLDER}/dependencies
|
||||
|
||||
OSM2ODR_ROOT_FOLDER=${CURDIR}/Util/OSM2ODR
|
||||
OSM2ODR_BUILD_FOLDER=${CARLA_BUILD_FOLDER}/libosm2dr-build
|
||||
OSM2ODR_SOURCE_FOLDER=${CARLA_BUILD_FOLDER}/libosm2dr-source
|
||||
|
||||
CARLAUE4_PLUGIN_DEPS_FOLDER=${CARLAUE4_PLUGIN_ROOT_FOLDER}/CarlaDependencies
|
||||
|
||||
|
|
|
@ -1 +0,0 @@
|
|||
bin
|
|
@ -1,78 +0,0 @@
|
|||
Christian Roessel <roessel@zpr.uni-koeln.de> roessel croessel
|
||||
Markus Hartinger <Markus.Hartinger@dlr.de>
|
||||
Peter Mieth <Peter.Mieth@dlr.de>
|
||||
Georg Hertkorn <georg.hertkorn@dlr.de> georg
|
||||
Daniel Krajzewicz <Daniel.Krajzewicz@dlr.de> dkrajzew
|
||||
Julia Ringel <Julia.Ringel@dlr.de> jringel
|
||||
Danilot Teta Boyom <Danilot.Tete-Boyom@dlr.de> boyom
|
||||
Andreas Gaubatz <andreas.gaubatz@uni-dortmund.de> agaubatz
|
||||
Maik Drozdzynski <maik.drozdzynski@uni-dortmund.de> der_maik81
|
||||
Miguel Liebe <miguel@venta-com.de> miguelliebe
|
||||
Eric Nicolay <Eric.Nicolay@dlr.de> ericnicolay
|
||||
Axel Wegener <wegener@itm.uni-luebeck.de> awegener
|
||||
Thimor Bohn <bohn@itm.uni-luebeck.de> t-bohn
|
||||
Felix Brack <fb@ltec.ch> fxrb
|
||||
Michael Behrisch <oss@behrisch.de> behrisch
|
||||
Yun-Pang Floetteroed <Yun-Pang.Floetteroed@dlr.de> yunpangwang
|
||||
Ronald Nippold <Ronald.Nippold@dlr.de> ronald_nippold
|
||||
Friedemann Wesner <wesner@itm.uni-luebeck.de> fwesner
|
||||
Tino Morenz <morenzt@tcd.ie> morenzt
|
||||
Christoph Sommer <christoph.sommer@informatik.uni-erlangen.de> sommerc
|
||||
Bjoern Hendriks <bjhend@users.sf.net> bjhend
|
||||
Sascha Krieg <sascha.krieg@dlr.de> SaschaKrieg saschaKrieg
|
||||
Clemens Honomichl <c.honomichl@googlemail.com> chonomichl
|
||||
Matthias Heppner <matthias@highmarket.de> heppa
|
||||
Lena Kalleske <Lena.Kalleske@dlr.de> kalleske
|
||||
Christian Schmidt <ch.schmidt@dlr.de> cschmidt87
|
||||
Matthew Fullerton <matthew.fullerton@tum.de> fullerton
|
||||
Walter Bamberger <w.bamberger@arcor.de> simsiem w-bamberger
|
||||
Piotr Woznica <piwoz@users.sf.net> piwoz
|
||||
Tobias Mayer <mayer.tobias (at) web.de>
|
||||
Laura Bieker-Walz <laura.bieker@dlr.de> bieker
|
||||
Matthias Roeckl <mroeckl@users.sf.net> mroeckl
|
||||
Jakob Erdmann <jakob.erdmann@dlr.de> namdre
|
||||
Jerome Haerri <haerri@users.sf.net> haerri
|
||||
Karol Stosiek <kstosiek@users.sf.net> kstosiek
|
||||
Maximilian Wittmann <wittmannxam@live.de> wittmax
|
||||
Marek Heinrich <marek.heinrich@dlr.de> mahei
|
||||
Melanie Weber <melanie.weber@dlr.de> mknocke
|
||||
Mario Krumnow <Mario.Krumnow@tu-dresden.de> mkrumnow
|
||||
Riccardo Belletti <riccardo.belletti2@studio.unibo.it> rickybo89
|
||||
Anna Chiara Bellini <acbellini@users.sf.net> acbellini
|
||||
Alessio Bonfietti <alessio.bonfietti@unibo.it> bonfioale
|
||||
Federico Caselli <f.caselli@unibo.it> fcaselli-it
|
||||
Robbin Blokpoel <robbin.blokpoel@imtech.com> rblokpoel
|
||||
Nikolaus Furian <furian@ivt.tugraz.at> nikolausfurian
|
||||
Gianfilippo Slager
|
||||
Sandesh Uppoor <suppoor@gmail.com> suppoor
|
||||
Matthias Wagner <Matthias.Wagner@dlr.de> mwagner
|
||||
Mathew Robertson
|
||||
Bill Baxter
|
||||
Lyle Johnson
|
||||
Peter Wagner <peter.wagner@dlr.de> piwagner
|
||||
Eric Melde <eric.melde@dlr.de> melde
|
||||
Evamarie Wiessner
|
||||
Andreas Kendziorra <andreas.kendziorra@dlr.de> kend-an
|
||||
Robert Hilbrich <robert.hilbrich@dlr.de> rhilbrich
|
||||
Thomas Lockhart <Thomas.G.Lockhart@jpl.nasa.gov>
|
||||
Gerald Richter <Gerald.Richter@ait.ac.at> ait-mob-dts
|
||||
Lukas Grohmann <Lukas.Grohmann@ait.ac.at>
|
||||
Tamas Kurczveil <kurczveil@iva.ing.tu-bs.de> emilkur
|
||||
Pablo Alvarez Lopez <pablo.alvarezlopez@dlr.de> palcraft
|
||||
Joerg Schweizer <joerg.schweizer@unibo.it> joerg-schweizer
|
||||
Mirco Sturari <m.sturari@pm.univpm.it> mircosturari
|
||||
Martin Dippold <dippold@ivt.tugraz.at>
|
||||
Gregor Laemmel <gregor.laemmel@dlr.de> laemmel
|
||||
Leonhard Luecken <leonhard.luecken@dlr.de> luecken
|
||||
Martin Taraz <martin@taraz.de> martintaraz
|
||||
Lara Codeca <lara.codeca@eurecom.fr>
|
||||
Matthias Schwamborn <matthias.schwamborn@dlr.de>
|
||||
Olaf Angelo Banse Bueno <Olaf.BanseBueno@dlr.de>
|
||||
Mirko Barthauer <m.barthauer@t-online.de>
|
||||
Michele Segata <segata@ccs-labs.org>
|
||||
Raphael Riebl <raphael.riebl@thi.de>
|
||||
Tarek Chouaki <tarek.chouaki@irt-systemx.fr>
|
||||
Tobias Jacobowitz <tobias.jacobowitz@posteo.de>
|
||||
Jim Div <div@thoda.uk>
|
||||
Maximiliano Bottazzi <maximiliano.bottazzi@dlr.de>
|
||||
Sebastian Ehmann <sebastian@dipolmoment.de>
|
|
@ -1,105 +0,0 @@
|
|||
# set VERSION to empty string
|
||||
cmake_policy(SET CMP0048 NEW)
|
||||
# do not expand quoted variables in if statements
|
||||
cmake_policy(SET CMP0054 NEW)
|
||||
# Options
|
||||
option(MULTITHREADED_BUILD "Use all available cores for building (applies to Visual Studio only)" true)
|
||||
option(PROFILING "Enable output of profiling data (applies to gcc/clang builds only)" false)
|
||||
set(BINARY_SUFFIX "" CACHE STRING "Append the suffix to every generated binary")
|
||||
set(COMPILE_DEFINITIONS "" CACHE STRING "Macros or defines to add when compiling")
|
||||
|
||||
# Set a default build type if none was specified
|
||||
# you may use -DCMAKE_BUILD_TYPE:STRING=Debug from the command line
|
||||
set(default_build_type "Release")
|
||||
|
||||
if (NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
message(STATUS "Setting build type to '${default_build_type}' as none was specified.")
|
||||
set(CMAKE_BUILD_TYPE "${default_build_type}" CACHE
|
||||
STRING "Choose the type of build." FORCE)
|
||||
# Set the possible values of build type for cmake-gui
|
||||
set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS "Debug" "Release")
|
||||
endif ()
|
||||
|
||||
project(SUMO)
|
||||
set(PACKAGE_VERSION "git")
|
||||
cmake_minimum_required(VERSION 3.1)
|
||||
|
||||
set(CMAKE_COLOR_MAKEFILE ON)
|
||||
set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake_modules/")
|
||||
|
||||
set(ENABLED_FEATURES "${CMAKE_SYSTEM} ${CMAKE_SYSTEM_PROCESSOR} ${CMAKE_CXX_COMPILER_ID} ${CMAKE_CXX_COMPILER_VERSION} ${CMAKE_BUILD_TYPE}")
|
||||
|
||||
if (COMPILE_DEFINITIONS)
|
||||
add_compile_definitions(${COMPILE_DEFINITIONS})
|
||||
endif ()
|
||||
|
||||
# compiler specific flags
|
||||
if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang")
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++11 -pthread -Wall -pedantic -Wextra -fPIC")
|
||||
elseif (MSVC)
|
||||
# enabling /WX is not possible due to warnings in external headers
|
||||
# /Wall brings MSVC 2013 to complete halt
|
||||
if (MULTITHREADED_BUILD)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
|
||||
endif ()
|
||||
if (MSVC_VERSION GREATER 1914)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /experimental:external /external:W2")
|
||||
set(CMAKE_INCLUDE_SYSTEM_FLAG_CXX "/external:I ")
|
||||
endif ()
|
||||
# exporting symbols for shared libraries needs to enabled explicitly
|
||||
set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS ON)
|
||||
endif ()
|
||||
|
||||
# force Visual Studio to leave out the Release / Debug dirs
|
||||
# Debug messages
|
||||
message(STATUS "CMAKE_BINARY_DIR: " ${CMAKE_BINARY_DIR})
|
||||
message(STATUS "CMAKE_SOURCE_DIR: " ${CMAKE_SOURCE_DIR})
|
||||
message(STATUS "")
|
||||
message(STATUS "Platform: ")
|
||||
message(STATUS " Host: " ${CMAKE_HOST_SYSTEM} " " ${CMAKE_HOST_SYSTEM_PROCESSOR})
|
||||
message(STATUS " Target: " ${CMAKE_SYSTEM} " " ${CMAKE_SYSTEM_PROCESSOR})
|
||||
message(STATUS " CMake: " ${CMAKE_VERSION})
|
||||
message(STATUS " CMake generator: " ${CMAKE_GENERATOR})
|
||||
message(STATUS " CMake build tool: " ${CMAKE_BUILD_TOOL})
|
||||
message(STATUS " Compiler: " ${CMAKE_CXX_COMPILER_ID} " " ${CMAKE_CXX_COMPILER_VERSION})
|
||||
if (CMAKE_GENERATOR MATCHES Xcode)
|
||||
message(STATUS " Xcode: " ${XCODE_VERSION})
|
||||
endif ()
|
||||
message(STATUS "")
|
||||
|
||||
find_package(Proj)
|
||||
if (PROJ_FOUND)
|
||||
include_directories(SYSTEM ${PROJ_INCLUDE_DIR})
|
||||
set(ENABLED_FEATURES "${ENABLED_FEATURES} Proj")
|
||||
endif (PROJ_FOUND)
|
||||
|
||||
set(XERCES_PATH "../../Build/xerces-c-3.2.3-install")
|
||||
set(XercesC_INCLUDE_DIR "${XERCES_PATH}/include")
|
||||
set(XercesC_LIBRARY "${XERCES_PATH}/lib")
|
||||
# Install xercesc
|
||||
file(GLOB XERCES_LIBS "${XercesC_LIBRARY}/*.*")
|
||||
install(FILES ${XERCES_LIBS} DESTINATION lib)
|
||||
find_package(XercesC REQUIRED)
|
||||
if (XercesC_FOUND)
|
||||
include_directories(SYSTEM ${XercesC_INCLUDE_DIRS})
|
||||
endif (XercesC_FOUND)
|
||||
|
||||
find_package(X11)
|
||||
if (X11_FOUND)
|
||||
link_directories(${X11_LIBRARY_DIR})
|
||||
include_directories(SYSTEM ${X11_INCLUDE_DIR})
|
||||
endif (X11_FOUND)
|
||||
|
||||
find_package(ZLIB)
|
||||
if (ZLIB_FOUND)
|
||||
set(HAVE_ZLIB 1)
|
||||
link_directories(${ZLIB_LIBRARY_DIR})
|
||||
include_directories(SYSTEM ${ZLIB_INCLUDE_DIR})
|
||||
endif ()
|
||||
|
||||
include_directories(${CMAKE_CURRENT_BINARY_DIR}/src)
|
||||
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
|
||||
add_subdirectory(src)
|
||||
|
||||
message(STATUS "Enabled features: ${ENABLED_FEATURES}")
|
|
@ -1,40 +0,0 @@
|
|||
{
|
||||
"configurations": [
|
||||
{
|
||||
"name": "x64-Debug",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Debug",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
},
|
||||
{
|
||||
"name": "x64-Release",
|
||||
"generator": "Ninja",
|
||||
"configurationType": "Release",
|
||||
"buildRoot": "${projectDir}\\out\\build\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "-v",
|
||||
"ctestCommandArgs": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"variables": []
|
||||
},
|
||||
{
|
||||
"name": "VisualStudio2019-x64",
|
||||
"generator": "Visual Studio 16 2019 Win64",
|
||||
"configurationType": "",
|
||||
"inheritEnvironments": [ "msvc_x64_x64" ],
|
||||
"buildRoot": "${projectDir}\\out\\${name}",
|
||||
"installRoot": "${projectDir}\\out\\install\\${name}",
|
||||
"cmakeCommandArgs": "",
|
||||
"buildCommandArgs": "",
|
||||
"ctestCommandArgs": "",
|
||||
"variables": []
|
||||
}
|
||||
]
|
||||
}
|
|
@ -1,277 +0,0 @@
|
|||
Eclipse Public License - v 2.0
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS ECLIPSE
|
||||
PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION
|
||||
OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a) in the case of the initial Contributor, the initial content
|
||||
Distributed under this Agreement, and
|
||||
|
||||
b) in the case of each subsequent Contributor:
|
||||
i) changes to the Program, and
|
||||
ii) additions to the Program;
|
||||
where such changes and/or additions to the Program originate from
|
||||
and are Distributed by that particular Contributor. A Contribution
|
||||
"originates" from a Contributor if it was added to the Program by
|
||||
such Contributor itself or anyone acting on such Contributor's behalf.
|
||||
Contributions do not include changes or additions to the Program that
|
||||
are not Modified Works.
|
||||
|
||||
"Contributor" means any person or entity that Distributes the Program.
|
||||
|
||||
"Licensed Patents" mean patent claims licensable by a Contributor which
|
||||
are necessarily infringed by the use or sale of its Contribution alone
|
||||
or when combined with the Program.
|
||||
|
||||
"Program" means the Contributions Distributed in accordance with this
|
||||
Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement
|
||||
or any Secondary License (as applicable), including Contributors.
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source Code or other
|
||||
form, that is based on (or derived from) the Program and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship.
|
||||
|
||||
"Modified Works" shall mean any work in Source Code or other form that
|
||||
results from an addition to, deletion from, or modification of the
|
||||
contents of the Program, including, for purposes of clarity any new file
|
||||
in Source Code form that contains any contents of the Program. Modified
|
||||
Works shall not include works that contain only declarations,
|
||||
interfaces, types, classes, structures, or files of the Program solely
|
||||
in each case in order to link to, bind by name, or subclass the Program
|
||||
or Modified Works thereof.
|
||||
|
||||
"Distribute" means the acts of a) distributing or b) making available
|
||||
in any manner that enables the transfer of a copy.
|
||||
|
||||
"Source Code" means the form of a Program preferred for making
|
||||
modifications, including but not limited to software source code,
|
||||
documentation source, and configuration files.
|
||||
|
||||
"Secondary License" means either the GNU General Public License,
|
||||
Version 2.0, or any later versions of that license, including any
|
||||
exceptions or additional permissions as identified by the initial
|
||||
Contributor.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free copyright
|
||||
license to reproduce, prepare Derivative Works of, publicly display,
|
||||
publicly perform, Distribute and sublicense the Contribution of such
|
||||
Contributor, if any, and such Derivative Works.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby
|
||||
grants Recipient a non-exclusive, worldwide, royalty-free patent
|
||||
license under Licensed Patents to make, use, sell, offer to sell,
|
||||
import and otherwise transfer the Contribution of such Contributor,
|
||||
if any, in Source Code or other form. This patent license shall
|
||||
apply to the combination of the Contribution and the Program if, at
|
||||
the time the Contribution is added by the Contributor, such addition
|
||||
of the Contribution causes such combination to be covered by the
|
||||
Licensed Patents. The patent license shall not apply to any other
|
||||
combinations which include the Contribution. No hardware per se is
|
||||
licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the
|
||||
licenses to its Contributions set forth herein, no assurances are
|
||||
provided by any Contributor that the Program does not infringe the
|
||||
patent or other intellectual property rights of any other entity.
|
||||
Each Contributor disclaims any liability to Recipient for claims
|
||||
brought by any other entity based on infringement of intellectual
|
||||
property rights or otherwise. As a condition to exercising the
|
||||
rights and licenses granted hereunder, each Recipient hereby
|
||||
assumes sole responsibility to secure any other intellectual
|
||||
property rights needed, if any. For example, if a third party
|
||||
patent license is required to allow Recipient to Distribute the
|
||||
Program, it is Recipient's responsibility to acquire that license
|
||||
before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has
|
||||
sufficient copyright rights in its Contribution, if any, to grant
|
||||
the copyright license set forth in this Agreement.
|
||||
|
||||
e) Notwithstanding the terms of any Secondary License, no
|
||||
Contributor makes additional grants to any Recipient (other than
|
||||
those set forth in this Agreement) as a result of such Recipient's
|
||||
receipt of the Program under the terms of a Secondary License
|
||||
(if permitted under the terms of Section 3).
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
3.1 If a Contributor Distributes the Program in any form, then:
|
||||
|
||||
a) the Program must also be made available as Source Code, in
|
||||
accordance with section 3.2, and the Contributor must accompany
|
||||
the Program with a statement that the Source Code for the Program
|
||||
is available under this Agreement, and informs Recipients how to
|
||||
obtain it in a reasonable manner on or through a medium customarily
|
||||
used for software exchange; and
|
||||
|
||||
b) the Contributor may Distribute the Program under a license
|
||||
different than this Agreement, provided that such license:
|
||||
i) effectively disclaims on behalf of all other Contributors all
|
||||
warranties and conditions, express and implied, including
|
||||
warranties or conditions of title and non-infringement, and
|
||||
implied warranties or conditions of merchantability and fitness
|
||||
for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all other Contributors all
|
||||
liability for damages, including direct, indirect, special,
|
||||
incidental and consequential damages, such as lost profits;
|
||||
|
||||
iii) does not attempt to limit or alter the recipients' rights
|
||||
in the Source Code under section 3.2; and
|
||||
|
||||
iv) requires any subsequent distribution of the Program by any
|
||||
party to be under a license that satisfies the requirements
|
||||
of this section 3.
|
||||
|
||||
3.2 When the Program is Distributed as Source Code:
|
||||
|
||||
a) it must be made available under this Agreement, or if the
|
||||
Program (i) is combined with other material in a separate file or
|
||||
files made available under a Secondary License, and (ii) the initial
|
||||
Contributor attached to the Source Code the notice described in
|
||||
Exhibit A of this Agreement, then the Program may be made available
|
||||
under the terms of such Secondary Licenses, and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of
|
||||
the Program.
|
||||
|
||||
3.3 Contributors may not remove or alter any copyright, patent,
|
||||
trademark, attribution notices, disclaimers of warranty, or limitations
|
||||
of liability ("notices") contained within the Program from any copy of
|
||||
the Program which they Distribute, provided that Contributors may add
|
||||
their own appropriate notices.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities
|
||||
with respect to end users, business partners and the like. While this
|
||||
license is intended to facilitate the commercial use of the Program,
|
||||
the Contributor who includes the Program in a commercial product
|
||||
offering should do so in a manner which does not create potential
|
||||
liability for other Contributors. Therefore, if a Contributor includes
|
||||
the Program in a commercial product offering, such Contributor
|
||||
("Commercial Contributor") hereby agrees to defend and indemnify every
|
||||
other Contributor ("Indemnified Contributor") against any losses,
|
||||
damages and costs (collectively "Losses") arising from claims, lawsuits
|
||||
and other legal actions brought by a third party against the Indemnified
|
||||
Contributor to the extent caused by the acts or omissions of such
|
||||
Commercial Contributor in connection with its distribution of the Program
|
||||
in a commercial product offering. The obligations in this section do not
|
||||
apply to any claims or Losses relating to any actual or alleged
|
||||
intellectual property infringement. In order to qualify, an Indemnified
|
||||
Contributor must: a) promptly notify the Commercial Contributor in
|
||||
writing of such claim, and b) allow the Commercial Contributor to control,
|
||||
and cooperate with the Commercial Contributor in, the defense and any
|
||||
related settlement negotiations. The Indemnified Contributor may
|
||||
participate in any such claim at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial
|
||||
product offering, Product X. That Contributor is then a Commercial
|
||||
Contributor. If that Commercial Contributor then makes performance
|
||||
claims, or offers warranties related to Product X, those performance
|
||||
claims and warranties are such Commercial Contributor's responsibility
|
||||
alone. Under this section, the Commercial Contributor would have to
|
||||
defend claims against the other Contributors related to those performance
|
||||
claims and warranties, and if a court requires any other Contributor to
|
||||
pay any damages as a result, the Commercial Contributor must pay
|
||||
those damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, THE PROGRAM IS PROVIDED ON AN "AS IS"
|
||||
BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR
|
||||
IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF
|
||||
TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR
|
||||
PURPOSE. Each Recipient is solely responsible for determining the
|
||||
appropriateness of using and distributing the Program and assumes all
|
||||
risks associated with its exercise of rights under this Agreement,
|
||||
including but not limited to the risks and costs of program errors,
|
||||
compliance with applicable laws, damage to or loss of data, programs
|
||||
or equipment, and unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, AND TO THE EXTENT
|
||||
PERMITTED BY APPLICABLE LAW, NEITHER RECIPIENT NOR ANY CONTRIBUTORS
|
||||
SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST
|
||||
PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE
|
||||
EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under
|
||||
applicable law, it shall not affect the validity or enforceability of
|
||||
the remainder of the terms of this Agreement, and without further
|
||||
action by the parties hereto, such provision shall be reformed to the
|
||||
minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against any entity
|
||||
(including a cross-claim or counterclaim in a lawsuit) alleging that the
|
||||
Program itself (excluding combinations of the Program with other software
|
||||
or hardware) infringes such Recipient's patent(s), then such Recipient's
|
||||
rights granted under Section 2(b) shall terminate as of the date such
|
||||
litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it
|
||||
fails to comply with any of the material terms or conditions of this
|
||||
Agreement and does not cure such failure in a reasonable period of
|
||||
time after becoming aware of such noncompliance. If all Recipient's
|
||||
rights under this Agreement terminate, Recipient agrees to cease use
|
||||
and distribution of the Program as soon as reasonably practicable.
|
||||
However, Recipient's obligations under this Agreement and any licenses
|
||||
granted by Recipient relating to the Program shall continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement,
|
||||
but in order to avoid inconsistency the Agreement is copyrighted and
|
||||
may only be modified in the following manner. The Agreement Steward
|
||||
reserves the right to publish new versions (including revisions) of
|
||||
this Agreement from time to time. No one other than the Agreement
|
||||
Steward has the right to modify this Agreement. The Eclipse Foundation
|
||||
is the initial Agreement Steward. The Eclipse Foundation may assign the
|
||||
responsibility to serve as the Agreement Steward to a suitable separate
|
||||
entity. Each new version of the Agreement will be given a distinguishing
|
||||
version number. The Program (including Contributions) may always be
|
||||
Distributed subject to the version of the Agreement under which it was
|
||||
received. In addition, after a new version of the Agreement is published,
|
||||
Contributor may elect to Distribute the Program (including its
|
||||
Contributions) under the new version.
|
||||
|
||||
Except as expressly stated in Sections 2(a) and 2(b) above, Recipient
|
||||
receives no rights or licenses to the intellectual property of any
|
||||
Contributor under this Agreement, whether expressly, by implication,
|
||||
estoppel or otherwise. All rights in the Program not expressly granted
|
||||
under this Agreement are reserved. Nothing in this Agreement is intended
|
||||
to be enforceable by any entity that is not a Contributor or Recipient.
|
||||
No third-party beneficiary rights are created under this Agreement.
|
||||
|
||||
Exhibit A - Form of Secondary Licenses Notice
|
||||
|
||||
"This Source Code may also be made available under the following
|
||||
Secondary Licenses when the conditions for such availability set forth
|
||||
in the Eclipse Public License, v. 2.0 are satisfied: {name license(s),
|
||||
version(s), and exceptions or additional permissions here}."
|
||||
|
||||
Simply including a copy of this Agreement, including this Exhibit A
|
||||
is not sufficient to license the Source Code under Secondary Licenses.
|
||||
|
||||
If it is not possible or desirable to put the notice in a particular
|
||||
file, then You may include the notice in a location (such as a LICENSE
|
||||
file in a relevant directory) where a recipient would be likely to
|
||||
look for such a notice.
|
||||
|
||||
You may add additional accurate notices of copyright ownership.
|
|
@ -1,30 +0,0 @@
|
|||
buildType:
|
||||
default: debug
|
||||
description: My option
|
||||
choices:
|
||||
debug:
|
||||
short: Debug
|
||||
long: Build with debug info
|
||||
buildType: Debug
|
||||
release:
|
||||
short: Release
|
||||
long: Optimize binaries
|
||||
buildType: Release
|
||||
|
||||
useFMI:
|
||||
default: 'no'
|
||||
description: My option
|
||||
choices:
|
||||
'yes':
|
||||
short: FMI
|
||||
long: Enable the use of FMI
|
||||
settings:
|
||||
FMI: 'yes'
|
||||
'no':
|
||||
short: 'No FMI'
|
||||
long: Do not build the FMI library
|
||||
settings:
|
||||
FMI: 'no'
|
||||
|
||||
|
||||
|
|
@ -1,97 +0,0 @@
|
|||
# Source: https://github.com/qgis/QGIS/blob/3b3f6748f1e5e8f77fa87477add360ec0203fb26/cmake/FindProj.cmake
|
||||
# Changes: included BSD license text
|
||||
|
||||
# Find Proj
|
||||
# ~~~~~~~~~
|
||||
# Copyright (c) 2007, Martin Dobias <wonder.sk at gmail.com>
|
||||
# Redistribution and use is allowed according to the terms of the BSD license.
|
||||
#
|
||||
#Redistribution and use in source and binary forms, with or without
|
||||
#modification, are permitted provided that the following conditions
|
||||
#are met:
|
||||
#
|
||||
#1. Redistributions of source code must retain the copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
#2. Redistributions in binary form must reproduce the copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#3. The name of the author may not be used to endorse or promote products
|
||||
# derived from this software without specific prior written permission.
|
||||
#
|
||||
#THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
||||
#IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
#OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
||||
#IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
#INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
||||
#NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
#DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
#THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
#(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
||||
#THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
# CMake module to search for Proj library
|
||||
#
|
||||
# If it's found it sets PROJ_FOUND to TRUE
|
||||
# and following variables are set:
|
||||
# PROJ_INCLUDE_DIR
|
||||
# PROJ_API_FILE
|
||||
# PROJ_LIBRARY
|
||||
|
||||
# FIND_PATH and FIND_LIBRARY normally search standard locations
|
||||
# before the specified paths. To search non-standard paths first,
|
||||
# FIND_* is invoked first with specified paths and NO_DEFAULT_PATH
|
||||
# and then again with no specified paths to search the default
|
||||
# locations. When an earlier FIND_* succeeds, subsequent FIND_*s
|
||||
# searching for the same item do nothing.
|
||||
|
||||
# try to use framework on mac
|
||||
# want clean framework path, not unix compatibility path
|
||||
IF (APPLE)
|
||||
IF (CMAKE_FIND_FRAMEWORK MATCHES "FIRST"
|
||||
OR CMAKE_FRAMEWORK_PATH MATCHES "ONLY"
|
||||
OR NOT CMAKE_FIND_FRAMEWORK)
|
||||
SET (CMAKE_FIND_FRAMEWORK_save ${CMAKE_FIND_FRAMEWORK} CACHE STRING "" FORCE)
|
||||
SET (CMAKE_FIND_FRAMEWORK "ONLY" CACHE STRING "" FORCE)
|
||||
#FIND_PATH(PROJ_INCLUDE_DIR PROJ/proj_api.h)
|
||||
FIND_LIBRARY(PROJ_LIBRARY PROJ)
|
||||
IF (PROJ_LIBRARY)
|
||||
# FIND_PATH doesn't add "Headers" for a framework
|
||||
SET (PROJ_INCLUDE_DIR ${PROJ_LIBRARY}/Headers CACHE PATH "Path to a file.")
|
||||
ENDIF (PROJ_LIBRARY)
|
||||
SET (CMAKE_FIND_FRAMEWORK ${CMAKE_FIND_FRAMEWORK_save} CACHE STRING "" FORCE)
|
||||
ENDIF ()
|
||||
ENDIF (APPLE)
|
||||
|
||||
FIND_PATH(PROJ_INCLUDE_DIR NAMES proj.h proj_api.h PATHS
|
||||
"$ENV{INCLUDE}"
|
||||
"$ENV{LIB_DIR}/include"
|
||||
"$ENV{GDAL_DIR}/include"
|
||||
)
|
||||
|
||||
FIND_LIBRARY(PROJ_LIBRARY NAMES proj_i proj proj_6_1 PATHS
|
||||
"$ENV{LIB}"
|
||||
"$ENV{LIB_DIR}/lib"
|
||||
"$ENV{GDAL_DIR}/lib"
|
||||
)
|
||||
|
||||
IF (PROJ_INCLUDE_DIR AND PROJ_LIBRARY)
|
||||
SET(PROJ_FOUND TRUE)
|
||||
IF (EXISTS "${PROJ_INCLUDE_DIR}/proj.h")
|
||||
SET(PROJ_API_FILE "proj.h")
|
||||
ELSE ()
|
||||
SET(PROJ_API_FILE "proj_api.h")
|
||||
ENDIF ()
|
||||
IF (NOT PROJ_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Found Proj: ${PROJ_LIBRARY}")
|
||||
ENDIF (NOT PROJ_FIND_QUIETLY)
|
||||
ELSE ()
|
||||
SET(PROJ_FOUND FALSE)
|
||||
SET(PROJ_LIBRARY "")
|
||||
IF (PROJ_FIND_REQUIRED)
|
||||
MESSAGE(FATAL_ERROR "Could not find Proj")
|
||||
ELSE ()
|
||||
IF (NOT PROJ_FIND_QUIETLY)
|
||||
MESSAGE(STATUS "Could NOT find Proj")
|
||||
ENDIF (NOT PROJ_FIND_QUIETLY)
|
||||
ENDIF (PROJ_FIND_REQUIRED)
|
||||
ENDIF ()
|
|
@ -1,66 +0,0 @@
|
|||
set(osm2odr_sources "OSM2ODR.cpp")
|
||||
|
||||
configure_file(config.h.cmake config.h)
|
||||
|
||||
if (EXISTS "${CMAKE_CURRENT_SOURCE_DIR}/../.git")
|
||||
set(VERSION_DEP "${CMAKE_CURRENT_SOURCE_DIR}/../.git")
|
||||
endif()
|
||||
|
||||
file(GLOB netbuild_sources "netbuild/*.cpp" "netbuild/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netbuild_sources}")
|
||||
|
||||
file(GLOB netimport_sources "netimport/*.cpp" "netimport/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netimport_sources}")
|
||||
|
||||
file(GLOB netimport_vissim_sources "netimport/vissim/*.cpp" "netimport/vissim/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netimport_vissim_sources}")
|
||||
|
||||
file(GLOB netimport_vissim_tempstructs_sources "netimport/vissim/tempstructs/*.cpp" "netimport/vissim/tempstructs/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netimport_vissim_tempstructs_sources}")
|
||||
|
||||
file(GLOB netimport_vissim_typeloader_sources "netimport/vissim/typeloader/*.cpp" "netimport/vissim/typeloader/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netimport_vissim_typeloader_sources}")
|
||||
|
||||
file(GLOB netwrite_sources "netwrite/*.cpp" "netwrite/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${netwrite_sources}")
|
||||
|
||||
file(GLOB foreign_eulerspiral_sources "foreign/eulerspiral/*.cpp" "foreign/eulerspiral/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${foreign_eulerspiral_sources}")
|
||||
|
||||
file(GLOB foreign_tcpip_sources "foreign/tcpip/*.cpp" "foreign/tcpip/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${foreign_tcpip_sources}")
|
||||
|
||||
file(GLOB utils_common_sources "utils/common/*.cpp" "utils/common/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_common_sources}")
|
||||
|
||||
file(GLOB utils_distribution_sources "utils/distribution/*.cpp" "utils/distribution/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_distribution_sources}")
|
||||
|
||||
file(GLOB utils_shapes_sources "utils/shapes/*.cpp" "utils/shapes/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_shapes_sources}")
|
||||
|
||||
file(GLOB utils_options_sources "utils/options/*.cpp" "utils/options/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_options_sources}")
|
||||
|
||||
file(GLOB utils_xml_sources "utils/xml/*.cpp" "utils/xml/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_xml_sources}")
|
||||
|
||||
file(GLOB utils_geom_sources "utils/geom/*.cpp" "utils/geom/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_geom_sources}")
|
||||
|
||||
file(GLOB utils_importio_sources "utils/importio/*.cpp" "utils/importio/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_importio_sources}")
|
||||
|
||||
file(GLOB utils_iodevices_sources "utils/iodevices/*.cpp" "utils/iodevices/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_iodevices_sources}")
|
||||
|
||||
file(GLOB utils_traction_wire_sources "utils/traction_wire/*.cpp" "utils/traction_wire/*.h")
|
||||
set(osm2odr_sources "${osm2odr_sources};${utils_traction_wire_sources}")
|
||||
|
||||
add_library(osm2odr STATIC ${osm2odr_sources})
|
||||
target_link_libraries(osm2odr ${XercesC_LIBRARIES} ${ZLIB_LIBRARIES} ${PROJ_LIBRARY})
|
||||
|
||||
target_compile_definitions(osm2odr PUBLIC "XERCES_STATIC_LIBRARY")
|
||||
|
||||
install(TARGETS osm2odr ARCHIVE DESTINATION lib)
|
||||
install(FILES OSM2ODR.h DESTINATION include)
|
|
@ -1,143 +0,0 @@
|
|||
// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#include "OSM2ODR.h"
|
||||
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <netimport/NIFrame.h>
|
||||
#include <netimport/NILoader.h>
|
||||
#include <netbuild/NBFrame.h>
|
||||
#include <netbuild/NBNetBuilder.h>
|
||||
#include <netwrite/NWFrame.h>
|
||||
#include <utils/options/OptionsIO.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/common/RandHelper.h>
|
||||
#include <utils/common/SystemFrame.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/distribution/DistributionCont.h>
|
||||
#include <utils/xml/XMLSubSys.h>
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include <utils/geom/GeoConvHelper.h>
|
||||
|
||||
|
||||
namespace osm2odr {
|
||||
|
||||
void fillOptions() {
|
||||
OptionsCont& oc = OptionsCont::getOptions();
|
||||
oc.addCallExample("-c <CONFIGURATION>", "generate net with options read from file");
|
||||
oc.addCallExample("-n ./nodes.xml -e ./edges.xml -v -t ./owntypes.xml",
|
||||
"generate net with given nodes, edges, and edge types doing verbose output");
|
||||
// insert options sub-topics
|
||||
SystemFrame::addConfigurationOptions(oc); // this subtopic is filled here, too
|
||||
oc.addOptionSubTopic("Input");
|
||||
oc.addOptionSubTopic("Output");
|
||||
GeoConvHelper::addProjectionOptions(oc);
|
||||
oc.addOptionSubTopic("Processing");
|
||||
oc.addOptionSubTopic("Building Defaults");
|
||||
oc.addOptionSubTopic("TLS Building");
|
||||
oc.addOptionSubTopic("Ramp Guessing");
|
||||
oc.addOptionSubTopic("Edge Removal");
|
||||
oc.addOptionSubTopic("Unregulated Nodes");
|
||||
oc.addOptionSubTopic("Junctions");
|
||||
oc.addOptionSubTopic("Pedestrian");
|
||||
oc.addOptionSubTopic("Bicycle");
|
||||
oc.addOptionSubTopic("Railway");
|
||||
oc.addOptionSubTopic("Formats");
|
||||
SystemFrame::addReportOptions(oc); // this subtopic is filled here, too
|
||||
|
||||
NIFrame::fillOptions();
|
||||
NBFrame::fillOptions(false);
|
||||
NWFrame::fillOptions(false);
|
||||
RandHelper::insertRandOptions();
|
||||
}
|
||||
|
||||
|
||||
bool checkOptions() {
|
||||
bool ok = NIFrame::checkOptions();
|
||||
ok &= NBFrame::checkOptions();
|
||||
ok &= NWFrame::checkOptions();
|
||||
ok &= SystemFrame::checkOptions();
|
||||
return ok;
|
||||
}
|
||||
|
||||
std::string ConvertOSMToOpenDRIVE(std::string osm_file, OSM2ODRSettings settings) {
|
||||
std::vector<std::string> OptionsArgs = {
|
||||
"--proj", settings.proj_string,
|
||||
"--geometry.remove", "--ramps.guess", "--edges.join", "--junctions.join", "--roundabouts.guess",
|
||||
"--keep-edges.by-type",
|
||||
"highway.motorway,highway.motorway_link,highway.trunk,highway.trunk_link,highway.primary,highway.primary_link,highway.secondary,highway.secondary_link,highway.tertiary,highway.tertiary_link,highway.unclassified,highway.residential",
|
||||
"--tls.discard-loaded", "--tls.discard-simple", "--default.lanewidth",
|
||||
std::to_string(settings.default_lane_width),
|
||||
"--osm-files", "TRUE", "--opendrive-output", "TRUE", // necessary for now to enable osm input and xodr output
|
||||
};
|
||||
if (settings.elevation_layer_height > 0) {
|
||||
OptionsArgs.emplace_back("--osm.layer-elevation");
|
||||
OptionsArgs.emplace_back(std::to_string(settings.elevation_layer_height));
|
||||
}
|
||||
if (settings.use_offsets) {
|
||||
OptionsArgs.emplace_back("--offset.x");
|
||||
OptionsArgs.emplace_back(std::to_string(settings.offset_x));
|
||||
OptionsArgs.emplace_back("--offset.y");
|
||||
OptionsArgs.emplace_back(std::to_string(settings.offset_y));
|
||||
}
|
||||
if (!settings.center_map) {
|
||||
OptionsArgs.emplace_back("--offset.disable-normalization");
|
||||
OptionsArgs.emplace_back("true");
|
||||
}
|
||||
|
||||
// OptionsCont::getOptions().clear();
|
||||
OptionsCont& oc = OptionsCont::getOptions();
|
||||
oc.input_osm_file = osm_file;
|
||||
|
||||
XMLSubSys::init();
|
||||
fillOptions();
|
||||
OptionsIO::setArgs(OptionsArgs);
|
||||
OptionsIO::getOptions();
|
||||
if (oc.processMetaOptions(OptionsArgs.size() < 2)) {
|
||||
SystemFrame::close();
|
||||
return 0;
|
||||
}
|
||||
XMLSubSys::setValidation(oc.getString("xml-validation"), oc.getString("xml-validation.net"));
|
||||
if (oc.isDefault("aggregate-warnings")) {
|
||||
oc.set("aggregate-warnings", "5");
|
||||
}
|
||||
MsgHandler::initOutputOptions();
|
||||
if (!checkOptions()) {
|
||||
throw ProcessError();
|
||||
}
|
||||
RandHelper::initRandGlobal();
|
||||
// build the projection
|
||||
if (!GeoConvHelper::init(oc)) {
|
||||
throw ProcessError("Could not build projection!");
|
||||
}
|
||||
NBNetBuilder nb;
|
||||
nb.applyOptions(oc);
|
||||
// load data
|
||||
NILoader nl(nb);
|
||||
nl.load(oc);
|
||||
// flush aggregated errors and optionally ignore them
|
||||
MsgHandler::getErrorInstance()->clear(oc.getBool("ignore-errors"));
|
||||
// check whether any errors occurred
|
||||
if (MsgHandler::getErrorInstance()->wasInformed()) {
|
||||
throw ProcessError();
|
||||
}
|
||||
nb.compute(oc);
|
||||
// check whether any errors occurred
|
||||
if (MsgHandler::getErrorInstance()->wasInformed()) {
|
||||
throw ProcessError();
|
||||
}
|
||||
NWFrame::writeNetwork(oc, nb);
|
||||
|
||||
|
||||
DistributionCont::clear();
|
||||
SystemFrame::close();
|
||||
|
||||
return oc.output_xodr_file;
|
||||
}
|
||||
|
||||
} // namespace OSM2ODR
|
|
@ -1,25 +0,0 @@
|
|||
// Copyright (c) 2020 Computer Vision Center (CVC) at the Universitat Autonoma
|
||||
// de Barcelona (UAB).
|
||||
//
|
||||
// This work is licensed under the terms of the MIT license.
|
||||
// For a copy, see <https://opensource.org/licenses/MIT>.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace osm2odr {
|
||||
|
||||
struct OSM2ODRSettings {
|
||||
bool use_offsets = false;
|
||||
double offset_x = 0;
|
||||
double offset_y = 0;
|
||||
double default_lane_width = 4.0;
|
||||
double elevation_layer_height = 0;
|
||||
std::string proj_string = "+proj=tmerc";
|
||||
bool center_map = true;
|
||||
};
|
||||
|
||||
std::string ConvertOSMToOpenDRIVE(std::string osm_file, OSM2ODRSettings settings = OSM2ODRSettings());
|
||||
|
||||
} // namespace osm2odr
|
|
@ -1,46 +0,0 @@
|
|||
Please feel free to add and / or modify files here but keep in mind that
|
||||
EPL requires that "derivative works" be licensed under the terms of the EPL.
|
||||
If the extension is a separate module and is not published under the EPL
|
||||
it will not be adopted in the SUMO mainline repository.
|
||||
|
||||
Modifications to the files and directories listed here are considered _derivative work_:
|
||||
|
||||
- activitygen
|
||||
- dfrouter
|
||||
- duarouter
|
||||
- foreign
|
||||
- gui
|
||||
- guinetload
|
||||
- guisim
|
||||
- jtrrouter
|
||||
- marouter
|
||||
- mesogui
|
||||
- mesosim
|
||||
- microsim
|
||||
- netbuild
|
||||
- netedit
|
||||
- netgen
|
||||
- netimport
|
||||
- netload
|
||||
- netwrite
|
||||
- od
|
||||
- osgview
|
||||
- polyconvert
|
||||
- router
|
||||
- tools
|
||||
- traci-server
|
||||
- traci_testclient
|
||||
- utils
|
||||
- guisim_main.cpp
|
||||
- netconvert_main.cpp
|
||||
- od2trips_main.cpp
|
||||
- sumo_main.cpp
|
||||
|
||||
Directories containing interface code for _separate modules_ (with separate lists) are:
|
||||
|
||||
- car following models that inherit from MSCFModel (excluding [modifications of the existing models](microsim/cfmodels/README_Contributing.md))
|
||||
- lane changing models that inherit from MSAbstractLaneChangeModel (excluding [modifications of the existing models](microsim/lcmodels/README_Contributing.md))
|
||||
- simulation output modules (excluding [changes to the existing classes](microsim/output/README_Contributing.md))
|
||||
- vehicle device modules (excluding [changes to the existing classes](microsim/devices/README_Contributing.md))
|
||||
- network import modules (excluding [changes to the existing classes](netimport/README_Contributing.md))
|
||||
- network export modules (excluding [changes to the existing classes](netwrite/README_Contributing.md))
|
|
@ -1,109 +0,0 @@
|
|||
/* Macros for Microsoft Visual Studio */
|
||||
#ifdef _MSC_VER
|
||||
|
||||
/* Disable "decorated name length exceeded, name was truncated" warnings. */
|
||||
#pragma warning(disable: 4503)
|
||||
/* Disable "identifier truncated in debug info" warnings. */
|
||||
#pragma warning(disable: 4786)
|
||||
/* Disable "C++ Exception Specification ignored" warnings */
|
||||
#pragma warning(disable: 4290)
|
||||
/* Disable DLL-Interface warnings */
|
||||
#pragma warning(disable: 4251)
|
||||
/* Disable integer overflow in arithmetics warnings */
|
||||
#pragma warning(disable: 26451)
|
||||
|
||||
/* Disable "unsafe" warnings for crt functions in VC++ 2005. */
|
||||
#if _MSC_VER >= 1400
|
||||
#define _CRT_SECURE_NO_WARNINGS
|
||||
#endif
|
||||
|
||||
/* define WIN32 */
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
#endif
|
||||
|
||||
/* Define for dynamic Fox linkage */
|
||||
#define FOXDLL 1
|
||||
|
||||
/* define default constructor for FOX moduls (Visual Studio) */
|
||||
#define FOX_CONSTRUCTOR(classname) __pragma(warning(suppress: 26495)) \
|
||||
classname() {}
|
||||
|
||||
/* Macros for GNU Compiler */
|
||||
#else
|
||||
|
||||
/* defined if we're using MINGW32 */
|
||||
#cmakedefine MINGW32
|
||||
|
||||
/* Windows (MinGW32) */
|
||||
#ifdef MINGW32
|
||||
|
||||
/* Define WIN32 */
|
||||
#ifndef WIN32
|
||||
#define WIN32
|
||||
#endif
|
||||
|
||||
/* Define for dynamic Fox linkage */
|
||||
#define FOXDLL 1
|
||||
|
||||
/* Define default constructor for FOX moduls (MinGW32) */
|
||||
#define FOX_CONSTRUCTOR(classname) classname() {}
|
||||
|
||||
/* Linux and OS */
|
||||
#else
|
||||
|
||||
/* Define default constructor for FOX moduls (Linux and OS) */
|
||||
#define FOX_CONSTRUCTOR(classname) classname() {}
|
||||
|
||||
/* MinGW32 */
|
||||
#endif
|
||||
|
||||
/* Visual Studio */
|
||||
#endif
|
||||
|
||||
|
||||
/* Reporting string for enabled options */
|
||||
#define HAVE_ENABLED "@ENABLED_FEATURES@"
|
||||
|
||||
/* defined if Eigen is available */
|
||||
#cmakedefine HAVE_EIGEN
|
||||
|
||||
/* defined if ffmpeg is available */
|
||||
#cmakedefine HAVE_FFMPEG
|
||||
|
||||
/* defined if FOX is available */
|
||||
#cmakedefine HAVE_FOX
|
||||
|
||||
/* defined if GDAL is available */
|
||||
#cmakedefine HAVE_GDAL
|
||||
|
||||
/* defined if GL2PS is available */
|
||||
#cmakedefine HAVE_GL2PS
|
||||
|
||||
/* defined if osg is available */
|
||||
#cmakedefine HAVE_OSG
|
||||
|
||||
/* defined if zlib is available */
|
||||
#cmakedefine HAVE_ZLIB
|
||||
|
||||
/* set to proj.h, proj_api.h or empty depending on which proj is available */
|
||||
#cmakedefine PROJ_API_FILE "@PROJ_API_FILE@"
|
||||
|
||||
/* defined if python is available */
|
||||
#cmakedefine HAVE_PYTHON
|
||||
|
||||
/* Define if auto-generated version.h should be used. */
|
||||
#define HAVE_VERSION_H
|
||||
#ifndef HAVE_VERSION_H
|
||||
/* Define if auto-generated version.h is unavailable. */
|
||||
#define VERSION_STRING "1.6.0"
|
||||
#endif
|
||||
|
||||
/* defines the epsilon to use on general floating point comparison */
|
||||
#define NUMERICAL_EPS 0.001
|
||||
|
||||
/* defines the epsilon to use on position comparison */
|
||||
#define POSITION_EPS 0.1
|
||||
|
||||
/* Define length for Xerces 3. */
|
||||
#define XERCES3_SIZE_t XMLSize_t
|
|
@ -1,2 +0,0 @@
|
|||
add_subdirectory(tcpip)
|
||||
add_subdirectory(eulerspiral)
|
|
@ -1,7 +0,0 @@
|
|||
set(foreign_eulerspiral_STAT_SRCS
|
||||
odrSpiral.cpp
|
||||
odrSpiral.h
|
||||
)
|
||||
|
||||
add_library(foreign_eulerspiral STATIC ${foreign_eulerspiral_STAT_SRCS})
|
||||
set_property(TARGET foreign_eulerspiral PROPERTY PROJECT_LABEL "z_foreign_eulerspiral")
|
|
@ -1,201 +0,0 @@
|
|||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -1,247 +0,0 @@
|
|||
/* ===================================================
|
||||
* file: euler.h
|
||||
* ---------------------------------------------------
|
||||
* purpose: free method for computing spirals
|
||||
* in OpenDRIVE applications
|
||||
* ---------------------------------------------------
|
||||
* using methods of CEPHES library
|
||||
* ---------------------------------------------------
|
||||
* first edit: 09.03.2010 by M. Dupuis @ VIRES GmbH
|
||||
* last mod.: 02.05.2017 by Michael Scholz @ German Aerospace Center (DLR)
|
||||
* last mod.: 05.07.2017 by Jakob Erdmann @ German Aerospace Center (DLR)
|
||||
* ===================================================
|
||||
Copyright 2010 VIRES Simulationstechnologie GmbH
|
||||
Copyright 2017 German Aerospace Center (DLR)
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
|
||||
NOTE:
|
||||
The methods have been realized using the CEPHES library
|
||||
http://www.netlib.org/cephes/
|
||||
and do neither constitute the only nor the exclusive way of implementing
|
||||
spirals for OpenDRIVE applications. Their sole purpose is to facilitate
|
||||
the interpretation of OpenDRIVE spiral data.
|
||||
*/
|
||||
|
||||
/* ====== INCLUSIONS ====== */
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
/* ====== LOCAL VARIABLES ====== */
|
||||
#ifndef M_PI
|
||||
#define M_PI 3.1415926535897932384626433832795
|
||||
#endif
|
||||
|
||||
/* S(x) for small x */
|
||||
static double sn[6] = {
|
||||
-2.99181919401019853726E3,
|
||||
7.08840045257738576863E5,
|
||||
-6.29741486205862506537E7,
|
||||
2.54890880573376359104E9,
|
||||
-4.42979518059697779103E10,
|
||||
3.18016297876567817986E11,
|
||||
};
|
||||
static double sd[6] = {
|
||||
/* 1.00000000000000000000E0,*/
|
||||
2.81376268889994315696E2,
|
||||
4.55847810806532581675E4,
|
||||
5.17343888770096400730E6,
|
||||
4.19320245898111231129E8,
|
||||
2.24411795645340920940E10,
|
||||
6.07366389490084639049E11,
|
||||
};
|
||||
|
||||
/* C(x) for small x */
|
||||
static double cn[6] = {
|
||||
-4.98843114573573548651E-8,
|
||||
9.50428062829859605134E-6,
|
||||
-6.45191435683965050962E-4,
|
||||
1.88843319396703850064E-2,
|
||||
-2.05525900955013891793E-1,
|
||||
9.99999999999999998822E-1,
|
||||
};
|
||||
static double cd[7] = {
|
||||
3.99982968972495980367E-12,
|
||||
9.15439215774657478799E-10,
|
||||
1.25001862479598821474E-7,
|
||||
1.22262789024179030997E-5,
|
||||
8.68029542941784300606E-4,
|
||||
4.12142090722199792936E-2,
|
||||
1.00000000000000000118E0,
|
||||
};
|
||||
|
||||
/* Auxiliary function f(x) */
|
||||
static double fn[10] = {
|
||||
4.21543555043677546506E-1,
|
||||
1.43407919780758885261E-1,
|
||||
1.15220955073585758835E-2,
|
||||
3.45017939782574027900E-4,
|
||||
4.63613749287867322088E-6,
|
||||
3.05568983790257605827E-8,
|
||||
1.02304514164907233465E-10,
|
||||
1.72010743268161828879E-13,
|
||||
1.34283276233062758925E-16,
|
||||
3.76329711269987889006E-20,
|
||||
};
|
||||
static double fd[10] = {
|
||||
/* 1.00000000000000000000E0,*/
|
||||
7.51586398353378947175E-1,
|
||||
1.16888925859191382142E-1,
|
||||
6.44051526508858611005E-3,
|
||||
1.55934409164153020873E-4,
|
||||
1.84627567348930545870E-6,
|
||||
1.12699224763999035261E-8,
|
||||
3.60140029589371370404E-11,
|
||||
5.88754533621578410010E-14,
|
||||
4.52001434074129701496E-17,
|
||||
1.25443237090011264384E-20,
|
||||
};
|
||||
|
||||
/* Auxiliary function g(x) */
|
||||
static double gn[11] = {
|
||||
5.04442073643383265887E-1,
|
||||
1.97102833525523411709E-1,
|
||||
1.87648584092575249293E-2,
|
||||
6.84079380915393090172E-4,
|
||||
1.15138826111884280931E-5,
|
||||
9.82852443688422223854E-8,
|
||||
4.45344415861750144738E-10,
|
||||
1.08268041139020870318E-12,
|
||||
1.37555460633261799868E-15,
|
||||
8.36354435630677421531E-19,
|
||||
1.86958710162783235106E-22,
|
||||
};
|
||||
static double gd[11] = {
|
||||
/* 1.00000000000000000000E0,*/
|
||||
1.47495759925128324529E0,
|
||||
3.37748989120019970451E-1,
|
||||
2.53603741420338795122E-2,
|
||||
8.14679107184306179049E-4,
|
||||
1.27545075667729118702E-5,
|
||||
1.04314589657571990585E-7,
|
||||
4.60680728146520428211E-10,
|
||||
1.10273215066240270757E-12,
|
||||
1.38796531259578871258E-15,
|
||||
8.39158816283118707363E-19,
|
||||
1.86958710162783236342E-22,
|
||||
};
|
||||
|
||||
|
||||
static double polevl( double x, double* coef, int n )
|
||||
{
|
||||
double ans;
|
||||
double *p = coef;
|
||||
int i;
|
||||
|
||||
ans = *p++;
|
||||
i = n;
|
||||
|
||||
do
|
||||
{
|
||||
ans = ans * x + *p++;
|
||||
}
|
||||
while (--i);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
static double p1evl( double x, double* coef, int n )
|
||||
{
|
||||
double ans;
|
||||
double *p = coef;
|
||||
int i;
|
||||
|
||||
ans = x + *p++;
|
||||
i = n - 1;
|
||||
|
||||
do
|
||||
{
|
||||
ans = ans * x + *p++;
|
||||
}
|
||||
while (--i);
|
||||
|
||||
return ans;
|
||||
}
|
||||
|
||||
|
||||
static void fresnel( double xxa, double *ssa, double *cca )
|
||||
{
|
||||
double f, g, cc, ss, c, s, t, u;
|
||||
double x, x2;
|
||||
|
||||
x = fabs( xxa );
|
||||
x2 = x * x;
|
||||
|
||||
if ( x2 < 2.5625 )
|
||||
{
|
||||
t = x2 * x2;
|
||||
ss = x * x2 * polevl (t, sn, 5) / p1evl (t, sd, 6);
|
||||
cc = x * polevl (t, cn, 5) / polevl (t, cd, 6);
|
||||
}
|
||||
else if ( x > 36974.0 )
|
||||
{
|
||||
cc = 0.5;
|
||||
ss = 0.5;
|
||||
}
|
||||
else
|
||||
{
|
||||
x2 = x * x;
|
||||
t = M_PI * x2;
|
||||
u = 1.0 / (t * t);
|
||||
t = 1.0 / t;
|
||||
f = 1.0 - u * polevl (u, fn, 9) / p1evl(u, fd, 10);
|
||||
g = t * polevl (u, gn, 10) / p1evl (u, gd, 11);
|
||||
|
||||
t = M_PI * 0.5 * x2;
|
||||
c = cos (t);
|
||||
s = sin (t);
|
||||
t = M_PI * x;
|
||||
cc = 0.5 + (f * s - g * c) / t;
|
||||
ss = 0.5 - (f * c + g * s) / t;
|
||||
}
|
||||
|
||||
if ( xxa < 0.0 )
|
||||
{
|
||||
cc = -cc;
|
||||
ss = -ss;
|
||||
}
|
||||
|
||||
*cca = cc;
|
||||
*ssa = ss;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* compute the actual "standard" spiral, starting with curvature 0
|
||||
* @param s run-length along spiral
|
||||
* @param cDot first derivative of curvature [1/m2]
|
||||
* @param x resulting x-coordinate in spirals local co-ordinate system [m]
|
||||
* @param y resulting y-coordinate in spirals local co-ordinate system [m]
|
||||
* @param t tangent direction at s [rad]
|
||||
*/
|
||||
|
||||
void odrSpiral( double s, double cDot, double *x, double *y, double *t )
|
||||
{
|
||||
double a;
|
||||
|
||||
a = 1.0 / sqrt( fabs( cDot ) );
|
||||
a *= sqrt( M_PI );
|
||||
|
||||
fresnel( s / a, y, x );
|
||||
|
||||
*x *= a;
|
||||
*y *= a;
|
||||
|
||||
if ( cDot < 0.0 )
|
||||
*y *= -1.0;
|
||||
|
||||
*t = s * s * cDot * 0.5;
|
||||
}
|
|
@ -1,32 +0,0 @@
|
|||
/* ===================================================
|
||||
* file: odrSpiral.c
|
||||
* ---------------------------------------------------
|
||||
* purpose: free sample for computing spirals
|
||||
* in OpenDRIVE applications
|
||||
* ---------------------------------------------------
|
||||
* first edit: 09.03.2010 by M. Dupuis @ VIRES GmbH
|
||||
* last mod.: 09.03.2010 by M. Dupuis @ VIRES GmbH
|
||||
* ===================================================
|
||||
|
||||
Copyright 2010 VIRES Simulationstechnologie GmbH
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
/**
|
||||
* compute the actual "standard" spiral, starting with curvature 0
|
||||
* @param s run-length along spiral
|
||||
* @param cDot first derivative of curvature [1/m2]
|
||||
* @param x resulting x-coordinate in spirals local co-ordinate system [m]
|
||||
* @param y resulting y-coordinate in spirals local co-ordinate system [m]
|
||||
* @param t tangent direction at s [rad]
|
||||
*/
|
||||
|
||||
extern void odrSpiral( double s, double cDot, double *x, double *y, double *t );
|
|
@ -1,121 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file LayeredRTree.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @date 16.10.2012
|
||||
///
|
||||
// A wrapper around RT-trees for for efficient storing of SUMO's GL-objects and
|
||||
// accessing them ordered by their layer
|
||||
// Note that we only need two layers at this time:
|
||||
// 1 (GLO_LANE, GLO_VEHICLE, GLO_POI)
|
||||
// 2 all the rest
|
||||
// The search order returns layer 2 first because it must be drawn before layer
|
||||
// 1 for alpha blending to work
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <utils/gui/globjects/GUIGlObject.h>
|
||||
#include <utils/gui/globjects/GUIGlObjectTypes.h>
|
||||
#include <utils/gui/settings/GUIVisualizationSettings.h>
|
||||
#include <utils/geom/Boundary.h>
|
||||
|
||||
#include "SUMORTree.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/** @class LayeredRTree
|
||||
* @brief A RT-tree for efficient storing of SUMO's GL-objects in layers
|
||||
*
|
||||
* This class maintains SUMORTrees for each layer (only 2 at the moment) but
|
||||
* provides the same interface as SUMORTree
|
||||
*/
|
||||
class LayeredRTree : public SUMORTree {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
LayeredRTree() {
|
||||
myLayers.push_back(new SUMORTree());
|
||||
myLayers.push_back(new SUMORTree());
|
||||
}
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~LayeredRTree() {
|
||||
for (std::vector<SUMORTree*>::iterator it = myLayers.begin(); it != myLayers.end(); ++it) {
|
||||
delete *it;
|
||||
}
|
||||
myLayers.clear();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Insert entry (delegate to appropriate layer)
|
||||
* @param a_min Min of bounding rect
|
||||
* @param a_max Max of bounding rect
|
||||
* @param a_dataId Positive Id of data. Maybe zero, but negative numbers not allowed.
|
||||
*/
|
||||
void Insert(const float a_min[2], const float a_max[2], GUIGlObject* const & a_dataId) {
|
||||
myLayers[selectLayer(a_dataId)]->Insert(a_min, a_max, a_dataId);
|
||||
}
|
||||
|
||||
|
||||
/** @brief Remove entry (delegate to appropriate layer)
|
||||
* @param a_min Min of bounding rect
|
||||
* @param a_max Max of bounding rect
|
||||
* @param a_dataId Positive Id of data. Maybe zero, but negative numbers not allowed.
|
||||
*/
|
||||
void Remove(const float a_min[2], const float a_max[2], GUIGlObject* const & a_dataId) {
|
||||
myLayers[selectLayer(a_dataId)]->Remove(a_min, a_max, a_dataId);
|
||||
}
|
||||
|
||||
/** @brief Find all within search rectangle (searches all layers in order)
|
||||
* @param a_min Min of search bounding rect
|
||||
* @param a_max Max of search bounding rect
|
||||
* @param a_searchResult Search result array. Caller should set grow size. Function will reset, not append to array.
|
||||
* @param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||
* @param a_context User context to pass as parameter to a_resultCallback
|
||||
* @return Returns the number of entries found
|
||||
*/
|
||||
int Search(const float a_min[2], const float a_max[2], const GUIVisualizationSettings& c) const {
|
||||
int result = 0;
|
||||
for (std::vector<SUMORTree*>::const_iterator it = myLayers.begin(); it != myLayers.end(); ++it) {
|
||||
result += (*it)->Search(a_min, a_max, c);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
/// @brief the layers for drawing
|
||||
std::vector<SUMORTree*> myLayers;
|
||||
|
||||
private:
|
||||
|
||||
/// @brief select the appropriate layer for each object
|
||||
inline size_t selectLayer(GUIGlObject* o) {
|
||||
switch (o->getType()) {
|
||||
case GLO_EDGE:
|
||||
case GLO_LANE:
|
||||
case GLO_POI:
|
||||
case GLO_VEHICLE:
|
||||
case GLO_PERSON:
|
||||
return 1;
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
};
|
|
@ -1,32 +0,0 @@
|
|||
|
||||
TITLE
|
||||
|
||||
R-TREES: A DYNAMIC INDEX STRUCTURE FOR SPATIAL SEARCHING
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
A C++ templated version of the RTree algorithm.
|
||||
For more information please read the comments in RTree.h
|
||||
|
||||
AUTHORS
|
||||
|
||||
* 1983 Original algorithm and test code by Antonin Guttman and Michael Stonebraker, UC Berkely
|
||||
* 1994 ANCI C ported from original test code by Melinda Green - melinda@superliminal.com
|
||||
* 1995 Sphere volume fix for degeneracy problem submitted by Paul Brook
|
||||
* 2004 Templated C++ port by Greg Douglas
|
||||
|
||||
LICENSE:
|
||||
|
||||
Entirely free for all uses. Enjoy!
|
||||
|
||||
FILES
|
||||
* RTree.h The C++ templated RTree implementation. Well commented.
|
||||
* Test.cpp A simple test program, ported from the original C version.
|
||||
* MemoryTest.cpp A more rigourous test to validate memory use.
|
||||
* README.TXT This file.
|
||||
|
||||
TO BUILD
|
||||
|
||||
To build a test, compile only one of the test files with RTree.h.
|
||||
Both test files contain a main() function.
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,193 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file SUMORTree.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @date 27.10.2008
|
||||
///
|
||||
// A RT-tree for efficient storing of SUMO's GL-objects
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <fx.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/geom/Boundary.h>
|
||||
#include <utils/gui/globjects/GUIGlObject.h>
|
||||
#include <utils/gui/settings/GUIVisualizationSettings.h>
|
||||
#include <utils/gui/div/GUIIOGlobals.h>
|
||||
|
||||
#include "RTree.h"
|
||||
|
||||
|
||||
#define GUI_RTREE_QUAL RTree<GUIGlObject*, GUIGlObject, float, 2, GUIVisualizationSettings>
|
||||
|
||||
// specialized implementation for speedup and avoiding warnings
|
||||
|
||||
template<>
|
||||
inline float GUI_RTREE_QUAL::RectSphericalVolume(Rect* a_rect) {
|
||||
ASSERT(a_rect);
|
||||
const float extent0 = a_rect->m_max[0] - a_rect->m_min[0];
|
||||
const float extent1 = a_rect->m_max[1] - a_rect->m_min[1];
|
||||
return .78539816f * (extent0 * extent0 + extent1 * extent1);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline GUI_RTREE_QUAL::Rect GUI_RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB) {
|
||||
ASSERT(a_rectA && a_rectB);
|
||||
Rect newRect;
|
||||
newRect.m_min[0] = rtree_min(a_rectA->m_min[0], a_rectB->m_min[0]);
|
||||
newRect.m_max[0] = rtree_max(a_rectA->m_max[0], a_rectB->m_max[0]);
|
||||
newRect.m_min[1] = rtree_min(a_rectA->m_min[1], a_rectB->m_min[1]);
|
||||
newRect.m_max[1] = rtree_max(a_rectA->m_max[1], a_rectB->m_max[1]);
|
||||
return newRect;
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/** @class SUMORTree
|
||||
* @brief A RT-tree for efficient storing of SUMO's GL-objects
|
||||
*
|
||||
* This class specialises the used RT-tree implementation from "rttree.h" and
|
||||
* extends it by a mutex for avoiding parallel change and traversal of the tree.
|
||||
*/
|
||||
class SUMORTree : private GUI_RTREE_QUAL, public Boundary {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
SUMORTree() :
|
||||
GUI_RTREE_QUAL(&GUIGlObject::drawGL),
|
||||
myLock(true) {
|
||||
}
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~SUMORTree() {
|
||||
// check if lock is locked before insert objects
|
||||
if (myLock.locked()) {
|
||||
// cannot throw exception in destructor
|
||||
WRITE_ERROR("Mutex of SUMORTree is locked during call of the destructor");
|
||||
}
|
||||
// show information in gui testing debug gl mode
|
||||
WRITE_GLDEBUG("Number of objects in SUMORTree during call of the destructor: " + toString(myTreeDebug.size()));
|
||||
}
|
||||
|
||||
/** @brief Insert entry
|
||||
* @param a_min Min of bounding rect
|
||||
* @param a_max Max of bounding rect
|
||||
* @param a_dataId Positive Id of data. Maybe zero, but negative numbers not allowed.
|
||||
* @see RTree::Insert
|
||||
*/
|
||||
virtual void Insert(const float a_min[2], const float a_max[2], GUIGlObject* const & a_dataId) {
|
||||
FXMutexLock locker(myLock);
|
||||
GUI_RTREE_QUAL::Insert(a_min, a_max, a_dataId);
|
||||
}
|
||||
|
||||
/** @brief Remove entry
|
||||
* @param a_min Min of bounding rect
|
||||
* @param a_max Max of bounding rect
|
||||
* @param a_dataId Positive Id of data. Maybe zero, but negative numbers not allowed.
|
||||
* @see RTree::Remove
|
||||
*/
|
||||
virtual void Remove(const float a_min[2], const float a_max[2], GUIGlObject* const & a_dataId) {
|
||||
FXMutexLock locker(myLock);
|
||||
GUI_RTREE_QUAL::Remove(a_min, a_max, a_dataId);
|
||||
}
|
||||
|
||||
/** @brief Find all within search rectangle
|
||||
* @param a_min Min of search bounding rect
|
||||
* @param a_max Max of search bounding rect
|
||||
* @param a_searchResult Search result array. Caller should set grow size. Function will reset, not append to array.
|
||||
* @param a_resultCallback Callback function to return result. Callback should return 'true' to continue searching
|
||||
* @param a_context User context to pass as parameter to a_resultCallback
|
||||
* @return Returns the number of entries found
|
||||
* @see RTree::Search
|
||||
*/
|
||||
virtual int Search(const float a_min[2], const float a_max[2], const GUIVisualizationSettings& c) const {
|
||||
FXMutexLock locker(myLock);
|
||||
return GUI_RTREE_QUAL::Search(a_min, a_max, c);
|
||||
}
|
||||
|
||||
/** @brief Adds an additional object (detector/shape/trigger) for visualisation
|
||||
* @param[in] o The object to add
|
||||
*/
|
||||
void addAdditionalGLObject(GUIGlObject *o) {
|
||||
// check if lock is locked before insert objects
|
||||
if (myLock.locked()) {
|
||||
throw ProcessError("Mutex of SUMORTree is locked before object insertion");
|
||||
}
|
||||
// lock mutex
|
||||
FXMutexLock locker(myLock);
|
||||
// obtain boundary of object
|
||||
Boundary b = o->getCenteringBoundary();
|
||||
// show information in gui testing debug gl mode
|
||||
if (MsgHandler::writeDebugGLMessages()) {
|
||||
if ((b.getWidth() == 0) || (b.getHeight() == 0)) {
|
||||
throw ProcessError("Boundary of GUIGlObject " + o->getMicrosimID() + " has an invalid size");
|
||||
} else if (myTreeDebug.count(o) > 0) {
|
||||
throw ProcessError("GUIGlObject was already inserted");
|
||||
} else {
|
||||
myTreeDebug[o] = b;
|
||||
// write GL Debug
|
||||
WRITE_GLDEBUG("\tInserted " + o->getFullName() + " into SUMORTree with boundary " + toString(b));
|
||||
}
|
||||
}
|
||||
// insert it in Tree
|
||||
const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
|
||||
const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
|
||||
Insert(cmin, cmax, o);
|
||||
}
|
||||
|
||||
/** @brief Removes an additional object (detector/shape/trigger) from being visualised
|
||||
* @param[in] o The object to remove
|
||||
*/
|
||||
void removeAdditionalGLObject(GUIGlObject *o) {
|
||||
// check if lock is locked remove insert objects
|
||||
if (myLock.locked()) {
|
||||
throw ProcessError("Mutex of SUMORTree is locked before object remove");
|
||||
}
|
||||
// lock mutex
|
||||
FXMutexLock locker(myLock);
|
||||
// obtain boundary of object
|
||||
Boundary b = o->getCenteringBoundary();
|
||||
// show information in gui testing debug gl mode
|
||||
if (MsgHandler::writeDebugGLMessages()) {
|
||||
if ((b.getWidth() == 0) || (b.getHeight() == 0)) {
|
||||
throw ProcessError("Boundary of GUIGlObject " + o->getMicrosimID() + " has an invalid size");
|
||||
} else if (myTreeDebug.count(o) == 0) {
|
||||
throw ProcessError("GUIGlObject wasn't inserted");
|
||||
} else if (toString(b) != toString(myTreeDebug.at(o))) {
|
||||
// show information in console before throwing exception
|
||||
std::cout << "Tree: " << toString(myTreeDebug.at(o)) << " original: " << toString(b) << std::endl;
|
||||
throw ProcessError("add boundary of GUIGlObject " + o->getMicrosimID() + " is different of removed boundary (" + toString(b) + " != " + toString(myTreeDebug.at(o)) + ")");
|
||||
} else {
|
||||
myTreeDebug.erase(o);
|
||||
WRITE_GLDEBUG("\tRemoved object " + o->getFullName() + " from SUMORTree with boundary " + toString(b));
|
||||
}
|
||||
}
|
||||
// remove it from Tree
|
||||
const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
|
||||
const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
|
||||
Remove(cmin, cmax, o);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief A mutex avoiding parallel change and traversal of the tree
|
||||
mutable FXMutex myLock;
|
||||
|
||||
private:
|
||||
/**@brief Map only used for check that SUMORTree works as expected, only is used if option "gui-testing-debug-gl" is enabled.
|
||||
* @note Warning: DO NOT USE in release mode and use it in debug mode carefully, due it produces a slowdown.
|
||||
*/
|
||||
std::map<GUIGlObject*, Boundary> myTreeDebug;
|
||||
};
|
|
@ -1,12 +0,0 @@
|
|||
set(foreign_tcpip_STAT_SRCS
|
||||
socket.h
|
||||
socket.cpp
|
||||
storage.h
|
||||
storage.cpp
|
||||
)
|
||||
|
||||
add_library(foreign_tcpip STATIC ${foreign_tcpip_STAT_SRCS})
|
||||
set_property(TARGET foreign_tcpip PROPERTY PROJECT_LABEL "z_foreign_tcpip")
|
||||
if (SUMO_UTILS)
|
||||
install(TARGETS foreign_tcpip DESTINATION lib)
|
||||
endif ()
|
|
@ -1,650 +0,0 @@
|
|||
/************************************************************************
|
||||
** This file is part of the network simulator Shawn. **
|
||||
** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
|
||||
** Shawn is free software; you can redistribute it and/or modify it **
|
||||
** under the terms of the BSD License. Refer to the shawn-licence.txt **
|
||||
** file in the root of the Shawn source tree for further details. **
|
||||
************************************************************************/
|
||||
|
||||
#ifdef SHAWN
|
||||
#include <apps/tcpip/socket.h>
|
||||
#include <sys/simulation/simulation_controller.h>
|
||||
#else
|
||||
#include "socket.h"
|
||||
#endif
|
||||
|
||||
#ifdef BUILD_TCPIP
|
||||
|
||||
|
||||
#ifndef WIN32
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#else
|
||||
#ifdef ERROR
|
||||
#undef ERROR
|
||||
#endif
|
||||
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
#ifndef vsnprintf
|
||||
#define vsnprintf _vsnprintf
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <cstdarg>
|
||||
#include <cassert>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
#ifdef SHAWN
|
||||
extern "C" void init_tcpip( shawn::SimulationController& sc )
|
||||
{
|
||||
// std::cout << "tcpip init" << std::endl;
|
||||
}
|
||||
#endif
|
||||
|
||||
namespace tcpip
|
||||
{
|
||||
const int Socket::lengthLen = 4;
|
||||
|
||||
#ifdef WIN32
|
||||
bool Socket::init_windows_sockets_ = true;
|
||||
bool Socket::windows_sockets_initialized_ = false;
|
||||
int Socket::instance_count_ = 0;
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Socket::
|
||||
Socket(std::string host, int port)
|
||||
: host_( host ),
|
||||
port_( port ),
|
||||
socket_(-1),
|
||||
server_socket_(-1),
|
||||
blocking_(true),
|
||||
verbose_(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Socket::
|
||||
Socket(int port)
|
||||
: host_(""),
|
||||
port_( port ),
|
||||
socket_(-1),
|
||||
server_socket_(-1),
|
||||
blocking_(true),
|
||||
verbose_(false)
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
init()
|
||||
{
|
||||
#ifdef WIN32
|
||||
instance_count_++;
|
||||
|
||||
if( init_windows_sockets_ && !windows_sockets_initialized_ )
|
||||
{
|
||||
WSAData wsaData;
|
||||
if( WSAStartup(MAKEWORD(1, 1), &wsaData) != 0 )
|
||||
BailOnSocketError("Unable to init WSA Sockets");
|
||||
windows_sockets_initialized_ = true;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
Socket::
|
||||
getFreeSocketPort()
|
||||
{
|
||||
// Create socket to find a random free port that can be handed to the app
|
||||
int sock = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
|
||||
struct sockaddr_in self;
|
||||
memset(&self, 0, sizeof(self));
|
||||
self.sin_family = AF_INET;
|
||||
self.sin_port = htons(0);
|
||||
self.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
socklen_t address_len = sizeof(self);
|
||||
// bind with port==0 assigns free port
|
||||
if ( bind(sock, (struct sockaddr*) &self, address_len) < 0)
|
||||
BailOnSocketError("tcpip::Socket::getFreeSocketPort() Unable to bind socket");
|
||||
// get the assigned port with getsockname
|
||||
if ( getsockname(sock, (struct sockaddr*) &self, &address_len) < 0)
|
||||
BailOnSocketError("tcpip::Socket::getFreeSocketPort() Unable to get socket name");
|
||||
const int port = ntohs(self.sin_port);
|
||||
#ifdef WIN32
|
||||
::closesocket( sock );
|
||||
#else
|
||||
::close( sock );
|
||||
#endif
|
||||
return port;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Socket::
|
||||
~Socket()
|
||||
{
|
||||
// Close first an existing client connection ...
|
||||
close();
|
||||
#ifdef WIN32
|
||||
instance_count_--;
|
||||
#endif
|
||||
|
||||
// ... then the server socket
|
||||
if( server_socket_ >= 0 )
|
||||
{
|
||||
#ifdef WIN32
|
||||
::closesocket( server_socket_ );
|
||||
#else
|
||||
::close( server_socket_ );
|
||||
#endif
|
||||
server_socket_ = -1;
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
if( server_socket_ == -1 && socket_ == -1
|
||||
&& init_windows_sockets_ && instance_count_ == 0 )
|
||||
WSACleanup();
|
||||
windows_sockets_initialized_ = false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
BailOnSocketError( std::string context)
|
||||
{
|
||||
#ifdef WIN32
|
||||
int e = WSAGetLastError();
|
||||
std::string msg = GetWinsockErrorString( e );
|
||||
#else
|
||||
std::string msg = strerror( errno );
|
||||
#endif
|
||||
throw SocketException( context + ": " + msg );
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
int
|
||||
Socket::
|
||||
port()
|
||||
{
|
||||
return port_;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
bool
|
||||
Socket::
|
||||
datawaiting(int sock)
|
||||
const
|
||||
{
|
||||
fd_set fds;
|
||||
FD_ZERO( &fds );
|
||||
FD_SET( (unsigned int)sock, &fds );
|
||||
|
||||
struct timeval tv;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
|
||||
int r = select( sock+1, &fds, nullptr, nullptr, &tv);
|
||||
|
||||
if (r < 0)
|
||||
BailOnSocketError("tcpip::Socket::datawaiting @ select");
|
||||
|
||||
if( FD_ISSET( sock, &fds ) )
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
bool
|
||||
Socket::
|
||||
atoaddr( std::string address, struct sockaddr_in& addr)
|
||||
{
|
||||
int status;
|
||||
struct addrinfo *servinfo; // will point to the results
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof hints); // make sure the struct is empty
|
||||
hints.ai_family = AF_INET; // restrict to IPv4?
|
||||
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
|
||||
hints.ai_flags = AI_PASSIVE; // fill in my IP for me
|
||||
|
||||
if ((status = getaddrinfo(address.c_str(), nullptr, &hints, &servinfo)) != 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool valid = false;
|
||||
|
||||
for (struct addrinfo *p = servinfo; p != nullptr; p = p->ai_next) {
|
||||
if (p->ai_family == AF_INET) { // IPv4
|
||||
addr = *(struct sockaddr_in *)p->ai_addr;
|
||||
addr.sin_port = htons((unsigned short)port_);
|
||||
valid = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
freeaddrinfo(servinfo); // free the linked list
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Socket*
|
||||
Socket::
|
||||
accept(const bool create)
|
||||
{
|
||||
if( socket_ >= 0 )
|
||||
return nullptr;
|
||||
|
||||
struct sockaddr_in client_addr;
|
||||
#ifdef WIN32
|
||||
int addrlen = sizeof(client_addr);
|
||||
#else
|
||||
socklen_t addrlen = sizeof(client_addr);
|
||||
#endif
|
||||
|
||||
if( server_socket_ < 0 )
|
||||
{
|
||||
struct sockaddr_in self;
|
||||
|
||||
//Create the server socket
|
||||
server_socket_ = static_cast<int>(socket( AF_INET, SOCK_STREAM, 0 ));
|
||||
if( server_socket_ < 0 )
|
||||
BailOnSocketError("tcpip::Socket::accept() @ socket");
|
||||
|
||||
//"Address already in use" error protection
|
||||
{
|
||||
|
||||
#ifdef WIN32
|
||||
//setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuseaddr, sizeof(reuseaddr));
|
||||
// No address reuse in Windows!!!
|
||||
#else
|
||||
int reuseaddr = 1;
|
||||
setsockopt(server_socket_, SOL_SOCKET, SO_REUSEADDR, &reuseaddr, sizeof(reuseaddr));
|
||||
#endif
|
||||
}
|
||||
|
||||
// Initialize address/port structure
|
||||
memset(&self, 0, sizeof(self));
|
||||
self.sin_family = AF_INET;
|
||||
self.sin_port = htons((unsigned short)port_);
|
||||
self.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
|
||||
// Assign a port number to the socket
|
||||
if ( bind(server_socket_, (struct sockaddr*)&self, sizeof(self)) != 0 )
|
||||
BailOnSocketError("tcpip::Socket::accept() Unable to create listening socket");
|
||||
|
||||
|
||||
// Make it a "listening socket"
|
||||
if ( listen(server_socket_, 10) == -1 )
|
||||
BailOnSocketError("tcpip::Socket::accept() Unable to listen on server socket");
|
||||
|
||||
// Make the newly created socket blocking or not
|
||||
set_blocking(blocking_);
|
||||
}
|
||||
|
||||
socket_ = static_cast<int>(::accept(server_socket_, (struct sockaddr*)&client_addr, &addrlen));
|
||||
|
||||
if( socket_ >= 0 )
|
||||
{
|
||||
int x = 1;
|
||||
setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
|
||||
if (create) {
|
||||
Socket* result = new Socket(0);
|
||||
result->socket_ = socket_;
|
||||
socket_ = -1;
|
||||
return result;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
set_blocking(bool blocking)
|
||||
{
|
||||
blocking_ = blocking;
|
||||
|
||||
if( server_socket_ > 0 )
|
||||
{
|
||||
#ifdef WIN32
|
||||
ULONG NonBlock = blocking_ ? 0 : 1;
|
||||
if (ioctlsocket(server_socket_, FIONBIO, &NonBlock) == SOCKET_ERROR)
|
||||
BailOnSocketError("tcpip::Socket::set_blocking() Unable to initialize non blocking I/O");
|
||||
#else
|
||||
long arg = fcntl(server_socket_, F_GETFL, NULL);
|
||||
if (blocking_)
|
||||
{
|
||||
arg &= ~O_NONBLOCK;
|
||||
} else {
|
||||
arg |= O_NONBLOCK;
|
||||
}
|
||||
fcntl(server_socket_, F_SETFL, arg);
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
connect()
|
||||
{
|
||||
sockaddr_in address;
|
||||
|
||||
if( !atoaddr( host_.c_str(), address) )
|
||||
BailOnSocketError("tcpip::Socket::connect() @ Invalid network address");
|
||||
|
||||
socket_ = static_cast<int>(socket( PF_INET, SOCK_STREAM, 0 ));
|
||||
if( socket_ < 0 )
|
||||
BailOnSocketError("tcpip::Socket::connect() @ socket");
|
||||
|
||||
if( ::connect( socket_, (sockaddr const*)&address, sizeof(address) ) < 0 )
|
||||
BailOnSocketError("tcpip::Socket::connect() @ connect");
|
||||
|
||||
if( socket_ >= 0 )
|
||||
{
|
||||
int x = 1;
|
||||
setsockopt(socket_, IPPROTO_TCP, TCP_NODELAY, (const char*)&x, sizeof(x));
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
close()
|
||||
{
|
||||
// Close client-connection
|
||||
if( socket_ >= 0 )
|
||||
{
|
||||
#ifdef WIN32
|
||||
::closesocket( socket_ );
|
||||
#else
|
||||
::close( socket_ );
|
||||
#endif
|
||||
|
||||
socket_ = -1;
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
send( const std::vector<unsigned char> &buffer)
|
||||
{
|
||||
if( socket_ < 0 )
|
||||
return;
|
||||
|
||||
printBufferOnVerbose(buffer, "Send");
|
||||
|
||||
size_t numbytes = buffer.size();
|
||||
unsigned char const *bufPtr = &buffer[0];
|
||||
while( numbytes > 0 )
|
||||
{
|
||||
#ifdef WIN32
|
||||
int bytesSent = ::send( socket_, (const char*)bufPtr, static_cast<int>(numbytes), 0 );
|
||||
#else
|
||||
int bytesSent = ::send( socket_, bufPtr, numbytes, 0 );
|
||||
#endif
|
||||
if( bytesSent < 0 )
|
||||
BailOnSocketError( "send failed" );
|
||||
|
||||
numbytes -= bytesSent;
|
||||
bufPtr += bytesSent;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
void
|
||||
Socket::
|
||||
sendExact( const Storage &b)
|
||||
{
|
||||
int length = static_cast<int>(b.size());
|
||||
Storage length_storage;
|
||||
length_storage.writeInt(lengthLen + length);
|
||||
|
||||
// Sending length_storage and b independently would probably be possible and
|
||||
// avoid some copying here, but both parts would have to go through the
|
||||
// TCP/IP stack on their own which probably would cost more performance.
|
||||
std::vector<unsigned char> msg;
|
||||
msg.insert(msg.end(), length_storage.begin(), length_storage.end());
|
||||
msg.insert(msg.end(), b.begin(), b.end());
|
||||
send(msg);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
size_t
|
||||
Socket::
|
||||
recvAndCheck(unsigned char * const buffer, std::size_t len)
|
||||
const
|
||||
{
|
||||
#ifdef WIN32
|
||||
const int bytesReceived = recv( socket_, (char*)buffer, static_cast<int>(len), 0 );
|
||||
#else
|
||||
const int bytesReceived = static_cast<int>(recv( socket_, buffer, len, 0 ));
|
||||
#endif
|
||||
if( bytesReceived == 0 )
|
||||
throw SocketException( "tcpip::Socket::recvAndCheck @ recv: peer shutdown" );
|
||||
if( bytesReceived < 0 )
|
||||
BailOnSocketError( "tcpip::Socket::recvAndCheck @ recv" );
|
||||
|
||||
return static_cast<size_t>(bytesReceived);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
receiveComplete(unsigned char * buffer, size_t len)
|
||||
const
|
||||
{
|
||||
while (len > 0)
|
||||
{
|
||||
const size_t bytesReceived = recvAndCheck(buffer, len);
|
||||
len -= bytesReceived;
|
||||
buffer += bytesReceived;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void
|
||||
Socket::
|
||||
printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label)
|
||||
const
|
||||
{
|
||||
if (verbose_)
|
||||
{
|
||||
std::cerr << label << " " << buffer.size() << " bytes via tcpip::Socket: [";
|
||||
// cache end iterator for performance
|
||||
const std::vector<unsigned char>::const_iterator end = buffer.end();
|
||||
for (std::vector<unsigned char>::const_iterator it = buffer.begin(); end != it; ++it)
|
||||
std::cerr << " " << static_cast<int>(*it) << " ";
|
||||
std::cerr << "]" << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
std::vector<unsigned char>
|
||||
Socket::
|
||||
receive(int bufSize)
|
||||
{
|
||||
std::vector<unsigned char> buffer;
|
||||
|
||||
if( socket_ < 0 )
|
||||
connect();
|
||||
|
||||
if( !datawaiting( socket_) )
|
||||
return buffer;
|
||||
|
||||
buffer.resize(bufSize);
|
||||
const size_t bytesReceived = recvAndCheck(&buffer[0], bufSize);
|
||||
|
||||
buffer.resize(bytesReceived);
|
||||
|
||||
printBufferOnVerbose(buffer, "Rcvd");
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
|
||||
|
||||
bool
|
||||
Socket::
|
||||
receiveExact( Storage &msg )
|
||||
{
|
||||
// buffer for received bytes
|
||||
// According to the C++ standard elements of a std::vector are stored
|
||||
// contiguously. Explicitly &buffer[n] == &buffer[0] + n for 0 <= n < buffer.size().
|
||||
std::vector<unsigned char> buffer(lengthLen);
|
||||
|
||||
// receive length of TraCI message
|
||||
receiveComplete(&buffer[0], lengthLen);
|
||||
Storage length_storage(&buffer[0], lengthLen);
|
||||
const int totalLen = length_storage.readInt();
|
||||
assert(totalLen > lengthLen);
|
||||
|
||||
// extent buffer
|
||||
buffer.resize(totalLen);
|
||||
|
||||
// receive remaining TraCI message
|
||||
receiveComplete(&buffer[lengthLen], totalLen - lengthLen);
|
||||
|
||||
// copy message content into passed Storage
|
||||
msg.reset();
|
||||
msg.writePacket(&buffer[lengthLen], totalLen - lengthLen);
|
||||
|
||||
printBufferOnVerbose(buffer, "Rcvd Storage with");
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
bool
|
||||
Socket::
|
||||
has_client_connection()
|
||||
const
|
||||
{
|
||||
return socket_ >= 0;
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
bool
|
||||
Socket::
|
||||
is_blocking()
|
||||
{
|
||||
return blocking_;
|
||||
}
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
// ----------------------------------------------------------------------
|
||||
std::string
|
||||
Socket::
|
||||
GetWinsockErrorString(int err)
|
||||
{
|
||||
|
||||
switch( err)
|
||||
{
|
||||
case 0: return "No error";
|
||||
case WSAEINTR: return "Interrupted system call";
|
||||
case WSAEBADF: return "Bad file number";
|
||||
case WSAEACCES: return "Permission denied";
|
||||
case WSAEFAULT: return "Bad address";
|
||||
case WSAEINVAL: return "Invalid argument";
|
||||
case WSAEMFILE: return "Too many open sockets";
|
||||
case WSAEWOULDBLOCK: return "Operation would block";
|
||||
case WSAEINPROGRESS: return "Operation now in progress";
|
||||
case WSAEALREADY: return "Operation already in progress";
|
||||
case WSAENOTSOCK: return "Socket operation on non-socket";
|
||||
case WSAEDESTADDRREQ: return "Destination address required";
|
||||
case WSAEMSGSIZE: return "Message too long";
|
||||
case WSAEPROTOTYPE: return "Protocol wrong type for socket";
|
||||
case WSAENOPROTOOPT: return "Bad protocol option";
|
||||
case WSAEPROTONOSUPPORT: return "Protocol not supported";
|
||||
case WSAESOCKTNOSUPPORT: return "Socket type not supported";
|
||||
case WSAEOPNOTSUPP: return "Operation not supported on socket";
|
||||
case WSAEPFNOSUPPORT: return "Protocol family not supported";
|
||||
case WSAEAFNOSUPPORT: return "Address family not supported";
|
||||
case WSAEADDRINUSE: return "Address already in use";
|
||||
case WSAEADDRNOTAVAIL: return "Can't assign requested address";
|
||||
case WSAENETDOWN: return "Network is down";
|
||||
case WSAENETUNREACH: return "Network is unreachable";
|
||||
case WSAENETRESET: return "Net Socket reset";
|
||||
case WSAECONNABORTED: return "Software caused tcpip::Socket abort";
|
||||
case WSAECONNRESET: return "Socket reset by peer";
|
||||
case WSAENOBUFS: return "No buffer space available";
|
||||
case WSAEISCONN: return "Socket is already connected";
|
||||
case WSAENOTCONN: return "Socket is not connected";
|
||||
case WSAESHUTDOWN: return "Can't send after socket shutdown";
|
||||
case WSAETOOMANYREFS: return "Too many references, can't splice";
|
||||
case WSAETIMEDOUT: return "Socket timed out";
|
||||
case WSAECONNREFUSED: return "Socket refused";
|
||||
case WSAELOOP: return "Too many levels of symbolic links";
|
||||
case WSAENAMETOOLONG: return "File name too long";
|
||||
case WSAEHOSTDOWN: return "Host is down";
|
||||
case WSAEHOSTUNREACH: return "No route to host";
|
||||
case WSAENOTEMPTY: return "Directory not empty";
|
||||
case WSAEPROCLIM: return "Too many processes";
|
||||
case WSAEUSERS: return "Too many users";
|
||||
case WSAEDQUOT: return "Disc quota exceeded";
|
||||
case WSAESTALE: return "Stale NFS file handle";
|
||||
case WSAEREMOTE: return "Too many levels of remote in path";
|
||||
case WSASYSNOTREADY: return "Network system is unavailable";
|
||||
case WSAVERNOTSUPPORTED: return "Winsock version out of range";
|
||||
case WSANOTINITIALISED: return "WSAStartup not yet called";
|
||||
case WSAEDISCON: return "Graceful shutdown in progress";
|
||||
case WSAHOST_NOT_FOUND: return "Host not found";
|
||||
case WSANO_DATA: return "No host data of that type was found";
|
||||
}
|
||||
|
||||
return "unknown";
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
} // namespace tcpip
|
||||
|
||||
#endif // BUILD_TCPIP
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Source $Source: $
|
||||
* Version $Revision: 645 $
|
||||
* Date $Date: 2012-04-27 14:03:33 +0200 (Fri, 27 Apr 2012) $
|
||||
*-----------------------------------------------------------------------
|
||||
* $Log: $
|
||||
*-----------------------------------------------------------------------*/
|
|
@ -1,145 +0,0 @@
|
|||
/************************************************************************
|
||||
** This file is part of the network simulator Shawn. **
|
||||
** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
|
||||
** Shawn is free software; you can redistribute it and/or modify it **
|
||||
** under the terms of the BSD License. Refer to the shawn-licence.txt **
|
||||
** file in the root of the Shawn source tree for further details. **
|
||||
************************************************************************/
|
||||
|
||||
#ifndef __SHAWN_APPS_TCPIP_SOCKET_H
|
||||
#define __SHAWN_APPS_TCPIP_SOCKET_H
|
||||
|
||||
#ifdef SHAWN
|
||||
#include <shawn_config.h>
|
||||
#include "_apps_enable_cmake.h"
|
||||
#ifdef ENABLE_TCPIP
|
||||
#define BUILD_TCPIP
|
||||
#endif
|
||||
#else
|
||||
#define BUILD_TCPIP
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BUILD_TCPIP
|
||||
|
||||
// Get Storage
|
||||
#ifdef SHAWN
|
||||
#include <apps/tcpip/storage.h>
|
||||
#else
|
||||
#include "storage.h"
|
||||
#endif
|
||||
|
||||
#ifdef SHAWN
|
||||
namespace shawn
|
||||
{ class SimulationController; }
|
||||
|
||||
// Dummy function is called when Shawn Simulation starts. Does nothing up to now.
|
||||
extern "C" void init_tcpip( shawn::SimulationController& );
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <list>
|
||||
#include <deque>
|
||||
#include <iostream>
|
||||
#include <cstddef>
|
||||
|
||||
|
||||
struct sockaddr_in;
|
||||
|
||||
namespace tcpip
|
||||
{
|
||||
|
||||
class SocketException: public std::runtime_error
|
||||
{
|
||||
public:
|
||||
SocketException(std::string what) : std::runtime_error(what.c_str()) {}
|
||||
};
|
||||
|
||||
class Socket
|
||||
{
|
||||
friend class Response;
|
||||
public:
|
||||
/// Constructor that prepare to connect to host:port
|
||||
Socket(std::string host, int port);
|
||||
|
||||
/// Constructor that prepare for accepting a connection on given port
|
||||
Socket(int port);
|
||||
|
||||
/// Destructor
|
||||
~Socket();
|
||||
|
||||
/// @brief Returns an free port on the system
|
||||
/// @note This is done by binding a socket with port=0, getting the assigned port, and closing the socket again
|
||||
static int getFreeSocketPort();
|
||||
|
||||
/// Connects to host_:port_
|
||||
void connect();
|
||||
|
||||
/// Wait for a incoming connection to port_
|
||||
Socket* accept(const bool create = false);
|
||||
|
||||
void send( const std::vector<unsigned char> &buffer);
|
||||
void sendExact( const Storage & );
|
||||
/// Receive up to \p bufSize available bytes from Socket::socket_
|
||||
std::vector<unsigned char> receive( int bufSize = 2048 );
|
||||
/// Receive a complete TraCI message from Socket::socket_
|
||||
bool receiveExact( Storage &);
|
||||
void close();
|
||||
int port();
|
||||
void set_blocking(bool);
|
||||
bool is_blocking();
|
||||
bool has_client_connection() const;
|
||||
|
||||
// If verbose, each send and received data is written to stderr
|
||||
bool verbose() { return verbose_; }
|
||||
void set_verbose(bool newVerbose) { verbose_ = newVerbose; }
|
||||
|
||||
protected:
|
||||
/// Length of the message length part of a TraCI message
|
||||
static const int lengthLen;
|
||||
|
||||
/// Receive \p len bytes from Socket::socket_
|
||||
void receiveComplete(unsigned char * const buffer, std::size_t len) const;
|
||||
/// Receive up to \p len available bytes from Socket::socket_
|
||||
size_t recvAndCheck(unsigned char * const buffer, std::size_t len) const;
|
||||
/// Print \p label and \p buffer to stderr if Socket::verbose_ is set
|
||||
void printBufferOnVerbose(const std::vector<unsigned char> buffer, const std::string &label) const;
|
||||
|
||||
private:
|
||||
void init();
|
||||
static void BailOnSocketError(std::string context);
|
||||
#ifdef WIN32
|
||||
static std::string GetWinsockErrorString(int err);
|
||||
#endif
|
||||
bool atoaddr(std::string, struct sockaddr_in& addr);
|
||||
bool datawaiting(int sock) const;
|
||||
|
||||
std::string host_;
|
||||
int port_;
|
||||
int socket_;
|
||||
int server_socket_;
|
||||
bool blocking_;
|
||||
|
||||
bool verbose_;
|
||||
#ifdef WIN32
|
||||
static bool init_windows_sockets_;
|
||||
static bool windows_sockets_initialized_;
|
||||
static int instance_count_;
|
||||
#endif
|
||||
};
|
||||
|
||||
} // namespace tcpip
|
||||
|
||||
#endif // BUILD_TCPIP
|
||||
|
||||
#endif
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Source $Source: $
|
||||
* Version $Revision: 612 $
|
||||
* Date $Date: 2011-06-14 15:16:52 +0200 (Tue, 14 Jun 2011) $
|
||||
*-----------------------------------------------------------------------
|
||||
* $Log:$
|
||||
*-----------------------------------------------------------------------*/
|
|
@ -1,474 +0,0 @@
|
|||
/************************************************************************
|
||||
** This file is part of the network simulator Shawn. **
|
||||
** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
|
||||
** Shawn is free software; you can redistribute it and/or modify it **
|
||||
** under the terms of the BSD License. Refer to the shawn-licence.txt **
|
||||
** file in the root of the Shawn source tree for further details. **
|
||||
************************************************************************
|
||||
** **
|
||||
** \author Axel Wegener <wegener@itm.uni-luebeck.de> **
|
||||
** \author Bjoern Hendriks <hendriks@ibr.cs.tu-bs.de> **
|
||||
** **
|
||||
************************************************************************/
|
||||
|
||||
#include "storage.h"
|
||||
|
||||
#ifdef BUILD_TCPIP
|
||||
|
||||
#include <iostream>
|
||||
#include <iterator>
|
||||
#include <sstream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <iomanip>
|
||||
|
||||
|
||||
//#define NULLITER static_cast<list<unsigned char>::iterator>(0)
|
||||
|
||||
namespace tcpip
|
||||
{
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Storage::Storage()
|
||||
{
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Storage::Storage(const unsigned char packet[], int length)
|
||||
{
|
||||
assert(length >= 0); // fixed MB, 2015-04-21
|
||||
|
||||
store.reserve(length);
|
||||
// Get the content
|
||||
for(int i = 0; i < length; ++i) store.push_back(packet[i]);
|
||||
|
||||
init();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::init()
|
||||
{
|
||||
// Initialize local variables
|
||||
iter_ = store.begin();
|
||||
|
||||
short a = 0x0102;
|
||||
unsigned char *p_a = reinterpret_cast<unsigned char*>(&a);
|
||||
bigEndian_ = (p_a[0] == 0x01); // big endian?
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
Storage::~Storage()
|
||||
{}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
bool Storage::valid_pos()
|
||||
{
|
||||
return (iter_ != store.end()); // this implies !store.empty()
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
unsigned int Storage::position() const
|
||||
{
|
||||
// According to C++ standard std::distance will simply compute the iterators
|
||||
// difference for random access iterators as std::vector provides.
|
||||
return static_cast<unsigned int>(std::distance(store.begin(), iter_));
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::reset()
|
||||
{
|
||||
store.clear();
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a char form the array
|
||||
* @return The read char (between 0 and 255)
|
||||
*/
|
||||
unsigned char Storage::readChar()
|
||||
{
|
||||
if ( !valid_pos() )
|
||||
{
|
||||
throw std::invalid_argument("Storage::readChar(): invalid position");
|
||||
}
|
||||
return readCharUnsafe();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void Storage::writeChar(unsigned char value)
|
||||
{
|
||||
store.push_back(value);
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a byte form the array
|
||||
* @return The read byte (between -128 and 127)
|
||||
*/
|
||||
int Storage::readByte()
|
||||
{
|
||||
int i = static_cast<int>(readChar());
|
||||
if (i < 128) return i;
|
||||
else return (i - 256);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void Storage::writeByte(int value)
|
||||
{
|
||||
if (value < -128 || value > 127)
|
||||
{
|
||||
throw std::invalid_argument("Storage::writeByte(): Invalid value, not in [-128, 127]");
|
||||
}
|
||||
writeChar( static_cast<unsigned char>( (value+256) % 256 ) );
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads an unsigned byte form the array
|
||||
* @return The read byte (between 0 and 255)
|
||||
*/
|
||||
int Storage::readUnsignedByte()
|
||||
{
|
||||
return static_cast<int>(readChar());
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
*
|
||||
*/
|
||||
void Storage::writeUnsignedByte(int value)
|
||||
{
|
||||
if (value < 0 || value > 255)
|
||||
{
|
||||
throw std::invalid_argument("Storage::writeUnsignedByte(): Invalid value, not in [0, 255]");
|
||||
}
|
||||
writeChar( static_cast<unsigned char>( value ));
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a string form the array
|
||||
* @return The read string
|
||||
*/
|
||||
std::string Storage::readString()
|
||||
{
|
||||
int len = readInt();
|
||||
checkReadSafe(len);
|
||||
StorageType::const_iterator end = iter_;
|
||||
std::advance(end, len);
|
||||
const std::string tmp(iter_, end);
|
||||
iter_ = end;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Writes a string into the array;
|
||||
* @param s The string to be written
|
||||
*/
|
||||
void Storage::writeString(const std::string &s)
|
||||
{
|
||||
writeInt(static_cast<int>(s.length()));
|
||||
|
||||
store.insert(store.end(), s.begin(), s.end());
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a string list form the array
|
||||
* @return The read string
|
||||
*/
|
||||
std::vector<std::string> Storage::readStringList()
|
||||
{
|
||||
std::vector<std::string> tmp;
|
||||
const int len = readInt();
|
||||
tmp.reserve(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
tmp.push_back(readString());
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
/**
|
||||
* Reads a double list from the array
|
||||
* @return The read double list
|
||||
*/
|
||||
std::vector<double> Storage::readDoubleList()
|
||||
{
|
||||
std::vector<double> tmp;
|
||||
const int len = readInt();
|
||||
tmp.reserve(len);
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
tmp.push_back(readDouble());
|
||||
}
|
||||
return tmp;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Writes a string into the array;
|
||||
* @param s The string to be written
|
||||
*/
|
||||
void Storage::writeStringList(const std::vector<std::string> &s)
|
||||
{
|
||||
writeInt(static_cast<int>(s.size()));
|
||||
for (std::vector<std::string>::const_iterator it = s.begin(); it!=s.end() ; it++)
|
||||
{
|
||||
writeString(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Writes a double list into the array;
|
||||
* @param s The double list to be written
|
||||
*/
|
||||
void Storage::writeDoubleList(const std::vector<double> &s)
|
||||
{
|
||||
writeInt(static_cast<int>(s.size()));
|
||||
for (std::vector<double>::const_iterator it = s.begin(); it!=s.end() ; it++)
|
||||
{
|
||||
writeDouble(*it);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* Restores an integer, which was split up in two bytes according to the
|
||||
* specification, it must have been split by its row byte representation
|
||||
* with MSBF-order
|
||||
*
|
||||
* @return the unspoiled integer value (between -32768 and 32767)
|
||||
*/
|
||||
int Storage::readShort()
|
||||
{
|
||||
short value = 0;
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
readByEndianess(p_value, 2);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeShort( int value )
|
||||
{
|
||||
if (value < -32768 || value > 32767)
|
||||
{
|
||||
throw std::invalid_argument("Storage::writeShort(): Invalid value, not in [-32768, 32767]");
|
||||
}
|
||||
|
||||
short svalue = static_cast<short>(value);
|
||||
unsigned char *p_svalue = reinterpret_cast<unsigned char*>(&svalue);
|
||||
writeByEndianess(p_svalue, 2);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* restores an integer, which was split up in four bytes acording to the
|
||||
* specification, it must have been split by its row byte representation
|
||||
* with MSBF-order
|
||||
*
|
||||
* @return the unspoiled integer value (between -2.147.483.648 and 2.147.483.647)
|
||||
*/
|
||||
int Storage::readInt()
|
||||
{
|
||||
int value = 0;
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
readByEndianess(p_value, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeInt( int value )
|
||||
{
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
writeByEndianess(p_value, 4);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
/**
|
||||
* restores a float , which was split up in four bytes acording to the
|
||||
* specification, it must have been split by its row byte representation
|
||||
* with MSBF-order
|
||||
*
|
||||
* @return the unspoiled float value
|
||||
*/
|
||||
float Storage::readFloat()
|
||||
{
|
||||
float value = 0;
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
readByEndianess(p_value, 4);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeFloat( float value )
|
||||
{
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
writeByEndianess(p_value, 4);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeDouble( double value )
|
||||
{
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
writeByEndianess(p_value, 8);
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
double Storage::readDouble( )
|
||||
{
|
||||
double value = 0;
|
||||
unsigned char *p_value = reinterpret_cast<unsigned char*>(&value);
|
||||
readByEndianess(p_value, 8);
|
||||
return value;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writePacket(unsigned char* packet, int length)
|
||||
{
|
||||
store.insert(store.end(), &(packet[0]), &(packet[length]));
|
||||
iter_ = store.begin(); // reserve() invalidates iterators
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writePacket(const std::vector<unsigned char> &packet)
|
||||
{
|
||||
std::copy(packet.begin(), packet.end(), std::back_inserter(store));
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeStorage(tcpip::Storage& other)
|
||||
{
|
||||
// the compiler cannot deduce to use a const_iterator as source
|
||||
store.insert<StorageType::const_iterator>(store.end(), other.iter_, other.store.end());
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::checkReadSafe(unsigned int num) const
|
||||
{
|
||||
if (std::distance(iter_, store.end()) < static_cast<int>(num))
|
||||
{
|
||||
std::ostringstream msg;
|
||||
msg << "tcpip::Storage::readIsSafe: want to read " << num << " bytes from Storage, "
|
||||
<< "but only " << std::distance(iter_, store.end()) << " remaining";
|
||||
throw std::invalid_argument(msg.str());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
unsigned char Storage::readCharUnsafe()
|
||||
{
|
||||
char hb = *iter_;
|
||||
++iter_;
|
||||
return hb;
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::writeByEndianess(const unsigned char * begin, unsigned int size)
|
||||
{
|
||||
const unsigned char * end = &(begin[size]);
|
||||
if (bigEndian_)
|
||||
store.insert(store.end(), begin, end);
|
||||
else
|
||||
store.insert(store.end(), std::reverse_iterator<const unsigned char *>(end), std::reverse_iterator<const unsigned char *>(begin));
|
||||
iter_ = store.begin();
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
void Storage::readByEndianess(unsigned char * array, int size)
|
||||
{
|
||||
checkReadSafe(size);
|
||||
if (bigEndian_)
|
||||
{
|
||||
for (int i = 0; i < size; ++i)
|
||||
array[i] = readCharUnsafe();
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = size - 1; i >= 0; --i)
|
||||
array[i] = readCharUnsafe();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
std::string Storage::hexDump() const
|
||||
{
|
||||
static const int width = 2;
|
||||
|
||||
std::ostringstream dump;
|
||||
// adapt stream attributes
|
||||
// 'showbase' inserts "0x", 'internal' makes leading '0' appear between "0x" and hex digits
|
||||
dump.setf(std::ostream::hex | std::ostream::showbase | std::ostream::internal);
|
||||
dump.fill('0');
|
||||
|
||||
for(StorageType::const_iterator it = store.begin(); it != store.end(); ++it)
|
||||
{
|
||||
// insert spaces between values
|
||||
if (it != store.begin())
|
||||
dump << " ";
|
||||
dump << std::setw(width) << static_cast<int>(*it);
|
||||
}
|
||||
|
||||
return dump.str();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // BUILD_TCPIP
|
||||
|
||||
/*-----------------------------------------------------------------------
|
||||
* Source $Source: $
|
||||
* Version $Revision: 620 $
|
||||
* Date $Date: 2011-07-08 17:39:10 +0200 (Fri, 08 Jul 2011) $
|
||||
*-----------------------------------------------------------------------
|
||||
* $Log: $
|
||||
*-----------------------------------------------------------------------*/
|
|
@ -1,136 +0,0 @@
|
|||
/************************************************************************
|
||||
** This file is part of the network simulator Shawn. **
|
||||
** Copyright (C) 2004-2007 by the SwarmNet (www.swarmnet.de) project **
|
||||
** Shawn is free software; you can redistribute it and/or modify it **
|
||||
** under the terms of the BSD License. Refer to the shawn-licence.txt **
|
||||
** file in the root of the Shawn source tree for further details. **
|
||||
************************************************************************
|
||||
** **
|
||||
** \author Axel Wegener <wegener@itm.uni-luebeck.de> **
|
||||
** \author Bjoern Hendriks <hendriks@ibr.cs.tu-bs.de> **
|
||||
** **
|
||||
************************************************************************/
|
||||
#ifndef __SHAWN_APPS_TCPIP_STORAGE_H
|
||||
#define __SHAWN_APPS_TCPIP_STORAGE_H
|
||||
|
||||
#ifdef SHAWN
|
||||
#include <shawn_config.h>
|
||||
#include "_apps_enable_cmake.h"
|
||||
#ifdef ENABLE_TCPIP
|
||||
#define BUILD_TCPIP
|
||||
#endif
|
||||
#else
|
||||
#define BUILD_TCPIP
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef BUILD_TCPIP
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <iostream>
|
||||
|
||||
namespace tcpip
|
||||
{
|
||||
|
||||
class Storage
|
||||
{
|
||||
|
||||
public:
|
||||
typedef std::vector<unsigned char> StorageType;
|
||||
|
||||
private:
|
||||
StorageType store;
|
||||
StorageType::const_iterator iter_;
|
||||
|
||||
// sortation of bytes forwards or backwards?
|
||||
bool bigEndian_;
|
||||
|
||||
/// Used in constructors to initialize local variables
|
||||
void init();
|
||||
|
||||
/// Check if the next \p num bytes can be read safely
|
||||
void checkReadSafe(unsigned int num) const;
|
||||
/// Read a byte \em without validity check
|
||||
unsigned char readCharUnsafe();
|
||||
/// Write \p size elements of array \p begin according to endianess
|
||||
void writeByEndianess(const unsigned char * begin, unsigned int size);
|
||||
/// Read \p size elements into \p array according to endianess
|
||||
void readByEndianess(unsigned char * array, int size);
|
||||
|
||||
|
||||
public:
|
||||
|
||||
/// Standard Constructor
|
||||
Storage();
|
||||
|
||||
/// Constructor, that fills the storage with an char array. If length is -1, the whole array is handed over
|
||||
Storage(const unsigned char[], int length=-1);
|
||||
|
||||
// Destructor
|
||||
virtual ~Storage();
|
||||
|
||||
virtual bool valid_pos();
|
||||
virtual unsigned int position() const;
|
||||
|
||||
void reset();
|
||||
/// Dump storage content as series of hex values
|
||||
std::string hexDump() const;
|
||||
|
||||
virtual unsigned char readChar();
|
||||
virtual void writeChar(unsigned char);
|
||||
|
||||
virtual int readByte();
|
||||
virtual void writeByte(int);
|
||||
// virtual void writeByte(unsigned char);
|
||||
|
||||
virtual int readUnsignedByte();
|
||||
virtual void writeUnsignedByte(int);
|
||||
|
||||
virtual std::string readString();
|
||||
virtual void writeString(const std::string& s);
|
||||
|
||||
virtual std::vector<std::string> readStringList();
|
||||
virtual void writeStringList(const std::vector<std::string> &s);
|
||||
|
||||
virtual std::vector<double> readDoubleList();
|
||||
virtual void writeDoubleList(const std::vector<double> &s);
|
||||
|
||||
virtual int readShort();
|
||||
virtual void writeShort(int);
|
||||
|
||||
virtual int readInt();
|
||||
virtual void writeInt(int);
|
||||
|
||||
virtual float readFloat();
|
||||
virtual void writeFloat( float );
|
||||
|
||||
virtual double readDouble();
|
||||
virtual void writeDouble( double );
|
||||
|
||||
virtual void writePacket(unsigned char* packet, int length);
|
||||
virtual void writePacket(const std::vector<unsigned char> &packet);
|
||||
|
||||
virtual void writeStorage(tcpip::Storage& store);
|
||||
|
||||
// Some enabled functions of the underlying std::list
|
||||
StorageType::size_type size() const { return store.size(); }
|
||||
|
||||
StorageType::const_iterator begin() const { return store.begin(); }
|
||||
StorageType::const_iterator end() const { return store.end(); }
|
||||
|
||||
};
|
||||
|
||||
} // namespace tcpip
|
||||
|
||||
#endif // BUILD_TCPIP
|
||||
|
||||
#endif
|
||||
/*-----------------------------------------------------------------------
|
||||
* Source $Source: $
|
||||
* Version $Revision: 620 $
|
||||
* Date $Date: 2011-07-08 17:39:10 +0200 (Fri, 08 Jul 2011) $
|
||||
*-----------------------------------------------------------------------
|
||||
* $Log: $
|
||||
*-----------------------------------------------------------------------*/
|
|
@ -1,21 +0,0 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Matei David, Ontario Institute for Cancer Research
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
|
@ -1,203 +0,0 @@
|
|||
#ifndef __STRICT_FSTREAM_HPP
|
||||
#define __STRICT_FSTREAM_HPP
|
||||
|
||||
#define __STDC_WANT_LIB_EXT1__ 1
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <cstring>
|
||||
#include <string>
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#define NOEXCEPT noexcept
|
||||
#else
|
||||
#define NOEXCEPT
|
||||
#endif
|
||||
|
||||
/**
|
||||
* This namespace defines wrappers for std::ifstream, std::ofstream, and
|
||||
* std::fstream objects. The wrappers perform the following steps:
|
||||
* - check the open modes make sense
|
||||
* - check that the call to open() is successful
|
||||
* - (for input streams) check that the opened file is peek-able
|
||||
* - turn on the badbit in the exception mask
|
||||
*/
|
||||
namespace strict_fstream
|
||||
{
|
||||
|
||||
/// Overload of error-reporting function, to enable use with VS.
|
||||
/// Ref: http://stackoverflow.com/a/901316/717706
|
||||
static std::string strerror()
|
||||
{
|
||||
std::string buff(80, '\0');
|
||||
#if defined _WIN32 || defined __STDC_LIB_EXT1__
|
||||
if (strerror_s(&buff[0], buff.size(), errno) != 0)
|
||||
{
|
||||
buff = "Unknown error";
|
||||
}
|
||||
#else
|
||||
if (strerror_r(errno, &buff[0], buff.size()) != 0)
|
||||
{
|
||||
buff = "Unknown error";
|
||||
}
|
||||
#endif
|
||||
buff.resize(buff.find('\0'));
|
||||
return buff;
|
||||
}
|
||||
|
||||
/// Exception class thrown by failed operations.
|
||||
class Exception
|
||||
: public std::exception
|
||||
{
|
||||
public:
|
||||
Exception(const std::string& msg) : _msg(msg) {}
|
||||
const char * what() const NOEXCEPT { return _msg.c_str(); }
|
||||
private:
|
||||
std::string _msg;
|
||||
}; // class Exception
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
struct static_method_holder
|
||||
{
|
||||
static std::string mode_to_string(std::ios_base::openmode mode)
|
||||
{
|
||||
static const int n_modes = 6;
|
||||
static const std::ios_base::openmode mode_val_v[n_modes] =
|
||||
{
|
||||
std::ios_base::in,
|
||||
std::ios_base::out,
|
||||
std::ios_base::app,
|
||||
std::ios_base::ate,
|
||||
std::ios_base::trunc,
|
||||
std::ios_base::binary
|
||||
};
|
||||
|
||||
static const char * mode_name_v[n_modes] =
|
||||
{
|
||||
"in",
|
||||
"out",
|
||||
"app",
|
||||
"ate",
|
||||
"trunc",
|
||||
"binary"
|
||||
};
|
||||
std::string res;
|
||||
for (int i = 0; i < n_modes; ++i)
|
||||
{
|
||||
if (mode & mode_val_v[i])
|
||||
{
|
||||
res += (! res.empty()? "|" : "");
|
||||
res += mode_name_v[i];
|
||||
}
|
||||
}
|
||||
if (res.empty()) res = "none";
|
||||
return res;
|
||||
}
|
||||
static void check_mode(const std::string& filename, std::ios_base::openmode mode)
|
||||
{
|
||||
if ((mode & std::ios_base::trunc) && ! (mode & std::ios_base::out))
|
||||
{
|
||||
throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and not out");
|
||||
}
|
||||
else if ((mode & std::ios_base::app) && ! (mode & std::ios_base::out))
|
||||
{
|
||||
throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: app and not out");
|
||||
}
|
||||
else if ((mode & std::ios_base::trunc) && (mode & std::ios_base::app))
|
||||
{
|
||||
throw Exception(std::string("strict_fstream: open('") + filename + "'): mode error: trunc and app");
|
||||
}
|
||||
}
|
||||
static void check_open(std::ios * s_p, const std::string& filename, std::ios_base::openmode mode)
|
||||
{
|
||||
if (s_p->fail())
|
||||
{
|
||||
throw Exception(std::string("strict_fstream: open('")
|
||||
+ filename + "'," + mode_to_string(mode) + "): open failed: "
|
||||
+ strerror());
|
||||
}
|
||||
}
|
||||
static void check_peek(std::istream * is_p, const std::string& filename, std::ios_base::openmode mode)
|
||||
{
|
||||
bool peek_failed = true;
|
||||
try
|
||||
{
|
||||
is_p->peek();
|
||||
peek_failed = is_p->fail();
|
||||
}
|
||||
catch (std::ios_base::failure e) {}
|
||||
if (peek_failed)
|
||||
{
|
||||
throw Exception(std::string("strict_fstream: open('")
|
||||
+ filename + "'," + mode_to_string(mode) + "): peek failed: "
|
||||
+ strerror());
|
||||
}
|
||||
is_p->clear();
|
||||
}
|
||||
}; // struct static_method_holder
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class ifstream
|
||||
: public std::ifstream
|
||||
{
|
||||
public:
|
||||
ifstream() = default;
|
||||
ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
open(filename, mode);
|
||||
}
|
||||
void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
mode |= std::ios_base::in;
|
||||
exceptions(std::ios_base::badbit);
|
||||
detail::static_method_holder::check_mode(filename, mode);
|
||||
std::ifstream::open(filename, mode);
|
||||
detail::static_method_holder::check_open(this, filename, mode);
|
||||
detail::static_method_holder::check_peek(this, filename, mode);
|
||||
}
|
||||
}; // class ifstream
|
||||
|
||||
class ofstream
|
||||
: public std::ofstream
|
||||
{
|
||||
public:
|
||||
ofstream() = default;
|
||||
ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
|
||||
{
|
||||
open(filename, mode);
|
||||
}
|
||||
void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
|
||||
{
|
||||
mode |= std::ios_base::out;
|
||||
exceptions(std::ios_base::badbit);
|
||||
detail::static_method_holder::check_mode(filename, mode);
|
||||
std::ofstream::open(filename, mode);
|
||||
detail::static_method_holder::check_open(this, filename, mode);
|
||||
}
|
||||
}; // class ofstream
|
||||
|
||||
class fstream
|
||||
: public std::fstream
|
||||
{
|
||||
public:
|
||||
fstream() = default;
|
||||
fstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
open(filename, mode);
|
||||
}
|
||||
void open(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
{
|
||||
if (! (mode & std::ios_base::out)) mode |= std::ios_base::in;
|
||||
exceptions(std::ios_base::badbit);
|
||||
detail::static_method_holder::check_mode(filename, mode);
|
||||
std::fstream::open(filename, mode);
|
||||
detail::static_method_holder::check_open(this, filename, mode);
|
||||
detail::static_method_holder::check_peek(this, filename, mode);
|
||||
}
|
||||
}; // class fstream
|
||||
|
||||
} // namespace strict_fstream
|
||||
|
||||
#endif
|
|
@ -1,408 +0,0 @@
|
|||
//---------------------------------------------------------
|
||||
// Copyright 2015 Ontario Institute for Cancer Research
|
||||
// Written by Matei David (matei@cs.toronto.edu)
|
||||
//---------------------------------------------------------
|
||||
|
||||
// Reference:
|
||||
// http://stackoverflow.com/questions/14086417/how-to-write-custom-input-stream-in-c
|
||||
|
||||
#ifndef __ZSTR_HPP
|
||||
#define __ZSTR_HPP
|
||||
|
||||
#include <cassert>
|
||||
#include <fstream>
|
||||
#include <sstream>
|
||||
#include <zlib.h>
|
||||
#include "strict_fstream.hpp"
|
||||
|
||||
namespace zstr
|
||||
{
|
||||
|
||||
/// Exception class thrown by failed zlib operations.
|
||||
class Exception
|
||||
: public std::exception
|
||||
{
|
||||
public:
|
||||
Exception(z_stream * zstrm_p, int ret)
|
||||
: _msg("zlib: ")
|
||||
{
|
||||
switch (ret)
|
||||
{
|
||||
case Z_STREAM_ERROR:
|
||||
_msg += "Z_STREAM_ERROR: ";
|
||||
break;
|
||||
case Z_DATA_ERROR:
|
||||
_msg += "Z_DATA_ERROR: ";
|
||||
break;
|
||||
case Z_MEM_ERROR:
|
||||
_msg += "Z_MEM_ERROR: ";
|
||||
break;
|
||||
case Z_VERSION_ERROR:
|
||||
_msg += "Z_VERSION_ERROR: ";
|
||||
break;
|
||||
case Z_BUF_ERROR:
|
||||
_msg += "Z_BUF_ERROR: ";
|
||||
break;
|
||||
default:
|
||||
std::ostringstream oss;
|
||||
oss << ret;
|
||||
_msg += "[" + oss.str() + "]: ";
|
||||
break;
|
||||
}
|
||||
_msg += zstrm_p->msg;
|
||||
}
|
||||
Exception(const std::string msg) : _msg(msg) {}
|
||||
const char * what() const NOEXCEPT { return _msg.c_str(); }
|
||||
private:
|
||||
std::string _msg;
|
||||
}; // class Exception
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
class z_stream_wrapper
|
||||
: public z_stream
|
||||
{
|
||||
public:
|
||||
z_stream_wrapper(bool _is_input = true, int _level = Z_DEFAULT_COMPRESSION)
|
||||
: is_input(_is_input)
|
||||
{
|
||||
this->zalloc = Z_NULL;
|
||||
this->zfree = Z_NULL;
|
||||
this->opaque = Z_NULL;
|
||||
int ret;
|
||||
if (is_input)
|
||||
{
|
||||
this->avail_in = 0;
|
||||
this->next_in = Z_NULL;
|
||||
ret = inflateInit2(this, 15+32);
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = deflateInit2(this, _level, Z_DEFLATED, 15+16, 8, Z_DEFAULT_STRATEGY);
|
||||
}
|
||||
if (ret != Z_OK) throw Exception(this, ret);
|
||||
}
|
||||
~z_stream_wrapper()
|
||||
{
|
||||
if (is_input)
|
||||
{
|
||||
inflateEnd(this);
|
||||
}
|
||||
else
|
||||
{
|
||||
deflateEnd(this);
|
||||
}
|
||||
}
|
||||
private:
|
||||
bool is_input;
|
||||
}; // class z_stream_wrapper
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class istreambuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
istreambuf(std::streambuf * _sbuf_p,
|
||||
std::size_t _buff_size = default_buff_size, bool _auto_detect = true)
|
||||
: sbuf_p(_sbuf_p),
|
||||
zstrm_p(nullptr),
|
||||
buff_size(_buff_size),
|
||||
auto_detect(_auto_detect),
|
||||
auto_detect_run(false),
|
||||
is_text(false)
|
||||
{
|
||||
assert(sbuf_p);
|
||||
in_buff = new char [buff_size];
|
||||
in_buff_start = in_buff;
|
||||
in_buff_end = in_buff;
|
||||
out_buff = new char [buff_size];
|
||||
setg(out_buff, out_buff, out_buff);
|
||||
}
|
||||
|
||||
istreambuf(const istreambuf &) = delete;
|
||||
istreambuf & operator = (const istreambuf &) = delete;
|
||||
|
||||
virtual ~istreambuf()
|
||||
{
|
||||
delete [] in_buff;
|
||||
delete [] out_buff;
|
||||
if (zstrm_p) delete zstrm_p;
|
||||
}
|
||||
|
||||
virtual std::streambuf::int_type underflow()
|
||||
{
|
||||
if (this->gptr() == this->egptr())
|
||||
{
|
||||
// pointers for free region in output buffer
|
||||
char * out_buff_free_start = out_buff;
|
||||
do
|
||||
{
|
||||
// read more input if none available
|
||||
if (in_buff_start == in_buff_end)
|
||||
{
|
||||
// empty input buffer: refill from the start
|
||||
in_buff_start = in_buff;
|
||||
std::streamsize sz = sbuf_p->sgetn(in_buff, buff_size);
|
||||
in_buff_end = in_buff + sz;
|
||||
if (in_buff_end == in_buff_start) break; // end of input
|
||||
}
|
||||
// auto detect if the stream contains text or deflate data
|
||||
if (auto_detect && ! auto_detect_run)
|
||||
{
|
||||
auto_detect_run = true;
|
||||
unsigned char b0 = *reinterpret_cast< unsigned char * >(in_buff_start);
|
||||
unsigned char b1 = *reinterpret_cast< unsigned char * >(in_buff_start + 1);
|
||||
// Ref:
|
||||
// http://en.wikipedia.org/wiki/Gzip
|
||||
// http://stackoverflow.com/questions/9050260/what-does-a-zlib-header-look-like
|
||||
is_text = ! (in_buff_start + 2 <= in_buff_end
|
||||
&& ((b0 == 0x1F && b1 == 0x8B) // gzip header
|
||||
|| (b0 == 0x78 && (b1 == 0x01 // zlib header
|
||||
|| b1 == 0x9C
|
||||
|| b1 == 0xDA))));
|
||||
}
|
||||
if (is_text)
|
||||
{
|
||||
// simply swap in_buff and out_buff, and adjust pointers
|
||||
assert(in_buff_start == in_buff);
|
||||
std::swap(in_buff, out_buff);
|
||||
out_buff_free_start = in_buff_end;
|
||||
in_buff_start = in_buff;
|
||||
in_buff_end = in_buff;
|
||||
}
|
||||
else
|
||||
{
|
||||
// run inflate() on input
|
||||
if (! zstrm_p) zstrm_p = new detail::z_stream_wrapper(true);
|
||||
zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(in_buff_start);
|
||||
zstrm_p->avail_in = (uInt)(in_buff_end - in_buff_start);
|
||||
zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff_free_start);
|
||||
zstrm_p->avail_out = (uInt)((out_buff + buff_size) - out_buff_free_start);
|
||||
int ret = inflate(zstrm_p, Z_NO_FLUSH);
|
||||
// process return code
|
||||
if (ret != Z_OK && ret != Z_STREAM_END) throw Exception(zstrm_p, ret);
|
||||
// update in&out pointers following inflate()
|
||||
in_buff_start = reinterpret_cast< decltype(in_buff_start) >(zstrm_p->next_in);
|
||||
in_buff_end = in_buff_start + zstrm_p->avail_in;
|
||||
out_buff_free_start = reinterpret_cast< decltype(out_buff_free_start) >(zstrm_p->next_out);
|
||||
assert(out_buff_free_start + zstrm_p->avail_out == out_buff + buff_size);
|
||||
// if stream ended, deallocate inflator
|
||||
if (ret == Z_STREAM_END)
|
||||
{
|
||||
delete zstrm_p;
|
||||
zstrm_p = nullptr;
|
||||
}
|
||||
}
|
||||
} while (out_buff_free_start == out_buff);
|
||||
// 2 exit conditions:
|
||||
// - end of input: there might or might not be output available
|
||||
// - out_buff_free_start != out_buff: output available
|
||||
this->setg(out_buff, out_buff, out_buff_free_start);
|
||||
}
|
||||
return this->gptr() == this->egptr()
|
||||
? traits_type::eof()
|
||||
: traits_type::to_int_type(*this->gptr());
|
||||
}
|
||||
private:
|
||||
std::streambuf * sbuf_p;
|
||||
char * in_buff;
|
||||
char * in_buff_start;
|
||||
char * in_buff_end;
|
||||
char * out_buff;
|
||||
detail::z_stream_wrapper * zstrm_p;
|
||||
std::size_t buff_size;
|
||||
bool auto_detect;
|
||||
bool auto_detect_run;
|
||||
bool is_text;
|
||||
|
||||
static const std::size_t default_buff_size = (std::size_t)1 << 20;
|
||||
}; // class istreambuf
|
||||
|
||||
class ostreambuf
|
||||
: public std::streambuf
|
||||
{
|
||||
public:
|
||||
ostreambuf(std::streambuf * _sbuf_p,
|
||||
std::size_t _buff_size = default_buff_size, int _level = Z_DEFAULT_COMPRESSION)
|
||||
: sbuf_p(_sbuf_p),
|
||||
zstrm_p(new detail::z_stream_wrapper(false, _level)),
|
||||
buff_size(_buff_size)
|
||||
{
|
||||
assert(sbuf_p);
|
||||
in_buff = new char [buff_size];
|
||||
out_buff = new char [buff_size];
|
||||
setp(in_buff, in_buff + buff_size);
|
||||
}
|
||||
|
||||
ostreambuf(const ostreambuf &) = delete;
|
||||
ostreambuf & operator = (const ostreambuf &) = delete;
|
||||
|
||||
int deflate_loop(int flush)
|
||||
{
|
||||
int ret = Z_OK;
|
||||
while (ret != Z_STREAM_END && ret != Z_BUF_ERROR)
|
||||
{
|
||||
zstrm_p->next_out = reinterpret_cast< decltype(zstrm_p->next_out) >(out_buff);
|
||||
zstrm_p->avail_out = (uInt)buff_size;
|
||||
ret = deflate(zstrm_p, flush);
|
||||
if (ret != Z_OK && ret != Z_STREAM_END && ret != Z_BUF_ERROR) throw Exception(zstrm_p, ret);
|
||||
std::streamsize sz = sbuf_p->sputn(out_buff, reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff);
|
||||
if (sz != reinterpret_cast< decltype(out_buff) >(zstrm_p->next_out) - out_buff)
|
||||
{
|
||||
// there was an error in the sink stream
|
||||
return -1;
|
||||
}
|
||||
if (sz == 0)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
virtual ~ostreambuf()
|
||||
{
|
||||
// flush the zlib stream
|
||||
//
|
||||
// NOTE: Errors here (sync() return value not 0) are ignored, because we
|
||||
// cannot throw in a destructor. This mirrors the behaviour of
|
||||
// std::basic_filebuf::~basic_filebuf(). To see an exception on error,
|
||||
// close the ofstream with an explicit call to close(), and do not rely
|
||||
// on the implicit call in the destructor.
|
||||
//
|
||||
sync();
|
||||
delete [] in_buff;
|
||||
delete [] out_buff;
|
||||
delete zstrm_p;
|
||||
}
|
||||
virtual std::streambuf::int_type overflow(std::streambuf::int_type c = traits_type::eof())
|
||||
{
|
||||
zstrm_p->next_in = reinterpret_cast< decltype(zstrm_p->next_in) >(pbase());
|
||||
zstrm_p->avail_in = (uInt)(pptr() - pbase());
|
||||
while (zstrm_p->avail_in > 0)
|
||||
{
|
||||
int r = deflate_loop(Z_NO_FLUSH);
|
||||
if (r != 0)
|
||||
{
|
||||
setp(nullptr, nullptr);
|
||||
return traits_type::eof();
|
||||
}
|
||||
}
|
||||
setp(in_buff, in_buff + buff_size);
|
||||
return traits_type::eq_int_type(c, traits_type::eof()) ? traits_type::eof() : sputc((char)c);
|
||||
}
|
||||
virtual int sync()
|
||||
{
|
||||
// first, call overflow to clear in_buff
|
||||
overflow();
|
||||
if (! pptr()) return -1;
|
||||
// then, call deflate asking to finish the zlib stream
|
||||
zstrm_p->next_in = nullptr;
|
||||
zstrm_p->avail_in = 0;
|
||||
if (deflate_loop(Z_FINISH) != 0) return -1;
|
||||
deflateReset(zstrm_p);
|
||||
return 0;
|
||||
}
|
||||
private:
|
||||
std::streambuf * sbuf_p;
|
||||
char * in_buff;
|
||||
char * out_buff;
|
||||
detail::z_stream_wrapper * zstrm_p;
|
||||
std::size_t buff_size;
|
||||
|
||||
static const std::size_t default_buff_size = (std::size_t)1 << 20;
|
||||
}; // class ostreambuf
|
||||
|
||||
class istream
|
||||
: public std::istream
|
||||
{
|
||||
public:
|
||||
istream(std::istream & is)
|
||||
: std::istream(new istreambuf(is.rdbuf()))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
explicit istream(std::streambuf * sbuf_p)
|
||||
: std::istream(new istreambuf(sbuf_p))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
virtual ~istream()
|
||||
{
|
||||
delete rdbuf();
|
||||
}
|
||||
}; // class istream
|
||||
|
||||
class ostream
|
||||
: public std::ostream
|
||||
{
|
||||
public:
|
||||
ostream(std::ostream & os)
|
||||
: std::ostream(new ostreambuf(os.rdbuf()))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
explicit ostream(std::streambuf * sbuf_p)
|
||||
: std::ostream(new ostreambuf(sbuf_p))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
virtual ~ostream()
|
||||
{
|
||||
delete rdbuf();
|
||||
}
|
||||
}; // class ostream
|
||||
|
||||
namespace detail
|
||||
{
|
||||
|
||||
template < typename FStream_Type >
|
||||
struct strict_fstream_holder
|
||||
{
|
||||
strict_fstream_holder(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
: _fs(filename, mode)
|
||||
{}
|
||||
FStream_Type _fs;
|
||||
}; // class strict_fstream_holder
|
||||
|
||||
} // namespace detail
|
||||
|
||||
class ifstream
|
||||
: private detail::strict_fstream_holder< strict_fstream::ifstream >,
|
||||
public std::istream
|
||||
{
|
||||
public:
|
||||
explicit ifstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::in)
|
||||
: detail::strict_fstream_holder< strict_fstream::ifstream >(filename, mode),
|
||||
std::istream(new istreambuf(_fs.rdbuf()))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
virtual ~ifstream()
|
||||
{
|
||||
if (rdbuf()) delete rdbuf();
|
||||
}
|
||||
}; // class ifstream
|
||||
|
||||
class ofstream
|
||||
: private detail::strict_fstream_holder< strict_fstream::ofstream >,
|
||||
public std::ostream
|
||||
{
|
||||
public:
|
||||
explicit ofstream(const std::string& filename, std::ios_base::openmode mode = std::ios_base::out)
|
||||
: detail::strict_fstream_holder< strict_fstream::ofstream >(filename, mode | std::ios_base::binary),
|
||||
std::ostream(new ostreambuf(_fs.rdbuf()))
|
||||
{
|
||||
exceptions(std::ios_base::badbit);
|
||||
}
|
||||
virtual ~ofstream()
|
||||
{
|
||||
if (rdbuf()) delete rdbuf();
|
||||
}
|
||||
}; // class ofstream
|
||||
|
||||
} // namespace zstr
|
||||
|
||||
#endif
|
|
@ -1,281 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file Helper.h
|
||||
/// @author Robert Hilbrich
|
||||
/// @author Leonhard Luecken
|
||||
/// @date 15.09.2017
|
||||
///
|
||||
// C++ TraCI client API implementation
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <memory>
|
||||
#include <libsumo/Subscription.h>
|
||||
#include <microsim/MSNet.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class Position;
|
||||
class PositionVector;
|
||||
class RGBColor;
|
||||
class MSEdge;
|
||||
class SUMOTrafficObject;
|
||||
class MSPerson;
|
||||
class MSVehicle;
|
||||
class MSBaseVehicle;
|
||||
class MSVehicleType;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// type definitions
|
||||
// ===========================================================================
|
||||
typedef std::map<const MSLane*, std::pair<double, double> > LaneCoverageInfo; // also declared in MSLane.h!
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
|
||||
class LaneStoringVisitor {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
LaneStoringVisitor(std::set<const Named*>& objects, const PositionVector& shape,
|
||||
const double range, const int domain)
|
||||
: myObjects(objects), myShape(shape), myRange(range), myDomain(domain) {}
|
||||
|
||||
/// @brief Destructor
|
||||
~LaneStoringVisitor() {}
|
||||
|
||||
/// @brief Adds the given object to the container
|
||||
void add(const MSLane* const l) const;
|
||||
|
||||
/// @brief The container
|
||||
std::set<const Named*>& myObjects;
|
||||
const PositionVector& myShape;
|
||||
const double myRange;
|
||||
const int myDomain;
|
||||
|
||||
private:
|
||||
/// @brief invalidated copy constructor
|
||||
LaneStoringVisitor(const LaneStoringVisitor& src);
|
||||
|
||||
/// @brief invalidated assignment operator
|
||||
LaneStoringVisitor& operator=(const LaneStoringVisitor& src);
|
||||
};
|
||||
|
||||
#define LANE_RTREE_QUAL RTree<MSLane*, MSLane, float, 2, LaneStoringVisitor>
|
||||
template<>
|
||||
inline float LANE_RTREE_QUAL::RectSphericalVolume(Rect* a_rect) {
|
||||
ASSERT(a_rect);
|
||||
const float extent0 = a_rect->m_max[0] - a_rect->m_min[0];
|
||||
const float extent1 = a_rect->m_max[1] - a_rect->m_min[1];
|
||||
return .78539816f * (extent0 * extent0 + extent1 * extent1);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline LANE_RTREE_QUAL::Rect LANE_RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB) {
|
||||
ASSERT(a_rectA && a_rectB);
|
||||
Rect newRect;
|
||||
newRect.m_min[0] = rtree_min(a_rectA->m_min[0], a_rectB->m_min[0]);
|
||||
newRect.m_max[0] = rtree_max(a_rectA->m_max[0], a_rectB->m_max[0]);
|
||||
newRect.m_min[1] = rtree_min(a_rectA->m_min[1], a_rectB->m_min[1]);
|
||||
newRect.m_max[1] = rtree_max(a_rectA->m_max[1], a_rectB->m_max[1]);
|
||||
return newRect;
|
||||
}
|
||||
|
||||
namespace libsumo {
|
||||
|
||||
/**
|
||||
* @class Helper
|
||||
* @brief C++ TraCI client API implementation
|
||||
*/
|
||||
class Helper {
|
||||
public:
|
||||
static void subscribe(const int commandId, const std::string& id, const std::vector<int>& variables,
|
||||
const double beginTime, const double endTime, const int contextDomain = 0, const double range = 0.);
|
||||
|
||||
static void addSubscriptionParam(double param);
|
||||
|
||||
static void handleSubscriptions(const SUMOTime t);
|
||||
|
||||
static bool needNewSubscription(libsumo::Subscription& s, std::vector<Subscription>& subscriptions, libsumo::Subscription*& modifiedSubscription);
|
||||
|
||||
static void clearSubscriptions();
|
||||
|
||||
static Subscription* addSubscriptionFilter(SubscriptionFilterType filter);
|
||||
|
||||
/// @brief helper functions
|
||||
static TraCIPositionVector makeTraCIPositionVector(const PositionVector& positionVector);
|
||||
static TraCIPosition makeTraCIPosition(const Position& position, const bool includeZ = false);
|
||||
static Position makePosition(const TraCIPosition& position);
|
||||
|
||||
static PositionVector makePositionVector(const TraCIPositionVector& vector);
|
||||
static TraCIColor makeTraCIColor(const RGBColor& color);
|
||||
static RGBColor makeRGBColor(const TraCIColor& color);
|
||||
|
||||
static MSEdge* getEdge(const std::string& edgeID);
|
||||
static const MSLane* getLaneChecking(const std::string& edgeID, int laneIndex, double pos);
|
||||
static std::pair<MSLane*, double> convertCartesianToRoadMap(const Position& pos, const SUMOVehicleClass vClass);
|
||||
static double getDrivingDistance(std::pair<const MSLane*, double>& roadPos1, std::pair<const MSLane*, double>& roadPos2);
|
||||
|
||||
static MSBaseVehicle* getVehicle(const std::string& id);
|
||||
static MSPerson* getPerson(const std::string& id);
|
||||
static SUMOTrafficObject* getTrafficObject(int domain, const std::string& id);
|
||||
static const MSVehicleType& getVehicleType(const std::string& vehicleID);
|
||||
|
||||
static void findObjectShape(int domain, const std::string& id, PositionVector& shape);
|
||||
|
||||
static void collectObjectsInRange(int domain, const PositionVector& shape, double range, std::set<const Named*>& into);
|
||||
static void collectObjectIDsInRange(int domain, const PositionVector& shape, double range, std::set<std::string>& into);
|
||||
|
||||
/**
|
||||
* @brief Filter the given ID-Set (which was obtained from an R-Tree search)
|
||||
* according to the filters set by the subscription or firstly build the object ID list if
|
||||
* the filters rather demand searching along the road network than considering a geometric range.
|
||||
* @param[in] s Subscription which holds the filter specification to be applied
|
||||
* @param[in/out] objIDs Set of object IDs that is to be filtered. Result is stored in place.
|
||||
* @note Currently this assumes that the objects are vehicles.
|
||||
*/
|
||||
static void applySubscriptionFilters(const Subscription& s, std::set<std::string>& objIDs);
|
||||
|
||||
static void applySubscriptionFilterFieldOfVision(const Subscription& s, std::set<std::string>& objIDs);
|
||||
|
||||
static void applySubscriptionFilterLateralDistanceSinglePass(const Subscription& s,
|
||||
std::set<std::string>& objIDs,
|
||||
std::set<const SUMOTrafficObject*>& vehs,
|
||||
const std::vector<const MSLane*>& lanes,
|
||||
double posOnLane, double posLat, bool isDownstream);
|
||||
|
||||
static void setRemoteControlled(MSVehicle* v, Position xyPos, MSLane* l, double pos, double posLat, double angle,
|
||||
int edgeOffset, ConstMSEdgeVector route, SUMOTime t);
|
||||
|
||||
static void setRemoteControlled(MSPerson* p, Position xyPos, MSLane* l, double pos, double posLat, double angle,
|
||||
int edgeOffset, ConstMSEdgeVector route, SUMOTime t);
|
||||
|
||||
static void postProcessRemoteControl();
|
||||
|
||||
static void cleanup();
|
||||
|
||||
static void registerVehicleStateListener();
|
||||
|
||||
static const std::vector<std::string>& getVehicleStateChanges(const MSNet::VehicleState state);
|
||||
|
||||
static void clearVehicleStates();
|
||||
|
||||
/// @name functions for moveToXY
|
||||
/// @{
|
||||
static bool moveToXYMap(const Position& pos, double maxRouteDistance, bool mayLeaveNetwork, const std::string& origID,
|
||||
const double angle, double speed, const ConstMSEdgeVector& currentRoute, const int routePosition,
|
||||
MSLane* currentLane, double currentLanePos, bool onRoad, SUMOVehicleClass vClass, bool setLateralPos,
|
||||
double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset, ConstMSEdgeVector& edges);
|
||||
|
||||
static bool moveToXYMap_matchingRoutePosition(const Position& pos, const std::string& origID,
|
||||
const ConstMSEdgeVector& currentRoute, int routeIndex,
|
||||
SUMOVehicleClass vClass, bool setLateralPos,
|
||||
double& bestDistance, MSLane** lane, double& lanePos, int& routeOffset);
|
||||
|
||||
static bool findCloserLane(const MSEdge* edge, const Position& pos, SUMOVehicleClass vClass, double& bestDistance, MSLane** lane);
|
||||
|
||||
class LaneUtility {
|
||||
public:
|
||||
LaneUtility(double dist_, double perpendicularDist_, double lanePos_, double angleDiff_, bool ID_,
|
||||
bool onRoute_, bool sameEdge_, const MSEdge* prevEdge_, const MSEdge* nextEdge_) :
|
||||
dist(dist_), perpendicularDist(perpendicularDist_), lanePos(lanePos_), angleDiff(angleDiff_), ID(ID_),
|
||||
onRoute(onRoute_), sameEdge(sameEdge_), prevEdge(prevEdge_), nextEdge(nextEdge_) {}
|
||||
~LaneUtility() {}
|
||||
|
||||
double dist;
|
||||
double perpendicularDist;
|
||||
double lanePos;
|
||||
double angleDiff;
|
||||
bool ID;
|
||||
bool onRoute;
|
||||
bool sameEdge;
|
||||
const MSEdge* prevEdge;
|
||||
const MSEdge* nextEdge;
|
||||
};
|
||||
/// @}
|
||||
|
||||
class SubscriptionWrapper final : public VariableWrapper {
|
||||
public:
|
||||
SubscriptionWrapper(VariableWrapper::SubscriptionHandler handler, SubscriptionResults& into, ContextSubscriptionResults& context);
|
||||
void setContext(const std::string& refID);
|
||||
void setParams(const std::vector<unsigned char>* params);
|
||||
const std::vector<unsigned char>* getParams() const {
|
||||
return myParams;
|
||||
}
|
||||
void clear();
|
||||
bool wrapDouble(const std::string& objID, const int variable, const double value);
|
||||
bool wrapInt(const std::string& objID, const int variable, const int value);
|
||||
bool wrapString(const std::string& objID, const int variable, const std::string& value);
|
||||
bool wrapStringList(const std::string& objID, const int variable, const std::vector<std::string>& value);
|
||||
bool wrapPosition(const std::string& objID, const int variable, const TraCIPosition& value);
|
||||
bool wrapColor(const std::string& objID, const int variable, const TraCIColor& value);
|
||||
bool wrapRoadPosition(const std::string& objID, const int variable, const TraCIRoadPosition& value);
|
||||
private:
|
||||
SubscriptionResults& myResults;
|
||||
ContextSubscriptionResults& myContextResults;
|
||||
SubscriptionResults* myActiveResults;
|
||||
const std::vector<unsigned char>* myParams = nullptr;
|
||||
private:
|
||||
/// @brief Invalidated assignment operator
|
||||
SubscriptionWrapper& operator=(const SubscriptionWrapper& s) = delete;
|
||||
};
|
||||
|
||||
private:
|
||||
static void handleSingleSubscription(const Subscription& s);
|
||||
|
||||
/// @brief Adds lane coverage information from newLaneCoverage into aggregatedLaneCoverage
|
||||
/// @param[in/out] aggregatedLaneCoverage - aggregated lane coverage info, to which the new will be added
|
||||
/// @param[in] newLaneCoverage - new lane coverage to be added
|
||||
/// @todo Disjunct ranges are not handled (LaneCoverageInfo definition would need to allow several intervals per lane) but
|
||||
/// the intermediate range is simply assimilated.
|
||||
static void fuseLaneCoverage(std::shared_ptr<LaneCoverageInfo> aggregatedLaneCoverage, const std::shared_ptr<LaneCoverageInfo> newLaneCoverage);
|
||||
|
||||
static void debugPrint(const SUMOTrafficObject* veh);
|
||||
|
||||
private:
|
||||
class VehicleStateListener : public MSNet::VehicleStateListener {
|
||||
public:
|
||||
void vehicleStateChanged(const SUMOVehicle* const vehicle, MSNet::VehicleState to, const std::string& info = "");
|
||||
/// @brief Changes in the states of simulated vehicles
|
||||
std::map<MSNet::VehicleState, std::vector<std::string> > myVehicleStateChanges;
|
||||
};
|
||||
|
||||
/// @brief The list of known, still valid subscriptions
|
||||
static std::vector<Subscription> mySubscriptions;
|
||||
|
||||
/// @brief The last context subscription
|
||||
static Subscription* myLastContextSubscription;
|
||||
|
||||
/// @brief Map of commandIds -> their executors; applicable if the executor applies to the method footprint
|
||||
static std::map<int, std::shared_ptr<VariableWrapper> > myWrapper;
|
||||
|
||||
/// @brief Changes in the states of simulated vehicles
|
||||
static VehicleStateListener myVehicleStateListener;
|
||||
|
||||
/// @brief A storage of lanes
|
||||
static LANE_RTREE_QUAL* myLaneTree;
|
||||
|
||||
static std::map<std::string, MSVehicle*> myRemoteControlledVehicles;
|
||||
static std::map<std::string, MSPerson*> myRemoteControlledPersons;
|
||||
|
||||
/// @brief invalidated standard constructor
|
||||
Helper() = delete;
|
||||
};
|
||||
|
||||
}
|
|
@ -1,165 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file Subscription.h
|
||||
/// @author Michael Behrisch
|
||||
/// @date 2007/10/24
|
||||
///
|
||||
// Subscription representation for libsumo and TraCI
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <libsumo/TraCIDefs.h>
|
||||
#include <utils/common/SUMOTime.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
namespace libsumo {
|
||||
|
||||
/** @brief Filter types for context subscriptions
|
||||
*/
|
||||
enum SubscriptionFilterType {
|
||||
// No filters
|
||||
SUBS_FILTER_NONE = 0,
|
||||
// Filter by list of lanes relative to ego vehicle
|
||||
SUBS_FILTER_LANES = 1,
|
||||
// Exclude vehicles on opposite (and other) lanes from context subscription result
|
||||
SUBS_FILTER_NOOPPOSITE = 1 << 1,
|
||||
// Specify maximal downstream distance for vehicles in context subscription result
|
||||
SUBS_FILTER_DOWNSTREAM_DIST = 1 << 2,
|
||||
// Specify maximal upstream distance for vehicles in context subscription result
|
||||
SUBS_FILTER_UPSTREAM_DIST = 1 << 3,
|
||||
// Only return leader and follower on specified lanes in context subscription result
|
||||
SUBS_FILTER_LEAD_FOLLOW = 1 << 4,
|
||||
// Only return foes on upcoming junction in context subscription result
|
||||
SUBS_FILTER_TURN = 1 << 6,
|
||||
// Only return vehicles of the given vClass in context subscription result
|
||||
SUBS_FILTER_VCLASS = 1 << 7,
|
||||
// Only return vehicles of the given vType in context subscription result
|
||||
SUBS_FILTER_VTYPE = 1 << 8,
|
||||
// Only return vehicles within field of vision in context subscription result
|
||||
// NOTE: relies on rTree, therefore incompatible with SUBS_FILTER_NO_RTREE
|
||||
SUBS_FILTER_FIELD_OF_VISION = 1 << 9,
|
||||
// Only return vehicles within the given lateral distance in context subscription result
|
||||
SUBS_FILTER_LATERAL_DIST = 1 << 10,
|
||||
// Filter category for measuring distances along the road network instead of using the usual rtree query
|
||||
SUBS_FILTER_NO_RTREE = SUBS_FILTER_LANES | SUBS_FILTER_DOWNSTREAM_DIST | SUBS_FILTER_UPSTREAM_DIST | SUBS_FILTER_LEAD_FOLLOW | SUBS_FILTER_TURN | SUBS_FILTER_LATERAL_DIST,
|
||||
// Filter category for maneuver filters
|
||||
SUBS_FILTER_MANEUVER = SUBS_FILTER_LEAD_FOLLOW | SUBS_FILTER_TURN,
|
||||
};
|
||||
|
||||
/** @class Subscription
|
||||
* @brief Representation of a subscription
|
||||
*/
|
||||
class Subscription {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] commandIdArg The command id of the subscription
|
||||
* @param[in] idArg The id of the object that is subscribed
|
||||
* @param[in] variablesArg The subscribed variables
|
||||
* @param[in] paramsArg The parameters for the subscribed variables
|
||||
* @param[in] beginTimeArg The begin time of the subscription
|
||||
* @param[in] endTimeArg The end time of the subscription
|
||||
* @param[in] contextDomainArg The domain ID of the context
|
||||
* @param[in] rangeArg The range of the context
|
||||
*/
|
||||
Subscription(int commandIdArg, const std::string& idArg,
|
||||
const std::vector<int>& variablesArg,
|
||||
const std::vector<std::vector<unsigned char>>& paramsArg,
|
||||
SUMOTime beginTimeArg, SUMOTime endTimeArg,
|
||||
int contextDomainArg, double rangeArg)
|
||||
: commandId(commandIdArg),
|
||||
id(idArg),
|
||||
variables(variablesArg),
|
||||
parameters(paramsArg),
|
||||
beginTime(beginTimeArg),
|
||||
endTime(endTimeArg),
|
||||
contextDomain(contextDomainArg),
|
||||
range(rangeArg),
|
||||
activeFilters(SUBS_FILTER_NONE),
|
||||
filterLanes(),
|
||||
filterDownstreamDist(-1),
|
||||
filterUpstreamDist(-1),
|
||||
filterVTypes(),
|
||||
filterVClasses(0),
|
||||
filterFieldOfVisionOpeningAngle(-1),
|
||||
filterLateralDist(-1) {}
|
||||
|
||||
bool isVehicleToVehicleContextSubscription() const {
|
||||
return commandId == CMD_SUBSCRIBE_VEHICLE_CONTEXT && contextDomain == CMD_GET_VEHICLE_VARIABLE;
|
||||
}
|
||||
|
||||
bool isVehicleToPersonContextSubscription() const {
|
||||
return commandId == CMD_SUBSCRIBE_VEHICLE_CONTEXT && contextDomain == CMD_GET_PERSON_VARIABLE;
|
||||
}
|
||||
|
||||
/// @brief commandIdArg The command id of the subscription
|
||||
int commandId;
|
||||
/// @brief The id of the object that is subscribed
|
||||
std::string id;
|
||||
/// @brief The subscribed variables
|
||||
std::vector<int> variables;
|
||||
/// @brief The parameters for the subscribed variables
|
||||
std::vector<std::vector<unsigned char> > parameters;
|
||||
/// @brief The begin time of the subscription
|
||||
SUMOTime beginTime;
|
||||
/// @brief The end time of the subscription
|
||||
SUMOTime endTime;
|
||||
/// @brief The domain ID of the context
|
||||
int contextDomain;
|
||||
/// @brief The range of the context
|
||||
double range;
|
||||
|
||||
/// @brief Active filters for the subscription (bitset, @see SubscriptionFilterType)
|
||||
int activeFilters;
|
||||
/// @brief lanes specified by the lanes filter
|
||||
std::vector<int> filterLanes;
|
||||
/// @brief Downstream distance specified by the downstream distance filter
|
||||
double filterDownstreamDist;
|
||||
/// @brief Upstream distance specified by the upstream distance filter
|
||||
double filterUpstreamDist;
|
||||
/// @brief vTypes specified by the vTypes filter
|
||||
std::set<std::string> filterVTypes;
|
||||
/// @brief vClasses specified by the vClasses filter, @see SVCPermissions
|
||||
int filterVClasses;
|
||||
/// @brief Opening angle (in deg) specified by the field of vision filter
|
||||
double filterFieldOfVisionOpeningAngle;
|
||||
/// @brief Lateral distance specified by the lateral distance filter
|
||||
double filterLateralDist;
|
||||
};
|
||||
|
||||
class VariableWrapper {
|
||||
public:
|
||||
/// @brief Definition of a method to be called for serving an associated commandID
|
||||
typedef bool(*SubscriptionHandler)(const std::string& objID, const int variable, VariableWrapper* wrapper);
|
||||
VariableWrapper(SubscriptionHandler handler = nullptr) : handle(handler) {}
|
||||
SubscriptionHandler handle;
|
||||
virtual void setContext(const std::string& /* refID */) {}
|
||||
virtual void setParams(const std::vector<unsigned char>* /* params */) {}
|
||||
virtual const std::vector<unsigned char>* getParams() const {
|
||||
return nullptr;
|
||||
}
|
||||
virtual void clear() {}
|
||||
virtual bool wrapDouble(const std::string& objID, const int variable, const double value) = 0;
|
||||
virtual bool wrapInt(const std::string& objID, const int variable, const int value) = 0;
|
||||
virtual bool wrapString(const std::string& objID, const int variable, const std::string& value) = 0;
|
||||
virtual bool wrapStringList(const std::string& objID, const int variable, const std::vector<std::string>& value) = 0;
|
||||
virtual bool wrapPosition(const std::string& objID, const int variable, const TraCIPosition& value) = 0;
|
||||
virtual bool wrapColor(const std::string& objID, const int variable, const TraCIColor& value) = 0;
|
||||
virtual bool wrapRoadPosition(const std::string& objID, const int variable, const TraCIRoadPosition& value) = 0;
|
||||
};
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,427 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file TraCIDefs.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Mario Krumnow
|
||||
/// @author Michael Behrisch
|
||||
/// @author Robert Hilbrich
|
||||
/// @date 30.05.2012
|
||||
///
|
||||
// C++ TraCI client API implementation
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
// we do not include config.h here, since we should be independent of a special sumo build
|
||||
#include <libsumo/TraCIConstants.h>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <stdexcept>
|
||||
#include <sstream>
|
||||
#include <memory>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// global definitions
|
||||
// ===========================================================================
|
||||
|
||||
#define LIBSUMO_SUBSCRIPTION_API \
|
||||
static void subscribe(const std::string& objectID, const std::vector<int>& varIDs = std::vector<int>({-1}), double begin = libsumo::INVALID_DOUBLE_VALUE, double end = libsumo::INVALID_DOUBLE_VALUE); \
|
||||
static void unsubscribe(const std::string& objectID); \
|
||||
static void subscribeContext(const std::string& objectID, int domain, double dist, const std::vector<int>& varIDs = std::vector<int>({-1}), double begin = libsumo::INVALID_DOUBLE_VALUE, double end = libsumo::INVALID_DOUBLE_VALUE); \
|
||||
static void unsubscribeContext(const std::string& objectID, int domain, double dist); \
|
||||
static const SubscriptionResults getAllSubscriptionResults(); \
|
||||
static const TraCIResults getSubscriptionResults(const std::string& objectID); \
|
||||
static const ContextSubscriptionResults getAllContextSubscriptionResults(); \
|
||||
static const SubscriptionResults getContextSubscriptionResults(const std::string& objectID);
|
||||
|
||||
#define LIBSUMO_SUBSCRIPTION_IMPLEMENTATION(CLASS, DOMAIN) \
|
||||
void \
|
||||
CLASS::subscribe(const std::string& objectID, const std::vector<int>& varIDs, double begin, double end) { \
|
||||
libsumo::Helper::subscribe(CMD_SUBSCRIBE_##DOMAIN##_VARIABLE, objectID, varIDs, begin, end); \
|
||||
} \
|
||||
void \
|
||||
CLASS::unsubscribe(const std::string& objectID) { \
|
||||
libsumo::Helper::subscribe(CMD_SUBSCRIBE_##DOMAIN##_VARIABLE, objectID, std::vector<int>(), libsumo::INVALID_DOUBLE_VALUE, libsumo::INVALID_DOUBLE_VALUE); \
|
||||
} \
|
||||
void \
|
||||
CLASS::subscribeContext(const std::string& objectID, int domain, double dist, const std::vector<int>& varIDs, double begin, double end) { \
|
||||
libsumo::Helper::subscribe(CMD_SUBSCRIBE_##DOMAIN##_CONTEXT, objectID, varIDs, begin, end, domain, dist); \
|
||||
} \
|
||||
void \
|
||||
CLASS::unsubscribeContext(const std::string& objectID, int domain, double dist) { \
|
||||
libsumo::Helper::subscribe(CMD_SUBSCRIBE_##DOMAIN##_CONTEXT, objectID, std::vector<int>(), libsumo::INVALID_DOUBLE_VALUE, libsumo::INVALID_DOUBLE_VALUE, domain, dist); \
|
||||
} \
|
||||
const SubscriptionResults \
|
||||
CLASS::getAllSubscriptionResults() { \
|
||||
return mySubscriptionResults; \
|
||||
} \
|
||||
const TraCIResults \
|
||||
CLASS::getSubscriptionResults(const std::string& objectID) { \
|
||||
return mySubscriptionResults[objectID]; \
|
||||
} \
|
||||
const ContextSubscriptionResults \
|
||||
CLASS::getAllContextSubscriptionResults() { \
|
||||
return myContextSubscriptionResults; \
|
||||
} \
|
||||
const SubscriptionResults \
|
||||
CLASS::getContextSubscriptionResults(const std::string& objectID) { \
|
||||
return myContextSubscriptionResults[objectID]; \
|
||||
}
|
||||
|
||||
|
||||
#define LIBSUMO_GET_PARAMETER_WITH_KEY_API \
|
||||
static const std::pair<std::string, std::string> getParameterWithKey(const std::string& objectID, const std::string& key);
|
||||
|
||||
#define LIBSUMO_GET_PARAMETER_WITH_KEY_IMPLEMENTATION(CLASS) \
|
||||
const std::pair<std::string, std::string> \
|
||||
CLASS::getParameterWithKey(const std::string& objectID, const std::string& key) { \
|
||||
return std::make_pair(key, getParameter(objectID, key)); \
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class and type definitions
|
||||
// ===========================================================================
|
||||
namespace libsumo {
|
||||
/**
|
||||
* @class TraCIException
|
||||
*/
|
||||
class TraCIException : public std::runtime_error {
|
||||
public:
|
||||
/** constructor */
|
||||
TraCIException(std::string what)
|
||||
: std::runtime_error(what) {}
|
||||
};
|
||||
|
||||
/// @name Structures definitions
|
||||
/// @{
|
||||
|
||||
struct TraCIResult {
|
||||
virtual ~TraCIResult() {}
|
||||
virtual std::string getString() {
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
/** @struct TraCIPosition
|
||||
* @brief A 3D-position
|
||||
*/
|
||||
struct TraCIPosition : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCIPosition(" << x << "," << y << "," << z << ")";
|
||||
return os.str();
|
||||
}
|
||||
double x = INVALID_DOUBLE_VALUE, y = INVALID_DOUBLE_VALUE, z = INVALID_DOUBLE_VALUE;
|
||||
};
|
||||
|
||||
/** @struct TraCIRoadPosition
|
||||
* @brief An edgeId, position and laneIndex
|
||||
*/
|
||||
struct TraCIRoadPosition : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCIRoadPosition(" << edgeID << "_" << laneIndex << "," << pos << ")";
|
||||
return os.str();
|
||||
}
|
||||
std::string edgeID;
|
||||
double pos;
|
||||
int laneIndex = INVALID_INT_VALUE;
|
||||
};
|
||||
|
||||
/** @struct TraCIColor
|
||||
* @brief A color
|
||||
*/
|
||||
struct TraCIColor : TraCIResult {
|
||||
TraCIColor() : r(0), g(0), b(0), a(255) {}
|
||||
TraCIColor(int r, int g, int b, int a = 255) : r(r), g(g), b(b), a(a) {}
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCIColor(" << r << "," << g << "," << b << "," << a << ")";
|
||||
return os.str();
|
||||
}
|
||||
int r, g, b, a;
|
||||
};
|
||||
|
||||
|
||||
/** @struct TraCILeaderDistance
|
||||
* @brief A leaderId and distance to leader
|
||||
*/
|
||||
struct TraCILeaderDistance : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCILeaderDistance(" << leaderID << "," << dist << ")";
|
||||
return os.str();
|
||||
}
|
||||
std::string leaderID;
|
||||
double dist;
|
||||
};
|
||||
|
||||
|
||||
/** @struct TraCIPositionVector
|
||||
* @brief A list of positions
|
||||
*/
|
||||
typedef std::vector<TraCIPosition> TraCIPositionVector;
|
||||
|
||||
|
||||
struct TraCIInt : TraCIResult {
|
||||
TraCIInt() : value(0) {}
|
||||
TraCIInt(int v) : value(v) {}
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << value;
|
||||
return os.str();
|
||||
}
|
||||
int value;
|
||||
};
|
||||
|
||||
|
||||
struct TraCIDouble : TraCIResult {
|
||||
TraCIDouble() : value(0.) {}
|
||||
TraCIDouble(double v) : value(v) {}
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << value;
|
||||
return os.str();
|
||||
}
|
||||
double value;
|
||||
};
|
||||
|
||||
|
||||
struct TraCIString : TraCIResult {
|
||||
TraCIString() : value("") {}
|
||||
TraCIString(std::string v) : value(v) {}
|
||||
std::string getString() {
|
||||
return value;
|
||||
}
|
||||
std::string value;
|
||||
};
|
||||
|
||||
|
||||
struct TraCIStringList : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "[";
|
||||
for (std::string v : value) {
|
||||
os << v << ",";
|
||||
}
|
||||
os << "]";
|
||||
return os.str();
|
||||
}
|
||||
std::vector<std::string> value;
|
||||
};
|
||||
|
||||
|
||||
/// @brief {variable->value}
|
||||
typedef std::map<int, std::shared_ptr<TraCIResult> > TraCIResults;
|
||||
/// @brief {object->{variable->value}}
|
||||
typedef std::map<std::string, TraCIResults> SubscriptionResults;
|
||||
typedef std::map<std::string, SubscriptionResults> ContextSubscriptionResults;
|
||||
|
||||
|
||||
class TraCIPhase {
|
||||
public:
|
||||
TraCIPhase() {}
|
||||
TraCIPhase(const double _duration, const std::string& _state, const double _minDur = libsumo::INVALID_DOUBLE_VALUE,
|
||||
const double _maxDur = libsumo::INVALID_DOUBLE_VALUE,
|
||||
const std::vector<int>& _next = std::vector<int>(),
|
||||
const std::string& _name = "") :
|
||||
duration(_duration), state(_state), minDur(_minDur), maxDur(_maxDur), next(_next), name(_name) {}
|
||||
~TraCIPhase() {}
|
||||
|
||||
double duration;
|
||||
std::string state;
|
||||
double minDur, maxDur;
|
||||
std::vector<int> next;
|
||||
std::string name;
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
#ifdef SWIG
|
||||
%template(TraCIPhaseVector) std::vector<libsumo::TraCIPhase*>; // *NOPAD*
|
||||
#endif
|
||||
|
||||
|
||||
namespace libsumo {
|
||||
class TraCILogic {
|
||||
public:
|
||||
TraCILogic() {}
|
||||
TraCILogic(const std::string& _programID, const int _type, const int _currentPhaseIndex,
|
||||
const std::vector<libsumo::TraCIPhase*>& _phases = std::vector<libsumo::TraCIPhase*>())
|
||||
: programID(_programID), type(_type), currentPhaseIndex(_currentPhaseIndex), phases(_phases) {}
|
||||
~TraCILogic() {}
|
||||
|
||||
std::string programID;
|
||||
int type;
|
||||
int currentPhaseIndex;
|
||||
std::vector<TraCIPhase*> phases;
|
||||
std::map<std::string, std::string> subParameter;
|
||||
};
|
||||
|
||||
|
||||
class TraCILink {
|
||||
public:
|
||||
TraCILink(const std::string& _from, const std::string& _via, const std::string& _to)
|
||||
: fromLane(_from), viaLane(_via), toLane(_to) {}
|
||||
~TraCILink() {}
|
||||
|
||||
std::string fromLane;
|
||||
std::string viaLane;
|
||||
std::string toLane;
|
||||
};
|
||||
|
||||
|
||||
class TraCIConnection {
|
||||
public:
|
||||
TraCIConnection() {} // this is needed by SWIG when building a vector of this type, please don't use it
|
||||
TraCIConnection(const std::string& _approachedLane, const bool _hasPrio, const bool _isOpen, const bool _hasFoe,
|
||||
const std::string _approachedInternal, const std::string _state, const std::string _direction, const double _length)
|
||||
: approachedLane(_approachedLane), hasPrio(_hasPrio), isOpen(_isOpen), hasFoe(_hasFoe),
|
||||
approachedInternal(_approachedInternal), state(_state), direction(_direction), length(_length) {}
|
||||
~TraCIConnection() {}
|
||||
|
||||
std::string approachedLane;
|
||||
bool hasPrio;
|
||||
bool isOpen;
|
||||
bool hasFoe;
|
||||
std::string approachedInternal;
|
||||
std::string state;
|
||||
std::string direction;
|
||||
double length;
|
||||
};
|
||||
|
||||
|
||||
/// @brief mirrors MSInductLoop::VehicleData
|
||||
struct TraCIVehicleData {
|
||||
/// @brief The id of the vehicle
|
||||
std::string id;
|
||||
/// @brief Length of the vehicle
|
||||
double length;
|
||||
/// @brief Entry-time of the vehicle in [s]
|
||||
double entryTime;
|
||||
/// @brief Leave-time of the vehicle in [s]
|
||||
double leaveTime;
|
||||
/// @brief Type of the vehicle in
|
||||
std::string typeID;
|
||||
};
|
||||
|
||||
|
||||
struct TraCINextTLSData {
|
||||
/// @brief The id of the next tls
|
||||
std::string id;
|
||||
/// @brief The tls index of the controlled link
|
||||
int tlIndex;
|
||||
/// @brief The distance to the tls
|
||||
double dist;
|
||||
/// @brief The current state of the tls
|
||||
char state;
|
||||
};
|
||||
|
||||
|
||||
struct TraCINextStopData : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCINextStopData(" << lane << "," << endPos << "," << stoppingPlaceID << "," << stopFlags << "," << duration << "," << until << ")";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
/// @brief The lane to stop at
|
||||
std::string lane;
|
||||
/// @brief The stopping position end
|
||||
double endPos;
|
||||
/// @brief Id assigned to the stop
|
||||
std::string stoppingPlaceID;
|
||||
/// @brief Stop flags
|
||||
int stopFlags;
|
||||
/// @brief The stopping duration
|
||||
double duration;
|
||||
/// @brief The time at which the vehicle may continue its journey
|
||||
double until;
|
||||
};
|
||||
|
||||
|
||||
/** @struct TraCINextStopDataVector
|
||||
* @brief A list of vehicle stops
|
||||
* @see TraCINextStopData
|
||||
*/
|
||||
struct TraCINextStopDataVector : TraCIResult {
|
||||
std::string getString() {
|
||||
std::ostringstream os;
|
||||
os << "TraCINextStopDataVector[";
|
||||
for (TraCINextStopData v : value) {
|
||||
os << v.getString() << ",";
|
||||
}
|
||||
os << "]";
|
||||
return os.str();
|
||||
}
|
||||
|
||||
std::vector<TraCINextStopData> value;
|
||||
};
|
||||
|
||||
|
||||
struct TraCIBestLanesData {
|
||||
/// @brief The id of the lane
|
||||
std::string laneID;
|
||||
/// @brief The length than can be driven from that lane without lane change
|
||||
double length;
|
||||
/// @brief The traffic density along length
|
||||
double occupation;
|
||||
/// @brief The offset of this lane from the best lane
|
||||
int bestLaneOffset;
|
||||
/// @brief Whether this lane allows continuing the route
|
||||
bool allowsContinuation;
|
||||
/// @brief The sequence of lanes that best allows continuing the route without lane change
|
||||
std::vector<std::string> continuationLanes;
|
||||
};
|
||||
|
||||
|
||||
class TraCIStage {
|
||||
public:
|
||||
TraCIStage(int type = INVALID_INT_VALUE, const std::string& vType = "", const std::string& line = "", const std::string& destStop = "",
|
||||
const std::vector<std::string>& edges = std::vector<std::string>(),
|
||||
double travelTime = INVALID_DOUBLE_VALUE, double cost = INVALID_DOUBLE_VALUE, double length = INVALID_DOUBLE_VALUE,
|
||||
const std::string& intended = "", double depart = INVALID_DOUBLE_VALUE, double departPos = INVALID_DOUBLE_VALUE,
|
||||
double arrivalPos = INVALID_DOUBLE_VALUE, const std::string& description = "") :
|
||||
type(type), vType(vType), line(line), destStop(destStop), edges(edges), travelTime(travelTime), cost(cost),
|
||||
length(length), intended(intended), depart(depart), departPos(departPos), arrivalPos(arrivalPos), description(description) {}
|
||||
/// @brief The type of stage (walking, driving, ...)
|
||||
int type;
|
||||
/// @brief The vehicle type when using a private car or bike
|
||||
std::string vType;
|
||||
/// @brief The line or the id of the vehicle type
|
||||
std::string line;
|
||||
/// @brief The id of the destination stop
|
||||
std::string destStop;
|
||||
/// @brief The sequence of edges to travel
|
||||
std::vector<std::string> edges;
|
||||
/// @brief duration of the stage in seconds
|
||||
double travelTime;
|
||||
/// @brief effort needed
|
||||
double cost;
|
||||
/// @brief length in m
|
||||
double length;
|
||||
/// @brief id of the intended vehicle for public transport ride
|
||||
std::string intended;
|
||||
/// @brief intended depart time for public transport ride or INVALID_DOUBLE_VALUE
|
||||
double depart;
|
||||
/// @brief position on the lane when starting the stage
|
||||
double departPos;
|
||||
/// @brief position on the lane when ending the stage
|
||||
double arrivalPos;
|
||||
/// @brief arbitrary description string
|
||||
std::string description;
|
||||
};
|
||||
}
|
|
@ -1,174 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSJunction.h
|
||||
/// @author Christian Roessel
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @date Wed, 12 Dez 2001
|
||||
///
|
||||
// The base class for an intersection
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <utils/geom/Position.h>
|
||||
#include <utils/geom/PositionVector.h>
|
||||
#include <utils/common/Named.h>
|
||||
#include <utils/common/Parameterised.h>
|
||||
#include <utils/common/SUMOTime.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/xml/SUMOXMLDefinitions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class MSVehicle;
|
||||
class MSLink;
|
||||
class MSLane;
|
||||
class MSEdge;
|
||||
class MSJunctionLogic;
|
||||
|
||||
typedef std::vector<MSEdge*> MSEdgeVector;
|
||||
typedef std::vector<const MSEdge*> ConstMSEdgeVector;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSJunction
|
||||
* @brief The base class for an intersection
|
||||
*/
|
||||
class MSJunction : public Named, public Parameterised {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the junction
|
||||
* @param[in] position The position of the junction
|
||||
* @param[in] shape The shape of the junction
|
||||
*/
|
||||
MSJunction(const std::string& id,
|
||||
SumoXMLNodeType type,
|
||||
const Position& position,
|
||||
const PositionVector& shape,
|
||||
const std::string& name);
|
||||
|
||||
|
||||
/// @brief Destructor.
|
||||
virtual ~MSJunction();
|
||||
|
||||
|
||||
/** performs some initialisation after the loading
|
||||
(e.g., link map computation) */
|
||||
virtual void postloadInit();
|
||||
|
||||
|
||||
/** returns the junction's position */
|
||||
const Position& getPosition() const;
|
||||
|
||||
|
||||
/** @brief Returns this junction's shape
|
||||
* @return The shape of this junction
|
||||
*/
|
||||
const PositionVector& getShape() const {
|
||||
return myShape;
|
||||
}
|
||||
|
||||
/// @brief return the junction name
|
||||
const std::string& getName() const {
|
||||
return myName;
|
||||
}
|
||||
|
||||
virtual const std::vector<MSLink*>& getFoeLinks(const MSLink* const /*srcLink*/) const {
|
||||
return myEmptyLinks;
|
||||
}
|
||||
|
||||
virtual const std::vector<MSLane*>& getFoeInternalLanes(const MSLink* const /*srcLink*/) const {
|
||||
return myEmptyLanes;
|
||||
}
|
||||
|
||||
inline const ConstMSEdgeVector& getIncoming() const {
|
||||
return myIncoming;
|
||||
}
|
||||
|
||||
int getNrOfIncomingLanes() const;
|
||||
|
||||
inline const ConstMSEdgeVector& getOutgoing() const {
|
||||
return myOutgoing;
|
||||
}
|
||||
|
||||
/** @brief Returns all internal lanes on the junction
|
||||
*/
|
||||
virtual const std::vector<MSLane*> getInternalLanes() const {
|
||||
return myEmptyLanes;
|
||||
}
|
||||
|
||||
void addIncoming(MSEdge* edge) {
|
||||
myIncoming.push_back(edge);
|
||||
}
|
||||
|
||||
void addOutgoing(MSEdge* edge) {
|
||||
myOutgoing.push_back(edge);
|
||||
}
|
||||
|
||||
/// @brief return the type of this Junction
|
||||
SumoXMLNodeType getType() const {
|
||||
return myType;
|
||||
}
|
||||
|
||||
/// @brief erase vehicle from myLinkLeaders
|
||||
void passedJunction(const MSVehicle* vehicle);
|
||||
|
||||
// @brief return the underlying right-of-way and conflict matrix
|
||||
virtual const MSJunctionLogic* getLogic() const {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief Tye type of this junction
|
||||
SumoXMLNodeType myType;
|
||||
|
||||
/// @brief The position of the junction
|
||||
Position myPosition;
|
||||
|
||||
/// @brief The shape of the junction
|
||||
PositionVector myShape;
|
||||
|
||||
/// @briefh The (optional) junction name
|
||||
std::string myName;
|
||||
|
||||
std::vector<MSLink*> myEmptyLinks;
|
||||
std::vector<MSLane*> myEmptyLanes;
|
||||
|
||||
|
||||
/// @brief incoming edges
|
||||
ConstMSEdgeVector myIncoming;
|
||||
/// @brief outgoing edges
|
||||
ConstMSEdgeVector myOutgoing;
|
||||
|
||||
/// @brief definition of the static dictionary type
|
||||
typedef std::map<std::string, MSJunction* > DictType;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated copy constructor.
|
||||
MSJunction(const MSJunction&);
|
||||
|
||||
/// @brief Invalidated assignment operator.
|
||||
MSJunction& operator=(const MSJunction&);
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,225 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2002-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSLeaderInfo.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Oct 2015
|
||||
///
|
||||
// Information about vehicles ahead (may be multiple vehicles if
|
||||
// lateral-resolution is active)
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class MSVehicle;
|
||||
class MSLane;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// types definitions
|
||||
// ===========================================================================
|
||||
typedef std::pair<const MSVehicle*, double> CLeaderDist;
|
||||
typedef std::pair<MSVehicle*, double> LeaderDist;
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSLeaderInfo
|
||||
*/
|
||||
class MSLeaderInfo {
|
||||
public:
|
||||
/// Constructor
|
||||
MSLeaderInfo(const MSLane* lane, const MSVehicle* ego = 0, double latOffset = 0);
|
||||
|
||||
/// Destructor
|
||||
virtual ~MSLeaderInfo();
|
||||
|
||||
/* @brief adds this vehicle as a leader in the appropriate sublanes
|
||||
* @param[in] veh The vehicle to add
|
||||
* @param[in] beyond Whether the vehicle is beyond the existing leaders (and thus may be shadowed by them)
|
||||
* @param[in] latOffset The lateral offset that must be added to the position of veh
|
||||
* @return The number of free sublanes
|
||||
*/
|
||||
virtual int addLeader(const MSVehicle* veh, bool beyond, double latOffset = 0);
|
||||
|
||||
/// @brief discard all information
|
||||
virtual void clear();
|
||||
|
||||
/* @brief returns sublanes occupied by veh
|
||||
* @param[in] veh The vehicle to check
|
||||
* @param[in] latOffset The offset value to add to the vehicle position
|
||||
* @param[out] rightmost The rightmost sublane occupied by veh
|
||||
* @param[out] leftmost The rightmost sublane occupied by veh
|
||||
*/
|
||||
void getSubLanes(const MSVehicle* veh, double latOffset, int& rightmost, int& leftmost) const;
|
||||
|
||||
/* @brief returns the sublane boundaries of the ith sublane
|
||||
* @param[in] sublane The sublane to check
|
||||
* @param[in] latOffset The offset value to add to the result
|
||||
* @param[out] rightSide The right border of the given sublane
|
||||
* @param[out] leftSide The left border of the given sublane
|
||||
*/
|
||||
void getSublaneBorders(int sublane, double latOffset, double& rightSide, double& leftSide) const;
|
||||
|
||||
/// @brief return the vehicle for the given sublane
|
||||
const MSVehicle* operator[](int sublane) const;
|
||||
|
||||
int numSublanes() const {
|
||||
return (int)myVehicles.size();
|
||||
}
|
||||
|
||||
int numFreeSublanes() const {
|
||||
return myFreeSublanes;
|
||||
}
|
||||
|
||||
bool hasVehicles() const {
|
||||
return myHasVehicles;
|
||||
}
|
||||
|
||||
const std::vector<const MSVehicle*>& getVehicles() const {
|
||||
return myVehicles;
|
||||
}
|
||||
|
||||
/// @brief whether a stopped vehicle is leader
|
||||
bool hasStoppedVehicle() const;
|
||||
|
||||
/// @brief print a debugging representation
|
||||
virtual std::string toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief the width of the lane to which this instance applies
|
||||
// @note: not const to simplify assignment
|
||||
double myWidth;
|
||||
|
||||
std::vector<const MSVehicle*> myVehicles;
|
||||
|
||||
/// @brief the number of free sublanes
|
||||
// if an ego vehicle is given in the constructor, the number of free
|
||||
// sublanes of those covered by ego
|
||||
int myFreeSublanes;
|
||||
|
||||
/// @brief borders of the ego vehicle for filtering of free sublanes
|
||||
int egoRightMost;
|
||||
int egoLeftMost;
|
||||
|
||||
bool myHasVehicles;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/// @brief saves leader/follower vehicles and their distances relative to an ego vehicle
|
||||
class MSLeaderDistanceInfo : public MSLeaderInfo {
|
||||
public:
|
||||
/// Constructor
|
||||
MSLeaderDistanceInfo(const MSLane* lane, const MSVehicle* ego, double latOffset);
|
||||
|
||||
/// @brief Construct for the non-sublane-case
|
||||
MSLeaderDistanceInfo(const CLeaderDist& cLeaderDist, const MSLane* dummy);
|
||||
|
||||
/// Destructor
|
||||
virtual ~MSLeaderDistanceInfo();
|
||||
|
||||
/* @brief adds this vehicle as a leader in the appropriate sublanes
|
||||
* @param[in] veh The vehicle to add
|
||||
* @param[in] gap The gap between the egoFront+minGap to the back of veh
|
||||
* or from the back of ego to the front+minGap of veh
|
||||
* @param[in] latOffset The lateral offset that must be added to the position of veh
|
||||
* @param[in] sublane The single sublane to which this leader shall be checked (-1 means: check for all)
|
||||
* @return The number of free sublanes
|
||||
*/
|
||||
virtual int addLeader(const MSVehicle* veh, double gap, double latOffset = 0, int sublane = -1);
|
||||
|
||||
virtual int addLeader(const MSVehicle* veh, bool beyond, double latOffset = 0) {
|
||||
UNUSED_PARAMETER(veh);
|
||||
UNUSED_PARAMETER(beyond);
|
||||
UNUSED_PARAMETER(latOffset);
|
||||
throw ProcessError("Method not supported");
|
||||
}
|
||||
|
||||
/// @brief discard all information
|
||||
virtual void clear();
|
||||
|
||||
/// @brief return the vehicle and its distance for the given sublane
|
||||
CLeaderDist operator[](int sublane) const;
|
||||
|
||||
/// @brief print a debugging representation
|
||||
virtual std::string toString() const;
|
||||
|
||||
const std::vector<double>& getDistances() const {
|
||||
return myDistances;
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
std::vector<double> myDistances;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/* @brief saves follower vehicles and their distances as well as their required gap relative to an ego vehicle
|
||||
* when adding new followers, the one with the largest required gap is recored
|
||||
* (rather than the one with the smallest gap) */
|
||||
class MSCriticalFollowerDistanceInfo : public MSLeaderDistanceInfo {
|
||||
public:
|
||||
/// Constructor
|
||||
MSCriticalFollowerDistanceInfo(const MSLane* lane, const MSVehicle* ego, double latOffset);
|
||||
|
||||
/// Destructor
|
||||
virtual ~MSCriticalFollowerDistanceInfo();
|
||||
|
||||
/* @brief adds this vehicle as a follower in the appropriate sublanes
|
||||
* @param[in] veh The vehicle to add
|
||||
* @param[in] ego The vehicle which is being followed
|
||||
* @param[in] gap The distance from the back of ego to the follower
|
||||
* @param[in] latOffset The lateral offset that must be added to the position of veh
|
||||
* @param[in] sublane The single sublane to which this leader shall be checked (-1 means: check for all)
|
||||
* @return The number of free sublanes
|
||||
*/
|
||||
int addFollower(const MSVehicle* veh, const MSVehicle* ego, double gap, double latOffset = 0, int sublane = -1);
|
||||
|
||||
virtual int addLeader(const MSVehicle* veh, double gap, double latOffset = 0, int sublane = -1) {
|
||||
UNUSED_PARAMETER(veh);
|
||||
UNUSED_PARAMETER(gap);
|
||||
UNUSED_PARAMETER(latOffset);
|
||||
UNUSED_PARAMETER(sublane);
|
||||
throw ProcessError("Method not supported");
|
||||
}
|
||||
|
||||
virtual int addLeader(const MSVehicle* veh, bool beyond, double latOffset = 0) {
|
||||
UNUSED_PARAMETER(veh);
|
||||
UNUSED_PARAMETER(beyond);
|
||||
UNUSED_PARAMETER(latOffset);
|
||||
throw ProcessError("Method not supported");
|
||||
}
|
||||
|
||||
/// @brief discard all information
|
||||
void clear();
|
||||
|
||||
/// @brief print a debugging representation
|
||||
std::string toString() const;
|
||||
|
||||
protected:
|
||||
|
||||
// @brief the differences between requriedGap and actual gap for each of the followers
|
||||
std::vector<double> myMissingGaps;
|
||||
|
||||
};
|
|
@ -1,682 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2002-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSLink.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A connnection between lanes
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utils/common/SUMOTime.h>
|
||||
#include <utils/common/SUMOVehicleClass.h>
|
||||
#include <utils/vehicle/SUMOVehicle.h>
|
||||
#include <utils/xml/SUMOXMLDefinitions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class MSLane;
|
||||
class MSJunction;
|
||||
class MSVehicle;
|
||||
class MSPerson;
|
||||
class OutputDevice;
|
||||
class MSTrafficLightLogic;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSLinks
|
||||
* @brief A connnection between lanes
|
||||
*
|
||||
* A link is basically a connection between two lanes, stored within the
|
||||
* originating (the one that is being left) lane and pointing to the
|
||||
* approached lane. When using inner-junction simulation, additionally
|
||||
* a "via-lane" is stored, the one that is used to cross the junction
|
||||
* and which represents the links shape.
|
||||
*
|
||||
* Because right-of-way rules are controlled by the junctions, the link
|
||||
* stores the information about where to write information about approaching
|
||||
* vehicles (the "request") and where to get the information whether the
|
||||
* vehicle really may drive (the "respond").
|
||||
*
|
||||
* Because a link is a connection over a junction, it basically also has a
|
||||
* length. This length is needed to assure that vehicles have the correct halting
|
||||
* distance before approaching the link. In the case of using internal lanes,
|
||||
* the link's length is 0.
|
||||
*/
|
||||
class MSLink {
|
||||
public:
|
||||
|
||||
// distance to link in m below which adaptation for zipper-merging should take place
|
||||
static const double ZIPPER_ADAPT_DIST;
|
||||
|
||||
struct LinkLeader {
|
||||
LinkLeader(MSVehicle* _veh, double _gap, double _distToCrossing, bool _fromLeft = true) :
|
||||
vehAndGap(std::make_pair(_veh, _gap)),
|
||||
distToCrossing(_distToCrossing),
|
||||
fromLeft(_fromLeft) {
|
||||
}
|
||||
|
||||
std::pair<MSVehicle*, double> vehAndGap;
|
||||
double distToCrossing;
|
||||
bool fromLeft;
|
||||
};
|
||||
|
||||
typedef std::vector<LinkLeader> LinkLeaders;
|
||||
|
||||
/** @struct ApproachingVehicleInformation
|
||||
* @brief A structure holding the information about vehicles approaching a link
|
||||
*/
|
||||
struct ApproachingVehicleInformation {
|
||||
/** @brief Constructor
|
||||
* @param[in] waitingTime The time during which the vehicle is waiting at this link
|
||||
* this needs to be placed here because MSVehicle::myWaitingTime is updated in between
|
||||
* calls to opened() causing order dependencies
|
||||
**/
|
||||
ApproachingVehicleInformation(const SUMOTime _arrivalTime, const SUMOTime _leavingTime,
|
||||
const double _arrivalSpeed, const double _leaveSpeed,
|
||||
const bool _willPass,
|
||||
const SUMOTime _arrivalTimeBraking,
|
||||
const double _arrivalSpeedBraking,
|
||||
const SUMOTime _waitingTime,
|
||||
const double _dist,
|
||||
const double _speed
|
||||
) :
|
||||
arrivalTime(_arrivalTime), leavingTime(_leavingTime),
|
||||
arrivalSpeed(_arrivalSpeed), leaveSpeed(_leaveSpeed),
|
||||
willPass(_willPass),
|
||||
arrivalTimeBraking(_arrivalTimeBraking),
|
||||
arrivalSpeedBraking(_arrivalSpeedBraking),
|
||||
waitingTime(_waitingTime),
|
||||
dist(_dist),
|
||||
speed(_speed) {
|
||||
}
|
||||
|
||||
/// @brief The time the vehicle's front arrives at the link
|
||||
const SUMOTime arrivalTime;
|
||||
/// @brief The estimated time at which the vehicle leaves the link
|
||||
const SUMOTime leavingTime;
|
||||
/// @brief The estimated speed with which the vehicle arrives at the link (for headway computation)
|
||||
const double arrivalSpeed;
|
||||
/// @brief The estimated speed with which the vehicle leaves the link (for headway computation)
|
||||
const double leaveSpeed;
|
||||
/// @brief Whether the vehicle wants to pass the link (@todo: check semantics)
|
||||
const bool willPass;
|
||||
/// @brief The time the vehicle's front arrives at the link if it starts braking
|
||||
const SUMOTime arrivalTimeBraking;
|
||||
/// @brief The estimated speed with which the vehicle arrives at the link if it starts braking(for headway computation)
|
||||
const double arrivalSpeedBraking;
|
||||
/// @brief The waiting duration at the current link
|
||||
const SUMOTime waitingTime;
|
||||
/// @brief The distance up to the current link
|
||||
const double dist;
|
||||
/// @brief The current speed
|
||||
const double speed;
|
||||
|
||||
private:
|
||||
/// invalidated assignment operator
|
||||
ApproachingVehicleInformation& operator=(const ApproachingVehicleInformation& s);
|
||||
|
||||
};
|
||||
|
||||
typedef std::map<const SUMOVehicle*, const ApproachingVehicleInformation, ComparatorNumericalIdLess> ApproachInfos;
|
||||
typedef std::vector<const SUMOVehicle*> BlockingFoes;
|
||||
|
||||
/** @brief Constructor for simulation which uses internal lanes
|
||||
*
|
||||
* @param[in] succLane The lane approached by this link
|
||||
* @param[in] via The lane to use within the junction
|
||||
* @param[in] dir The direction of this link
|
||||
* @param[in] state The state of this link
|
||||
* @param[in] length The length of this link
|
||||
*/
|
||||
MSLink(MSLane* predLane, MSLane* succLane, MSLane* via, LinkDirection dir, LinkState state, double length, double foeVisibilityDistance, bool keepClear, MSTrafficLightLogic* logic, int tlLinkIdx);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~MSLink();
|
||||
|
||||
|
||||
/** @brief Sets the request information
|
||||
*
|
||||
* Because traffic lights and junction logics are loaded after links,
|
||||
* we have to assign the information about the right-of-way
|
||||
* requests and responses after the initialisation.
|
||||
* @todo Unsecure!
|
||||
*/
|
||||
void setRequestInformation(int index, bool hasFoes, bool isCont,
|
||||
const std::vector<MSLink*>& foeLinks, const std::vector<MSLane*>& foeLanes,
|
||||
MSLane* internalLaneBefore = 0);
|
||||
|
||||
/// @brief add walkingarea as foe (when entering the junction)
|
||||
void addWalkingAreaFoe(const MSLane* lane) {
|
||||
myWalkingAreaFoe = lane;
|
||||
}
|
||||
|
||||
/// @brief add walkingarea as foe (when leaving the junction)
|
||||
void addWalkingAreaFoeExit(const MSLane* lane) {
|
||||
myWalkingAreaFoeExit = lane;
|
||||
}
|
||||
|
||||
/// @brief get walkingarea as foes
|
||||
const MSLane* getWalkingAreaFoe() {
|
||||
return myWalkingAreaFoe;
|
||||
}
|
||||
const MSLane* getWalkingAreaFoeExit() {
|
||||
return myWalkingAreaFoeExit;
|
||||
}
|
||||
|
||||
/** @brief Sets the information about an approaching vehicle
|
||||
*
|
||||
* The information is stored in myApproachingVehicles.
|
||||
*/
|
||||
void setApproaching(const SUMOVehicle* approaching, const SUMOTime arrivalTime,
|
||||
const double arrivalSpeed, const double leaveSpeed, const bool setRequest,
|
||||
const SUMOTime arrivalTimeBraking, const double arrivalSpeedBraking,
|
||||
const SUMOTime waitingTime, double dist);
|
||||
|
||||
/** @brief Sets the information about an approaching vehicle */
|
||||
void setApproaching(const SUMOVehicle* approaching, ApproachingVehicleInformation ai);
|
||||
|
||||
/// @brief removes the vehicle from myApproachingVehicles
|
||||
void removeApproaching(const SUMOVehicle* veh);
|
||||
|
||||
void addBlockedLink(MSLink* link);
|
||||
|
||||
/* @brief return information about this vehicle if it is registered as
|
||||
* approaching (dummy values otherwise)
|
||||
* @note used for visualisation of link items */
|
||||
ApproachingVehicleInformation getApproaching(const SUMOVehicle* veh) const;
|
||||
|
||||
/// @brief return all approaching vehicles
|
||||
const ApproachInfos& getApproaching() const {
|
||||
return myApproachingVehicles;
|
||||
}
|
||||
|
||||
/** @brief Remove all approaching vehicles before quick-loading state */
|
||||
void clearState();
|
||||
|
||||
/** @brief Returns the information whether the link may be passed
|
||||
*
|
||||
* Valid after the junctions have set their reponds
|
||||
*
|
||||
* @param[in] collectFoes If a vector is passed, all blocking foes are collected and inserted into this vector
|
||||
* @return Whether this link may be passed.
|
||||
*/
|
||||
bool opened(SUMOTime arrivalTime, double arrivalSpeed, double leaveSpeed, double vehicleLength,
|
||||
double impatience, double decel, SUMOTime waitingTime,
|
||||
double posLat = 0,
|
||||
BlockingFoes* collectFoes = nullptr,
|
||||
bool ignoreRed = false,
|
||||
const SUMOVehicle* ego = nullptr) const;
|
||||
|
||||
/** @brief Returns the information whether this link is blocked
|
||||
* Valid after the vehicles have set their requests
|
||||
* @param[in] arrivalTime The arrivalTime of the vehicle who checks for an approaching foe
|
||||
* @param[in] leaveTime The leaveTime of the vehicle who checks for an approaching foe
|
||||
* @param[in] arrivalSpeed The speed with which the checking vehicle plans to arrive at the link
|
||||
* @param[in] leaveSpeed The speed with which the checking vehicle plans to leave the link
|
||||
* @param[in] sameTargetLane Whether the link that calls this method has the same target lane as this link
|
||||
* @param[in] impatience The impatience of the checking vehicle
|
||||
* @param[in] decel The maximum deceleration of the checking vehicle
|
||||
* @param[in] waitingTime The waiting time of the checking vehicle
|
||||
* @param[in] collectFoes If a vector is passed the return value is always False, instead all blocking foes are collected and inserted into this vector
|
||||
* @return Whether this link is blocked
|
||||
* @note Since this needs to be called without a SUMOVehicle (TraCI), we cannot simply pass the checking vehicle itself
|
||||
**/
|
||||
bool blockedAtTime(SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
|
||||
bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
|
||||
BlockingFoes* collectFoes = nullptr, const SUMOVehicle* ego = nullptr) const;
|
||||
|
||||
|
||||
bool isBlockingAnyone() const {
|
||||
return myApproachingVehicles.size() != 0;
|
||||
}
|
||||
|
||||
bool willHaveBlockedFoe() const;
|
||||
|
||||
|
||||
|
||||
/** @brief Returns the information whether a vehicle is approaching on one of the link's foe streams
|
||||
*
|
||||
* Valid after the vehicles have set their requests
|
||||
* @param[in] arrivalTime The arrivalTime of the vehicle who checks for an approaching foe
|
||||
* @param[in] leaveTime The leaveTime of the vehicle who checks for an approaching foe
|
||||
* @param[in] speed The speed with which the checking vehicle plans to leave the link
|
||||
* @param[in] decel The maximum deceleration of the checking vehicle
|
||||
* @return Whether a foe of this link is approaching
|
||||
*/
|
||||
bool hasApproachingFoe(SUMOTime arrivalTime, SUMOTime leaveTime, double speed, double decel) const;
|
||||
|
||||
/** @brief get the foe vehicle that is closest to the intersection or nullptr along with the foe link
|
||||
* This function is used for finding circular deadlock at right_before_left junctions
|
||||
* @param[in] wrapAround The link on which the ego vehicle wants to enter the junction
|
||||
*/
|
||||
std::pair<const SUMOVehicle*, const MSLink*> getFirstApproachingFoe(const MSLink* wrapAround) const;
|
||||
|
||||
MSJunction* getJunction() const {
|
||||
return myJunction;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the current state of the link
|
||||
*
|
||||
* @return The current state of this link
|
||||
*/
|
||||
LinkState getState() const {
|
||||
return myState;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the off-state for the link
|
||||
*
|
||||
* @return The current state of this link
|
||||
*/
|
||||
LinkState getOffState() const {
|
||||
return myOffState;
|
||||
}
|
||||
|
||||
|
||||
//@brief Returns the time of the last state change
|
||||
inline SUMOTime getLastStateChange() const {
|
||||
return myLastStateChange;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the direction the vehicle passing this link take
|
||||
*
|
||||
* @return The direction of this link
|
||||
*/
|
||||
LinkDirection getDirection() const;
|
||||
|
||||
|
||||
/** @brief Sets the current tl-state
|
||||
*
|
||||
* @param[in] state The current state of the link
|
||||
* @param[in] t The time of the state change
|
||||
*/
|
||||
void setTLState(LinkState state, SUMOTime t);
|
||||
|
||||
|
||||
/** @brief Returns the connected lane
|
||||
*
|
||||
* @return The lane approached by this link
|
||||
*/
|
||||
MSLane* getLane() const;
|
||||
|
||||
|
||||
/** @brief Returns the respond index (for visualization)
|
||||
*
|
||||
* @return The respond index for this link
|
||||
*/
|
||||
inline int getIndex() const {
|
||||
return myIndex;
|
||||
}
|
||||
|
||||
/** @brief Returns the TLS index */
|
||||
inline int getTLIndex() const {
|
||||
return myTLIndex;
|
||||
}
|
||||
|
||||
/** @brief Returns the TLS index */
|
||||
inline const MSTrafficLightLogic* getTLLogic() const {
|
||||
return myLogic;
|
||||
}
|
||||
|
||||
/** @brief Returns whether this link is a major link
|
||||
* @return Whether the link has a large priority
|
||||
*/
|
||||
inline bool havePriority() const {
|
||||
return myState >= 'A' && myState <= 'Z';
|
||||
}
|
||||
|
||||
/** @brief Returns whether this link is blocked by a red (or redyellow) traffic light
|
||||
* @return Whether the link has a red light
|
||||
*/
|
||||
inline bool haveRed() const {
|
||||
return myState == LINKSTATE_TL_RED || myState == LINKSTATE_TL_REDYELLOW;
|
||||
}
|
||||
|
||||
inline bool haveYellow() const {
|
||||
return myState == LINKSTATE_TL_YELLOW_MINOR || myState == LINKSTATE_TL_YELLOW_MAJOR;
|
||||
}
|
||||
|
||||
inline bool haveGreen() const {
|
||||
return myState == LINKSTATE_TL_GREEN_MAJOR || myState == LINKSTATE_TL_GREEN_MINOR;
|
||||
}
|
||||
|
||||
inline bool isTLSControlled() const {
|
||||
return myLogic != 0;
|
||||
}
|
||||
|
||||
/** @brief Returns the length of this link
|
||||
*
|
||||
* @return The length of this link
|
||||
*/
|
||||
double getLength() const {
|
||||
return myLength;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the distance on the approaching lane from which an
|
||||
* approaching vehicle is able to see all relevant foes and
|
||||
* may accelerate if the link is minor and no foe is approaching.
|
||||
*
|
||||
* @return The foe-visibility-distance
|
||||
*/
|
||||
double getFoeVisibilityDistance() const {
|
||||
return myFoeVisibilityDistance;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns whether this link belongs to a junction where more than one edge is incoming
|
||||
*
|
||||
* @return Whether any foe links exist
|
||||
*/
|
||||
bool hasFoes() const {
|
||||
return myHasFoes;
|
||||
}
|
||||
|
||||
// @brief return whether the vehicle may continute past this link to wait within the intersection
|
||||
bool isCont() const;
|
||||
|
||||
|
||||
/// @brief whether the junction after this link must be kept clear
|
||||
bool keepClear() const {
|
||||
return myKeepClear;
|
||||
}
|
||||
|
||||
/// @brief whether this is a link past an internal junction which currently has priority
|
||||
bool lastWasContMajor() const;
|
||||
|
||||
/// @brief whether this is a link past an internal junction which currently has green major
|
||||
bool lastWasContMajorGreen() const;
|
||||
|
||||
/** @brief Returns the cumulative length of all internal lanes after this link
|
||||
* @return sum of the lengths of all internal lanes following this link
|
||||
*/
|
||||
double getInternalLengthsAfter() const;
|
||||
|
||||
/** @brief Returns the cumulative length of all internal lanes before this link
|
||||
* @return sum of the lengths of all internal lanes before this link
|
||||
*/
|
||||
double getInternalLengthsBefore() const;
|
||||
|
||||
/** @brief Returns the sum of the lengths along internal lanes following this link
|
||||
* to the crossing with the given foe lane, if the lane is no foe
|
||||
* lane to any of the internal lanes, INVALID_DOUBLE is returned.
|
||||
* @see getLengthBeforeCrossing()
|
||||
*/
|
||||
double getLengthsBeforeCrossing(const MSLane* foeLane) const;
|
||||
|
||||
|
||||
/** @brief Returns the internal length from the beginning of the link's internal lane before
|
||||
* to the crossing with the given foe lane if applicable, if the lane is no foe
|
||||
* lane to the link, INVALID_DOUBLE is returned.
|
||||
* @see getLengthsBeforeCrossing()
|
||||
*/
|
||||
double getLengthBeforeCrossing(const MSLane* foeLane) const;
|
||||
|
||||
|
||||
/** @brief Returns the following inner lane
|
||||
*
|
||||
* @return The inner lane to use to cross the junction
|
||||
*/
|
||||
MSLane* getViaLane() const;
|
||||
|
||||
/** @brief Returns all potential link leaders (vehicles on foeLanes)
|
||||
* Valid during the planMove() phase
|
||||
* @param[in] ego The ego vehicle that is looking for leaders
|
||||
* @param[in] dist The distance of the vehicle who is asking about the leader to this link
|
||||
* @param[out] blocking Return blocking pedestrians if a vector is given
|
||||
* @param[in] isShadowLink whether this link is a shadowLink for ego
|
||||
* @return The all vehicles on foeLanes and their (virtual) distances to the asking vehicle
|
||||
*/
|
||||
LinkLeaders getLeaderInfo(const MSVehicle* ego, double dist, std::vector<const MSPerson*>* collectBlockers = 0, bool isShadowLink = false) const;
|
||||
|
||||
/// @brief check for persons on walkingarea in the path of ego vehicle
|
||||
void checkWalkingAreaFoe(const MSVehicle* ego, const MSLane* foeLane, std::vector<const MSPerson*>* collectBlockers, LinkLeaders& result) const;
|
||||
|
||||
/// @brief return the speed at which ego vehicle must approach the zipper link
|
||||
double getZipperSpeed(const MSVehicle* ego, const double dist, double vSafe,
|
||||
SUMOTime arrivalTime,
|
||||
BlockingFoes* collectFoes) const;
|
||||
|
||||
/// @brief return the via lane if it exists and the lane otherwise
|
||||
MSLane* getViaLaneOrLane() const;
|
||||
|
||||
/// @brief return the internalLaneBefore if it exists and the laneBefore otherwise
|
||||
const MSLane* getLaneBefore() const;
|
||||
|
||||
/// @brief return myInternalLaneBefore (always 0 when compiled without internal lanes)
|
||||
const MSLane* getInternalLaneBefore() const;
|
||||
|
||||
/// @brief return the expected time at which the given vehicle will clear the link
|
||||
SUMOTime getLeaveTime(const SUMOTime arrivalTime, const double arrivalSpeed, const double leaveSpeed, const double vehicleLength) const;
|
||||
|
||||
/// @brief write information about all approaching vehicles to the given output device
|
||||
void writeApproaching(OutputDevice& od, const std::string fromLaneID) const;
|
||||
|
||||
/// @brief return the link that is parallel to this lane or 0
|
||||
MSLink* getParallelLink(int direction) const;
|
||||
|
||||
/// @brief return whether the fromLane of this link is an internal lane
|
||||
bool fromInternalLane() const;
|
||||
|
||||
/// @brief return whether the toLane of this link is an internal lane and fromLane is a normal lane
|
||||
bool isEntryLink() const;
|
||||
|
||||
/// @brief return whether this link enters the conflict area (not a continuation link)
|
||||
bool isConflictEntryLink() const;
|
||||
|
||||
/// @brief return whether the fromLane of this link is an internal lane and toLane is a normal lane
|
||||
bool isExitLink() const;
|
||||
|
||||
/// @brief return whether the fromLane of this link is an internal lane and its incoming lane is also an internal lane
|
||||
bool isExitLinkAfterInternalJunction() const;
|
||||
|
||||
/// @brief returns the corresponding exit link for entryLinks to a junction.
|
||||
MSLink* getCorrespondingExitLink() const;
|
||||
|
||||
/// @brief return whether the fromLane and the toLane of this link are internal lanes
|
||||
bool isInternalJunctionLink() const;
|
||||
|
||||
/** @brief Returns the time penalty for passing a tls-controlled link (meso) */
|
||||
SUMOTime getMesoTLSPenalty() const {
|
||||
return myMesoTLSPenalty;
|
||||
}
|
||||
|
||||
/** @brief Returns the average proportion of green time to cycle time */
|
||||
double getGreenFraction() const {
|
||||
return myGreenFraction;
|
||||
}
|
||||
|
||||
/** @brief Sets the time penalty for passing a tls-controlled link (meso) */
|
||||
void setMesoTLSPenalty(const SUMOTime penalty) {
|
||||
myMesoTLSPenalty = penalty;
|
||||
}
|
||||
|
||||
/** @brief Sets the green fraction for passing a tls-controlled link (meso) */
|
||||
void setGreenFraction(const double fraction) {
|
||||
myGreenFraction = fraction;
|
||||
}
|
||||
|
||||
const std::vector<const MSLane*>& getFoeLanes() const {
|
||||
return myFoeLanes;
|
||||
}
|
||||
|
||||
const std::vector<std::pair<double, double> >& getLengthsBehindCrossing() const {
|
||||
return myLengthsBehindCrossing;
|
||||
}
|
||||
|
||||
const std::vector<MSLink*>& getFoeLinks() const {
|
||||
return myFoeLinks;
|
||||
}
|
||||
|
||||
/// @brief initialize parallel links (to be called after all links are loaded)
|
||||
void initParallelLinks();
|
||||
|
||||
/// @brief return lateral shift that must be applied when passing this link
|
||||
double getLateralShift() {
|
||||
return myLateralShift;
|
||||
}
|
||||
|
||||
/// @brief get string description for this link
|
||||
std::string getDescription() const;
|
||||
|
||||
private:
|
||||
/// @brief return whether the given vehicles may NOT merge safely
|
||||
static inline bool unsafeMergeSpeeds(double leaderSpeed, double followerSpeed, double leaderDecel, double followerDecel) {
|
||||
// XXX mismatch between continuous an discrete deceleration
|
||||
return (leaderSpeed * leaderSpeed / leaderDecel) <= (followerSpeed * followerSpeed / followerDecel);
|
||||
}
|
||||
|
||||
/// @brief whether follower could stay behind leader (possibly by braking)
|
||||
static bool couldBrakeForLeader(double followDist, double leaderDist, const MSVehicle* follow, const MSVehicle* leader);
|
||||
|
||||
MSLink* computeParallelLink(int direction);
|
||||
|
||||
bool blockedByFoe(const SUMOVehicle* veh, const ApproachingVehicleInformation& avi,
|
||||
SUMOTime arrivalTime, SUMOTime leaveTime, double arrivalSpeed, double leaveSpeed,
|
||||
bool sameTargetLane, double impatience, double decel, SUMOTime waitingTime,
|
||||
const SUMOVehicle* ego) const;
|
||||
|
||||
/// @brief figure out whether the cont status remains in effect when switching off the tls
|
||||
bool checkContOff() const;
|
||||
|
||||
/// @brief check if the lane intersects with a foe cont-lane
|
||||
bool contIntersect(const MSLane* lane, const MSLane* foe);
|
||||
|
||||
private:
|
||||
/// @brief The lane behind the junction approached by this link
|
||||
MSLane* myLane;
|
||||
|
||||
/// @brief The lane approaching this link
|
||||
MSLane* myLaneBefore;
|
||||
|
||||
ApproachInfos myApproachingVehicles;
|
||||
std::set<MSLink*> myBlockedFoeLinks;
|
||||
|
||||
/// @brief The position within this respond
|
||||
int myIndex;
|
||||
|
||||
/// @brief the traffic light index
|
||||
const int myTLIndex;
|
||||
|
||||
/// @brief the controlling logic or 0
|
||||
const MSTrafficLightLogic* myLogic;
|
||||
|
||||
/// @brief The state of the link
|
||||
LinkState myState;
|
||||
/// @brief The state of the link when switching of traffic light control
|
||||
const LinkState myOffState;
|
||||
|
||||
/// @brief The time of the last state change
|
||||
SUMOTime myLastStateChange;
|
||||
|
||||
/// @brief An abstract (hopefully human readable) definition of the link's direction
|
||||
LinkDirection myDirection;
|
||||
|
||||
/// @brief The length of the link
|
||||
/// @note This is not equal to the result of getInternalLengthsAfter for links with more than one internal lane.
|
||||
double myLength;
|
||||
|
||||
/// @brief distance from which an approaching vehicle is able to
|
||||
/// see all relevant foes and may accelerate if the link is minor
|
||||
/// and no foe is approaching. Defaults to 4.5m.
|
||||
double myFoeVisibilityDistance;
|
||||
|
||||
/// @brief Whether any foe links exist
|
||||
bool myHasFoes;
|
||||
|
||||
// @brief whether vehicles may continue past this link to wait within the intersection
|
||||
bool myAmCont;
|
||||
// @brief whether vehicles may continue past this link to wait within the intersection after switching of the traffic light at this intersection
|
||||
bool myAmContOff;
|
||||
|
||||
// @brief whether vehicles must keep the intersection clear if there is a downstream jam
|
||||
bool myKeepClear;
|
||||
|
||||
/// @brief The following junction-internal lane if used
|
||||
MSLane* const myInternalLane;
|
||||
|
||||
/* @brief The preceding junction-internal lane, only used at
|
||||
* - exit links (from internal lane to normal lane)
|
||||
* - internal junction links (from internal lane to internal lane)
|
||||
*/
|
||||
const MSLane* myInternalLaneBefore;
|
||||
|
||||
/// @brief penalty time at tls for mesoscopic simulation
|
||||
SUMOTime myMesoTLSPenalty;
|
||||
/// @brief green fraction at tls for mesoscopic simulation
|
||||
double myGreenFraction;
|
||||
|
||||
/// @brief lateral shift to be applied when passing this link
|
||||
double myLateralShift;
|
||||
|
||||
/* @brief lengths after the crossing point with foeLane
|
||||
* (lengthOnThis, lengthOnFoe)
|
||||
* (index corresponds to myFoeLanes)
|
||||
* empty vector for entry links
|
||||
* */
|
||||
std::vector<std::pair<double, double> > myLengthsBehindCrossing;
|
||||
|
||||
// TODO: documentation
|
||||
std::vector<MSLink*> myFoeLinks;
|
||||
std::vector<const MSLane*> myFoeLanes;
|
||||
|
||||
/// @brief walkingArea that must be checked when entering the intersection
|
||||
const MSLane* myWalkingAreaFoe;
|
||||
/// @brief walkingArea that must be checked when leaving the intersection
|
||||
const MSLane* myWalkingAreaFoeExit;
|
||||
|
||||
/// @brief whether on of myFoeLanes is a crossing
|
||||
bool myHavePedestrianCrossingFoe;
|
||||
|
||||
/* @brief Links with the same origin lane and the same destination edge that may
|
||||
be in conflict for sublane simulation */
|
||||
std::vector<MSLink*> mySublaneFoeLinks;
|
||||
/* @brief Links with the same origin lane and different destination edge that may
|
||||
be in conflict for sublane simulation */
|
||||
std::vector<MSLink*> mySublaneFoeLinks2;
|
||||
|
||||
/* @brief Internal Lanes with the same origin lane and the same destination edge that may
|
||||
be in conflict for sublane simulation */
|
||||
std::vector<MSLane*> mySublaneFoeLanes;
|
||||
|
||||
static const SUMOTime myLookaheadTime;
|
||||
static const SUMOTime myLookaheadTimeZipper;
|
||||
|
||||
MSLink* myParallelRight;
|
||||
MSLink* myParallelLeft;
|
||||
|
||||
/// @brief the junction to which this link belongs
|
||||
MSJunction* myJunction;
|
||||
|
||||
/// invalidated copy constructor
|
||||
MSLink(const MSLink& s);
|
||||
|
||||
/// invalidated assignment operator
|
||||
MSLink& operator=(const MSLink& s);
|
||||
|
||||
};
|
|
@ -1,63 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2002-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSLinkCont.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A vector of links
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include "MSLink.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class MSEdge;
|
||||
class MSLane;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSLinkCont
|
||||
* A simple contanier of definitions about how a lane may be left
|
||||
*/
|
||||
typedef std::vector<MSLink*> MSLinkCont;
|
||||
|
||||
|
||||
/**
|
||||
* @class MSLinkContHelper
|
||||
* Some helping functions for dealing with links.
|
||||
*/
|
||||
class MSLinkContHelper {
|
||||
public:
|
||||
/** @brief Returns the internal lane that must be passed in order to get to the desired edge
|
||||
Returns 0 if no such edge exists */
|
||||
static const MSEdge* getInternalFollowingEdge(const MSLane* fromLane,
|
||||
const MSEdge* followerAfterInternal);
|
||||
|
||||
static const MSLane* getInternalFollowingLane(const MSLane* fromLane,
|
||||
const MSLane* followerAfterInternal);
|
||||
|
||||
/** @brief Returns the link connecting both lanes
|
||||
Both lanes have to be non-internal; 0 may be returned if no connection
|
||||
exists */
|
||||
static MSLink* getConnectingLink(const MSLane& from, const MSLane& to);
|
||||
};
|
|
@ -1,275 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2003-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSMoveReminder.h
|
||||
/// @author Christian Roessel
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @author Jakob Erdmann
|
||||
/// @date 2003-05-21
|
||||
///
|
||||
// Something on a lane to be noticed about vehicle movement
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <iostream>
|
||||
#include <map>
|
||||
#include <utils/common/SUMOTime.h>
|
||||
#include <utils/common/StdDefs.h>
|
||||
#ifdef HAVE_FOX
|
||||
#include <fx.h>
|
||||
#endif
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class SUMOTrafficObject;
|
||||
class MSLane;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSMoveReminder
|
||||
* @brief Something on a lane to be noticed about vehicle movement
|
||||
*
|
||||
* Base class of all move-reminders. During move, the vehicles call
|
||||
* notifyMove() for all reminders on their current lane (all lanes
|
||||
* they pass during one step). If a vehicle enters the lane the reminder is
|
||||
* positioned at during insertion or lanechange notifyEnter() is
|
||||
* called. If a vehicle leaves the reminder lane it calls notifyLeave().
|
||||
*
|
||||
* The reminder knows whom to tell about move, insertion and lanechange. The
|
||||
* vehicles will remove the reminder that is not notifyMove() from
|
||||
* their reminder container.
|
||||
*
|
||||
* @see MSLane::addMoveReminder
|
||||
* @see MSLane::getMoveReminder
|
||||
* @note: cannot inherit from Named because it would couse double inheritance
|
||||
*/
|
||||
class MSMoveReminder {
|
||||
public:
|
||||
/** @brief Constructor.
|
||||
*
|
||||
* @param[in] lane Lane on which the reminder will work.
|
||||
* @param[in] doAdd whether to add the reminder to the lane
|
||||
*/
|
||||
MSMoveReminder(const std::string& description, MSLane* const lane = 0, const bool doAdd = true);
|
||||
|
||||
|
||||
/** @brief Destructor
|
||||
*/
|
||||
virtual ~MSMoveReminder() {}
|
||||
|
||||
|
||||
/** @brief Returns the lane the reminder works on.
|
||||
*
|
||||
* @return The lane the reminder is anchored on.
|
||||
*/
|
||||
const MSLane* getLane() const {
|
||||
return myLane;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Definition of a vehicle state
|
||||
enum Notification {
|
||||
/// @brief The vehicle has departed (was inserted into the network)
|
||||
NOTIFICATION_DEPARTED,
|
||||
/// @brief The vehicle arrived at a junction
|
||||
NOTIFICATION_JUNCTION,
|
||||
/// @brief The vehicle changes the segment (meso only)
|
||||
NOTIFICATION_SEGMENT,
|
||||
/// @brief The vehicle changes lanes (micro only)
|
||||
NOTIFICATION_LANE_CHANGE,
|
||||
/* All notifications below must result in the vehicle not being on the net
|
||||
* (onLeaveLane sets amOnNet=false if reason>=NOTIFICATION_TELEPORT) */
|
||||
/// @brief The vehicle is being teleported
|
||||
NOTIFICATION_TELEPORT,
|
||||
/// @brief The vehicle starts or ends parking
|
||||
NOTIFICATION_PARKING,
|
||||
/// @brief The vehicle needs another parking area
|
||||
NOTIFICATION_PARKING_REROUTE,
|
||||
/// @brief The vehicle arrived at its destination (is deleted)
|
||||
NOTIFICATION_ARRIVED, // arrived and everything after is treated as permanent deletion from the net
|
||||
/// @brief The vehicle was teleported out of the net
|
||||
NOTIFICATION_TELEPORT_ARRIVED,
|
||||
/// @brief The vehicle got removed by a calibrator
|
||||
NOTIFICATION_VAPORIZED_CALIBRATOR,
|
||||
/// @brief The vehicle got removed by a collision
|
||||
NOTIFICATION_VAPORIZED_COLLISION,
|
||||
/// @brief The vehicle got removed via TraCI
|
||||
NOTIFICATION_VAPORIZED_TRACI,
|
||||
/// @brief The vehicle got removed via the GUI
|
||||
NOTIFICATION_VAPORIZED_GUI,
|
||||
/// @brief The vehicle got vaporized with a vaporizer
|
||||
NOTIFICATION_VAPORIZED_VAPORIZER
|
||||
};
|
||||
|
||||
|
||||
/// @name Interface methods, to be derived by subclasses
|
||||
/// @{
|
||||
|
||||
/** @brief Checks whether the reminder is activated by a vehicle entering the lane
|
||||
*
|
||||
* Lane change means in this case that the vehicle changes to the lane
|
||||
* the reminder is placed at.
|
||||
*
|
||||
* @param[in] veh The entering vehicle.
|
||||
* @param[in] reason how the vehicle enters the lane
|
||||
* @return True if vehicle enters the reminder.
|
||||
* @see Notification
|
||||
*/
|
||||
virtual bool notifyEnter(SUMOTrafficObject& veh, Notification reason, const MSLane* enteredLane) {
|
||||
UNUSED_PARAMETER(reason);
|
||||
UNUSED_PARAMETER(&veh);
|
||||
UNUSED_PARAMETER(&enteredLane);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Checks whether the reminder still has to be notified about the vehicle moves
|
||||
*
|
||||
* Indicator if the reminders is still active for the passed
|
||||
* vehicle/parameters. If false, the vehicle will erase this reminder
|
||||
* from it's reminder-container.
|
||||
*
|
||||
* @param[in] veh Vehicle that asks this reminder.
|
||||
* @param[in] oldPos Position before move.
|
||||
* @param[in] newPos Position after move with newSpeed.
|
||||
* @param[in] newSpeed Moving speed.
|
||||
*
|
||||
* @return True if vehicle hasn't passed the reminder completely.
|
||||
*/
|
||||
virtual bool notifyMove(SUMOTrafficObject& veh,
|
||||
double oldPos,
|
||||
double newPos,
|
||||
double newSpeed) {
|
||||
UNUSED_PARAMETER(oldPos);
|
||||
UNUSED_PARAMETER(newPos);
|
||||
UNUSED_PARAMETER(newSpeed);
|
||||
UNUSED_PARAMETER(&veh);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Computes idling emission values and adds them to the emission sums
|
||||
*
|
||||
* Idling implied by zero velocity, acceleration and slope
|
||||
*
|
||||
* @param[in] veh The vehicle
|
||||
*
|
||||
* @see MSMoveReminder::notifyMove
|
||||
* @see PollutantsInterface
|
||||
*/
|
||||
virtual bool notifyIdle(SUMOTrafficObject& veh) {
|
||||
UNUSED_PARAMETER(&veh);
|
||||
return true;
|
||||
}
|
||||
|
||||
/** @brief Called if the vehicle leaves the reminder's lane
|
||||
*
|
||||
* Informs if vehicle leaves reminder lane (due to lane change, removal
|
||||
* from the network, or leaving to the next lane).
|
||||
* The default is to do nothing.
|
||||
*
|
||||
* @param[in] veh The leaving vehicle.
|
||||
* @param[in] lastPos Position on the lane when leaving.
|
||||
* @param[in] reason how the vehicle leaves the lane
|
||||
* @see Notification
|
||||
*
|
||||
* @return True if the reminder wants to receive further info.
|
||||
*/
|
||||
virtual bool notifyLeave(SUMOTrafficObject& veh, double lastPos, Notification reason, const MSLane* enteredLane = 0) {
|
||||
UNUSED_PARAMETER(&veh);
|
||||
UNUSED_PARAMETER(lastPos);
|
||||
UNUSED_PARAMETER(reason);
|
||||
UNUSED_PARAMETER(enteredLane);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// TODO: Documentation
|
||||
void updateDetector(SUMOTrafficObject& veh, double entryPos, double leavePos,
|
||||
SUMOTime entryTime, SUMOTime currentTime, SUMOTime leaveTime,
|
||||
bool cleanUp);
|
||||
|
||||
/// @}
|
||||
|
||||
/** @brief Internal notification about the vehicle moves.
|
||||
* @note meso uses this though it never calls notifyMove()
|
||||
*
|
||||
* Indicator if the reminders is still active for the passed
|
||||
* vehicle/parameters. If false, the vehicle will erase this reminder
|
||||
* from it's reminder-container.
|
||||
*
|
||||
* @param[in] veh Vehicle that asks this reminder.
|
||||
* @param[in] frontOnLane time the front of the vehicle spent on the lane.
|
||||
* @param[in] timeOnLane time some part of the vehicle spent on the lane.
|
||||
* @param[in] meanSpeedFrontOnLane Average speed for the time that the front is on the lane.
|
||||
* @param[in] meanSpeedVehicleOnLane Average speed for the time that the vehicle is on the lane (with front or back).
|
||||
* @param[in] travelledDistanceFrontOnLane distance travelled while overlapping with the lane.
|
||||
* @param[in] travelledDistanceVehicleOnLane distance travelled while front was on the lane.
|
||||
* @param[in] meanLengthOnLane the average length of the vehicle's part on the lane during the last step (==complete length in meso case)
|
||||
*/
|
||||
virtual void notifyMoveInternal(const SUMOTrafficObject& veh,
|
||||
const double frontOnLane,
|
||||
const double timeOnLane,
|
||||
const double meanSpeedFrontOnLane,
|
||||
const double meanSpeedVehicleOnLane,
|
||||
const double travelledDistanceFrontOnLane,
|
||||
const double travelledDistanceVehicleOnLane,
|
||||
const double meanLengthOnLane) {
|
||||
UNUSED_PARAMETER(meanLengthOnLane);
|
||||
UNUSED_PARAMETER(travelledDistanceFrontOnLane);
|
||||
UNUSED_PARAMETER(travelledDistanceVehicleOnLane);
|
||||
UNUSED_PARAMETER(meanSpeedVehicleOnLane);
|
||||
UNUSED_PARAMETER(meanSpeedFrontOnLane);
|
||||
UNUSED_PARAMETER(frontOnLane);
|
||||
UNUSED_PARAMETER(timeOnLane);
|
||||
UNUSED_PARAMETER(&veh);
|
||||
}
|
||||
|
||||
void setDescription(const std::string& description) {
|
||||
myDescription = description;
|
||||
}
|
||||
|
||||
const std::string& getDescription() const {
|
||||
return myDescription;
|
||||
}
|
||||
|
||||
protected:
|
||||
void removeFromVehicleUpdateValues(SUMOTrafficObject& veh);
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief Lane on which the reminder works
|
||||
MSLane* const myLane;
|
||||
/// @brief a description of this moveReminder
|
||||
std::string myDescription;
|
||||
|
||||
#ifdef HAVE_FOX
|
||||
/// @brief the mutex for notifications
|
||||
mutable FXMutex myNotificationMutex;
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::map<SUMOTrafficObject*, std::pair<SUMOTime, double> > myLastVehicleUpdateValues;
|
||||
|
||||
|
||||
private:
|
||||
MSMoveReminder& operator=(const MSMoveReminder&); // just to avoid a compiler warning
|
||||
|
||||
};
|
|
@ -1,891 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file MSNet.h
|
||||
/// @author Christian Roessel
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Thimor Bohn
|
||||
/// @author Eric Nicolay
|
||||
/// @author Clemens Honomichl
|
||||
/// @author Michael Behrisch
|
||||
/// @author Leonhard Luecken
|
||||
/// @date Mon, 12 Mar 2001
|
||||
///
|
||||
// The simulated network and simulation performer
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <typeinfo>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <iomanip>
|
||||
#include <memory>
|
||||
#include <utils/common/SUMOTime.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/common/NamedObjectCont.h>
|
||||
#include <utils/common/NamedRTree.h>
|
||||
#include <utils/router/SUMOAbstractRouter.h>
|
||||
#include "MSJunction.h"
|
||||
|
||||
#ifdef HAVE_FOX
|
||||
#include <utils/foxtools/FXConditionalLock.h>
|
||||
#endif
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class MSEdge;
|
||||
class MSEdgeControl;
|
||||
class MSEventControl;
|
||||
class MSVehicleControl;
|
||||
class MSJunctionControl;
|
||||
class MSInsertionControl;
|
||||
class SUMORouteLoaderControl;
|
||||
class MSTransportableControl;
|
||||
class MSVehicle;
|
||||
class MSRoute;
|
||||
class MSLane;
|
||||
class MSTLLogicControl;
|
||||
class MSTrafficLightLogic;
|
||||
class MSDetectorControl;
|
||||
class ShapeContainer;
|
||||
class MSDynamicShapeUpdater;
|
||||
class PolygonDynamics;
|
||||
class MSEdgeWeightsStorage;
|
||||
class SUMOVehicle;
|
||||
class MSTractionSubstation;
|
||||
class MSStoppingPlace;
|
||||
template<class E, class L, class N, class V>
|
||||
class IntermodalRouter;
|
||||
template<class E, class L, class N, class V>
|
||||
class PedestrianRouter;
|
||||
class OptionsCont;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class MSNet
|
||||
* @brief The simulated network and simulation perfomer
|
||||
*/
|
||||
class MSNet {
|
||||
public:
|
||||
/** @enum SimulationState
|
||||
* @brief Possible states of a simulation - running or stopped with different reasons
|
||||
*/
|
||||
enum SimulationState {
|
||||
/// @brief The simulation is loading
|
||||
SIMSTATE_LOADING,
|
||||
/// @brief The simulation is running
|
||||
SIMSTATE_RUNNING,
|
||||
/// @brief The final simulation step has been performed
|
||||
SIMSTATE_END_STEP_REACHED,
|
||||
/// @brief The simulation does not contain further vehicles
|
||||
SIMSTATE_NO_FURTHER_VEHICLES,
|
||||
/// @brief The connection to a client was closed by the client
|
||||
SIMSTATE_CONNECTION_CLOSED,
|
||||
/// @brief An error occurred during the simulation step
|
||||
SIMSTATE_ERROR_IN_SIM,
|
||||
/// @brief An external interrupt occured
|
||||
SIMSTATE_INTERRUPTED,
|
||||
/// @brief The simulation had too many teleports
|
||||
SIMSTATE_TOO_MANY_TELEPORTS
|
||||
};
|
||||
|
||||
typedef PedestrianRouter<MSEdge, MSLane, MSJunction, MSVehicle> MSPedestrianRouter;
|
||||
typedef IntermodalRouter<MSEdge, MSLane, MSJunction, SUMOVehicle> MSIntermodalRouter;
|
||||
|
||||
|
||||
public:
|
||||
/** @brief Returns the pointer to the unique instance of MSNet (singleton).
|
||||
* @return Pointer to the unique MSNet-instance
|
||||
* @exception ProcessError If a network was not yet constructed
|
||||
*/
|
||||
static MSNet* getInstance();
|
||||
|
||||
/**
|
||||
* @brief Returns whether this is a GUI Net
|
||||
*/
|
||||
virtual bool isGUINet() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @brief Place for static initializations of simulation components (called after successful net build)
|
||||
static void initStatic();
|
||||
|
||||
/// @brief Place for static initializations of simulation components (called after successful net build)
|
||||
static void cleanupStatic();
|
||||
|
||||
|
||||
/** @brief Returns whether the network was already constructed
|
||||
* @return whether the network was already constructed
|
||||
*/
|
||||
static bool hasInstance() {
|
||||
return myInstance != nullptr;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
*
|
||||
* This constructor builds a net of which only some basic structures are initialised.
|
||||
* It prepares the network for being filled while loading.
|
||||
* As soon as all edge/junction/traffic lights and other containers are build, they
|
||||
* must be initialised using "closeBuilding".
|
||||
* @param[in] vc The vehicle control to use
|
||||
* @param[in] beginOfTimestepEvents The event control to use for simulation step begin events
|
||||
* @param[in] endOfTimestepEvents The event control to use for simulation step end events
|
||||
* @param[in] insertionEvents The event control to use for insertion events
|
||||
* @param[in] shapeCont The shape container to use
|
||||
* @exception ProcessError If a network was already constructed
|
||||
* @see closeBuilding
|
||||
*/
|
||||
MSNet(MSVehicleControl* vc, MSEventControl* beginOfTimestepEvents,
|
||||
MSEventControl* endOfTimestepEvents,
|
||||
MSEventControl* insertionEvents,
|
||||
ShapeContainer* shapeCont = 0);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~MSNet();
|
||||
|
||||
|
||||
/** @brief Closes the network's building process
|
||||
*
|
||||
* Assigns the structures built while loading to this network.
|
||||
* @param[in] oc The options to use
|
||||
* @param[in] edges The control of edges which belong to this network
|
||||
* @param[in] junctions The control of junctions which belong to this network
|
||||
* @param[in] routeLoaders The route loaders used
|
||||
* @param[in] tlc The control of traffic lights which belong to this network
|
||||
* @param[in] stateDumpTimes List of time steps at which state shall be written
|
||||
* @param[in] stateDumpFiles Filenames for states
|
||||
* @param[in] hasInternalLinks Whether the network actually contains internal links
|
||||
* @param[in] version The network version
|
||||
* @todo Try to move all this to the constructor?
|
||||
*/
|
||||
void closeBuilding(const OptionsCont& oc, MSEdgeControl* edges, MSJunctionControl* junctions,
|
||||
SUMORouteLoaderControl* routeLoaders, MSTLLogicControl* tlc,
|
||||
std::vector<SUMOTime> stateDumpTimes, std::vector<std::string> stateDumpFiles,
|
||||
bool hasInternalLinks, bool hasNeighs,
|
||||
double version);
|
||||
|
||||
|
||||
/** @brief Returns whether the network has specific vehicle class permissions
|
||||
* @return whether permissions are present
|
||||
*/
|
||||
bool hasPermissions() const {
|
||||
return myHavePermissions;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Labels the network to contain vehicle class permissions
|
||||
void setPermissionsFound() {
|
||||
myHavePermissions = true;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Adds a restriction for an edge type
|
||||
* @param[in] id The id of the type
|
||||
* @param[in] svc The vehicle class the restriction refers to
|
||||
* @param[in] speed The restricted speed
|
||||
*/
|
||||
void addRestriction(const std::string& id, const SUMOVehicleClass svc, const double speed);
|
||||
|
||||
|
||||
/** @brief Returns the restrictions for an edge type
|
||||
* If no restrictions are present, 0 is returned.
|
||||
* @param[in] id The id of the type
|
||||
* @return The mapping of vehicle classes to maximum speeds
|
||||
*/
|
||||
const std::map<SUMOVehicleClass, double>* getRestrictions(const std::string& id) const;
|
||||
|
||||
|
||||
/** @brief Clears all dictionaries
|
||||
* @todo Try to move all this to the destructor
|
||||
*/
|
||||
static void clearAll();
|
||||
|
||||
|
||||
/** @brief Simulates from timestep start to stop
|
||||
* @param[in] start The begin time step of the simulation
|
||||
* @param[in] stop The end time step of the simulation
|
||||
* @return Returns always 0
|
||||
* @todo Recheck return value
|
||||
* @todo What exceptions may occure?
|
||||
*/
|
||||
SimulationState simulate(SUMOTime start, SUMOTime stop);
|
||||
|
||||
|
||||
/** @brief Performs a single simulation step
|
||||
* @todo Which exceptions may occur?
|
||||
*/
|
||||
void simulationStep();
|
||||
|
||||
|
||||
/** @brief loads routes for the next few steps */
|
||||
void loadRoutes();
|
||||
|
||||
|
||||
/** @brief Writes performance output and running vehicle stats
|
||||
*
|
||||
* @param[in] start The step the simulation was started with
|
||||
*/
|
||||
const std::string generateStatistics(SUMOTime start);
|
||||
|
||||
/// @brief write statistic output to (xml) file
|
||||
void writeStatistics() const;
|
||||
|
||||
/** @brief Closes the simulation (all files, connections, etc.)
|
||||
*
|
||||
* Writes also performance output
|
||||
*
|
||||
* @param[in] start The step the simulation was started with
|
||||
*/
|
||||
void closeSimulation(SUMOTime start, const std::string& reason = "");
|
||||
|
||||
|
||||
/** @brief This method returns the current simulation state. It should not modify status.
|
||||
* @param[in] stopTime The time the simulation shall stop at
|
||||
* @return The current simulation state
|
||||
* @see SimulationState
|
||||
*/
|
||||
SimulationState simulationState(SUMOTime stopTime) const;
|
||||
|
||||
|
||||
/** @brief Called after a simulation step, this method adapts the current simulation state if necessary
|
||||
* @param[in] state The current simulation state
|
||||
* @return The new simulation state
|
||||
* @see SimulationState
|
||||
*/
|
||||
SimulationState adaptToState(const SimulationState state) const;
|
||||
|
||||
|
||||
/** @brief Returns the message to show if a certain state occurs
|
||||
* @return Readable description of the state
|
||||
*/
|
||||
static std::string getStateMessage(SimulationState state);
|
||||
|
||||
|
||||
/** @brief Returns the current simulation step
|
||||
* @return the current simulation step
|
||||
*/
|
||||
inline SUMOTime getCurrentTimeStep() const {
|
||||
return myStep;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Sets the current simulation step (used by state loading)
|
||||
* @param step the current simulation step
|
||||
*/
|
||||
inline void setCurrentTimeStep(const SUMOTime step) {
|
||||
myStep = step;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Resets events when quick-loading state
|
||||
* @param step The new simulation step
|
||||
*/
|
||||
void clearState(const SUMOTime step);
|
||||
|
||||
/** @brief Write netstate, summary and detector output
|
||||
* @todo Which exceptions may occur?
|
||||
*/
|
||||
void writeOutput();
|
||||
|
||||
|
||||
/** @brief Returns whether duration shall be logged
|
||||
* @return Whether duration shall be logged
|
||||
*/
|
||||
bool logSimulationDuration() const;
|
||||
|
||||
|
||||
|
||||
/// @name Output during the simulation
|
||||
//@{
|
||||
|
||||
/** @brief Prints the current step number
|
||||
*
|
||||
* Called on the begin of a simulation step
|
||||
*/
|
||||
void preSimStepOutput() const;
|
||||
|
||||
|
||||
/** @brief Prints the statistics of the step at its end
|
||||
*
|
||||
* Called on the end of a simulation step
|
||||
*/
|
||||
void postSimStepOutput() const;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
/// @name Retrieval of references to substructures
|
||||
/// @{
|
||||
|
||||
/** @brief Returns the vehicle control
|
||||
* @return The vehicle control
|
||||
* @see MSVehicleControl
|
||||
* @see myVehicleControl
|
||||
*/
|
||||
MSVehicleControl& getVehicleControl() {
|
||||
return *myVehicleControl;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the person control
|
||||
*
|
||||
* If the person control does not exist, yet, it is created.
|
||||
*
|
||||
* @return The person control
|
||||
* @see MSPersonControl
|
||||
* @see myPersonControl
|
||||
*/
|
||||
virtual MSTransportableControl& getPersonControl();
|
||||
|
||||
/** @brief Returns whether persons are simulated
|
||||
*/
|
||||
bool hasPersons() const {
|
||||
return myPersonControl != nullptr;
|
||||
}
|
||||
|
||||
/** @brief Returns the container control
|
||||
*
|
||||
* If the container control does not exist, yet, it is created.
|
||||
*
|
||||
* @return The container control
|
||||
* @see MSContainerControl
|
||||
* @see myContainerControl
|
||||
*/
|
||||
virtual MSTransportableControl& getContainerControl();
|
||||
|
||||
/** @brief Returns whether containers are simulated
|
||||
*/
|
||||
bool hasContainers() const {
|
||||
return myContainerControl != nullptr;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the edge control
|
||||
* @return The edge control
|
||||
* @see MSEdgeControl
|
||||
* @see myEdges
|
||||
*/
|
||||
MSEdgeControl& getEdgeControl() {
|
||||
return *myEdges;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the insertion control
|
||||
* @return The insertion control
|
||||
* @see MSInsertionControl
|
||||
* @see myInserter
|
||||
*/
|
||||
MSInsertionControl& getInsertionControl() {
|
||||
return *myInserter;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the detector control
|
||||
* @return The detector control
|
||||
* @see MSDetectorControl
|
||||
* @see myDetectorControl
|
||||
*/
|
||||
MSDetectorControl& getDetectorControl() {
|
||||
return *myDetectorControl;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the tls logics control
|
||||
* @return The tls logics control
|
||||
* @see MSTLLogicControl
|
||||
* @see myLogics
|
||||
*/
|
||||
MSTLLogicControl& getTLSControl() {
|
||||
return *myLogics;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the junctions control
|
||||
* @return The junctions control
|
||||
* @see MSJunctionControl
|
||||
* @see myJunctions
|
||||
*/
|
||||
MSJunctionControl& getJunctionControl() {
|
||||
return *myJunctions;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the event control for events executed at the begin of a time step
|
||||
* @return The control responsible for events that are executed at the begin of a time step
|
||||
* @see MSEventControl
|
||||
* @see myBeginOfTimestepEvents
|
||||
*/
|
||||
MSEventControl* getBeginOfTimestepEvents() {
|
||||
return myBeginOfTimestepEvents;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the event control for events executed at the end of a time step
|
||||
* @return The control responsible for events that are executed at the end of a time step
|
||||
* @see MSEventControl
|
||||
* @see myEndOfTimestepEvents
|
||||
*/
|
||||
MSEventControl* getEndOfTimestepEvents() {
|
||||
return myEndOfTimestepEvents;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the event control for insertion events
|
||||
* @return The control responsible for insertion events
|
||||
* @see MSEventControl
|
||||
* @see myInsertionEvents
|
||||
*/
|
||||
MSEventControl* getInsertionEvents() {
|
||||
return myInsertionEvents;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the shapes container
|
||||
* @return The shapes container
|
||||
* @see ShapeContainer
|
||||
* @see myShapeContainer
|
||||
*/
|
||||
ShapeContainer& getShapeContainer() {
|
||||
return *myShapeContainer;
|
||||
}
|
||||
|
||||
/** @brief Returns the dynamic shapes updater
|
||||
* @see PolygonDynamics
|
||||
*/
|
||||
MSDynamicShapeUpdater* getDynamicShapeUpdater() {
|
||||
return myDynamicShapeUpdater.get();
|
||||
}
|
||||
|
||||
/** @brief Creates and returns a dynamic shapes updater
|
||||
* @see PolygonDynamics
|
||||
*/
|
||||
MSDynamicShapeUpdater* makeDynamicShapeUpdater();
|
||||
|
||||
/** @brief Returns the net's internal edge travel times/efforts container
|
||||
*
|
||||
* If the net does not have such a container, it is built.
|
||||
* @return The net's knowledge about edge weights
|
||||
*/
|
||||
MSEdgeWeightsStorage& getWeightsStorage();
|
||||
/// @}
|
||||
|
||||
/// @name Insertion and retrieval of stopping places
|
||||
/// @{
|
||||
|
||||
/** @brief Adds a stopping place
|
||||
*
|
||||
* If another stop with the same id and category exists, false is returned.
|
||||
* Otherwise, the stop is added to the internal stopping place container.
|
||||
*
|
||||
* This control gets responsible for deletion of the added stop.
|
||||
*
|
||||
* @param[in] stop The stop to add
|
||||
* @return Whether the stop could be added
|
||||
*/
|
||||
bool addStoppingPlace(const SumoXMLTag category, MSStoppingPlace* stop);
|
||||
|
||||
|
||||
/** @brief Adds a traction substation
|
||||
*
|
||||
* If another traction substation with the same id and category exists, false is returned.
|
||||
* Otherwise, the traction substation is added to the internal substations container.
|
||||
*
|
||||
* @param[in] substation The traction substation to add
|
||||
* @return Whether the stop could be added
|
||||
*/
|
||||
bool addTractionSubstation(MSTractionSubstation* substation);
|
||||
|
||||
|
||||
/** @brief Returns the named stopping place of the given category
|
||||
* @param[in] id The id of the stop to return.
|
||||
* @param[in] category The type of stop
|
||||
* @return The named stop, or 0 if no such stop exists
|
||||
*/
|
||||
MSStoppingPlace* getStoppingPlace(const std::string& id, const SumoXMLTag category) const;
|
||||
|
||||
/** @brief Returns the stop of the given category close to the given position
|
||||
* @param[in] lane the lane of the stop to return.
|
||||
* @param[in] pos the position of the stop to return.
|
||||
* @param[in] category The type of stop
|
||||
* @return The stop id on the location, or "" if no such stop exists
|
||||
*/
|
||||
std::string getStoppingPlaceID(const MSLane* lane, const double pos, const SumoXMLTag category) const;
|
||||
/// @}
|
||||
|
||||
const NamedObjectCont<MSStoppingPlace*>& getStoppingPlaces(SumoXMLTag category) const;
|
||||
|
||||
/// @brief write charging station output
|
||||
void writeChargingStationOutput() const;
|
||||
|
||||
/// @brief write rail signal block output
|
||||
void writeRailSignalBlocks() const;
|
||||
|
||||
/// @brief creates a wrapper for the given logic (see GUINet)
|
||||
virtual void createTLWrapper(MSTrafficLightLogic*) {};
|
||||
|
||||
/// @brief write the output generated by an overhead wire segment
|
||||
void writeOverheadWireSegmentOutput() const;
|
||||
|
||||
/// @brief write electrical substation output
|
||||
void writeSubstationOutput() const;
|
||||
|
||||
/// @brief return wheter the given logic (or rather it's wrapper) is selected in the GUI
|
||||
virtual bool isSelected(const MSTrafficLightLogic*) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
/// @name Notification about vehicle state changes
|
||||
/// @{
|
||||
|
||||
/// @brief Definition of a vehicle state
|
||||
enum VehicleState {
|
||||
/// @brief The vehicle was built, but has not yet departed
|
||||
VEHICLE_STATE_BUILT,
|
||||
/// @brief The vehicle has departed (was inserted into the network)
|
||||
VEHICLE_STATE_DEPARTED,
|
||||
/// @brief The vehicle started to teleport
|
||||
VEHICLE_STATE_STARTING_TELEPORT,
|
||||
/// @brief The vehicle ended being teleported
|
||||
VEHICLE_STATE_ENDING_TELEPORT,
|
||||
/// @brief The vehicle arrived at his destination (is deleted)
|
||||
VEHICLE_STATE_ARRIVED,
|
||||
/// @brief The vehicle got a new route
|
||||
VEHICLE_STATE_NEWROUTE,
|
||||
/// @brief The vehicles starts to park
|
||||
VEHICLE_STATE_STARTING_PARKING,
|
||||
/// @brief The vehicle ends to park
|
||||
VEHICLE_STATE_ENDING_PARKING,
|
||||
/// @brief The vehicles starts to stop
|
||||
VEHICLE_STATE_STARTING_STOP,
|
||||
/// @brief The vehicle ends to stop
|
||||
VEHICLE_STATE_ENDING_STOP,
|
||||
/// @brief The vehicle is involved in a collision
|
||||
VEHICLE_STATE_COLLISION,
|
||||
/// @brief The vehicle had to brake harder than permitted
|
||||
VEHICLE_STATE_EMERGENCYSTOP,
|
||||
/// @brief Vehicle maneuvering either entering or exiting a parking space
|
||||
VEHICLE_STATE_MANEUVERING
|
||||
};
|
||||
|
||||
|
||||
/** @class VehicleStateListener
|
||||
* @brief Interface for objects listening to vehicle state changes
|
||||
*/
|
||||
class VehicleStateListener {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
VehicleStateListener() { }
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~VehicleStateListener() { }
|
||||
|
||||
/** @brief Called if a vehicle changes its state
|
||||
* @param[in] vehicle The vehicle which changed its state
|
||||
* @param[in] to The state the vehicle has changed to
|
||||
* @param[in] info Additional information on the state change
|
||||
*/
|
||||
virtual void vehicleStateChanged(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info = "") = 0;
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** @brief Adds a vehicle states listener
|
||||
* @param[in] listener The listener to add
|
||||
*/
|
||||
void addVehicleStateListener(VehicleStateListener* listener);
|
||||
|
||||
|
||||
/** @brief Removes a vehicle states listener
|
||||
* @param[in] listener The listener to remove
|
||||
*/
|
||||
void removeVehicleStateListener(VehicleStateListener* listener);
|
||||
|
||||
|
||||
/** @brief Informs all added listeners about a vehicle's state change
|
||||
* @param[in] vehicle The vehicle which changed its state
|
||||
* @param[in] to The state the vehicle has changed to
|
||||
* @param[in] info Information regarding the replacement
|
||||
* @see VehicleStateListener:vehicleStateChanged
|
||||
*/
|
||||
void informVehicleStateListener(const SUMOVehicle* const vehicle, VehicleState to, const std::string& info = "");
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/** @brief Returns the travel time to pass an edge
|
||||
* @param[in] e The edge for which the travel time to be passed shall be returned
|
||||
* @param[in] v The vehicle that is rerouted
|
||||
* @param[in] t The time for which the travel time shall be returned [s]
|
||||
* @return The travel time for an edge
|
||||
* @see DijkstraRouter_ByProxi
|
||||
*/
|
||||
static double getTravelTime(const MSEdge* const e, const SUMOVehicle* const v, double t);
|
||||
|
||||
|
||||
/** @brief Returns the effort to pass an edge
|
||||
* @param[in] e The edge for which the effort to be passed shall be returned
|
||||
* @param[in] v The vehicle that is rerouted
|
||||
* @param[in] t The time for which the effort shall be returned [s]
|
||||
* @return The effort (abstract) for an edge
|
||||
* @see DijkstraRouter_ByProxi
|
||||
*/
|
||||
static double getEffort(const MSEdge* const e, const SUMOVehicle* const v, double t);
|
||||
|
||||
|
||||
/* @brief get the router, initialize on first use
|
||||
* @param[in] prohibited The vector of forbidden edges (optional)
|
||||
*/
|
||||
SUMOAbstractRouter<MSEdge, SUMOVehicle>& getRouterTT(const int rngIndex,
|
||||
const MSEdgeVector& prohibited = MSEdgeVector()) const;
|
||||
SUMOAbstractRouter<MSEdge, SUMOVehicle>& getRouterEffort(const int rngIndex,
|
||||
const MSEdgeVector& prohibited = MSEdgeVector()) const;
|
||||
MSPedestrianRouter& getPedestrianRouter(const int rngIndex, const MSEdgeVector& prohibited = MSEdgeVector()) const;
|
||||
MSIntermodalRouter& getIntermodalRouter(const int rngIndex, const int routingMode = 0, const MSEdgeVector& prohibited = MSEdgeVector()) const;
|
||||
|
||||
static void adaptIntermodalRouter(MSIntermodalRouter& router);
|
||||
|
||||
|
||||
/// @brief return whether the network contains internal links
|
||||
bool hasInternalLinks() const {
|
||||
return myHasInternalLinks;
|
||||
}
|
||||
|
||||
/// @brief return whether the network contains elevation data
|
||||
bool hasElevation() const {
|
||||
return myHasElevation;
|
||||
}
|
||||
|
||||
/// @brief return whether the network contains walkingareas and crossings
|
||||
bool hasPedestrianNetwork() const {
|
||||
return myHasPedestrianNetwork;
|
||||
|
||||
}
|
||||
/// @brief return whether the network contains bidirectional rail edges
|
||||
bool hasBidiEdges() const {
|
||||
return myHasBidiEdges;
|
||||
}
|
||||
|
||||
/// @brief return the network version
|
||||
double getNetworkVersion() const {
|
||||
return myVersion;
|
||||
}
|
||||
|
||||
/// @brief return whether a warning regarding the given object shall be issued
|
||||
bool warnOnce(const std::string& typeAndID);
|
||||
|
||||
void interrupt() {
|
||||
myAmInterrupted = true;
|
||||
}
|
||||
|
||||
bool isInterrupted() const {
|
||||
return myAmInterrupted;
|
||||
}
|
||||
|
||||
/// @brief find electrical substation by its id
|
||||
MSTractionSubstation* findTractionSubstation(const std::string& substationId);
|
||||
|
||||
/// @brief return whether given electrical substation exists in the network
|
||||
bool existTractionSubstation(const std::string& substationId);
|
||||
|
||||
protected:
|
||||
/// @brief check all lanes for elevation data
|
||||
bool checkElevation();
|
||||
|
||||
/// @brief check all lanes for type walkingArea
|
||||
bool checkWalkingarea();
|
||||
|
||||
/// @brief check wether bidirectional edges occur in the network
|
||||
bool checkBidiEdges();
|
||||
|
||||
protected:
|
||||
/// @brief Unique instance of MSNet
|
||||
static MSNet* myInstance;
|
||||
|
||||
/// @brief Route loader for dynamic loading of routes
|
||||
SUMORouteLoaderControl* myRouteLoaders;
|
||||
|
||||
/// @brief Current time step.
|
||||
SUMOTime myStep;
|
||||
|
||||
/// @brief Maximum number of teleports.
|
||||
int myMaxTeleports;
|
||||
|
||||
/// @brief whether an interrupt occured
|
||||
bool myAmInterrupted;
|
||||
|
||||
|
||||
|
||||
/// @name Substructures
|
||||
/// @{
|
||||
|
||||
/// @brief Controls vehicle building and deletion; @see MSVehicleControl
|
||||
MSVehicleControl* myVehicleControl;
|
||||
/// @brief Controls person building and deletion; @see MSTransportableControl
|
||||
MSTransportableControl* myPersonControl;
|
||||
/// @brief Controls container building and deletion; @see MSTransportableControl
|
||||
MSTransportableControl* myContainerControl;
|
||||
/// @brief Controls edges, performs vehicle movement; @see MSEdgeControl
|
||||
MSEdgeControl* myEdges;
|
||||
/// @brief Controls junctions, realizes right-of-way rules; @see MSJunctionControl
|
||||
MSJunctionControl* myJunctions;
|
||||
/// @brief Controls tls logics, realizes waiting on tls rules; @see MSJunctionControl
|
||||
MSTLLogicControl* myLogics;
|
||||
/// @brief Controls vehicle insertion; @see MSInsertionControl
|
||||
MSInsertionControl* myInserter;
|
||||
/// @brief Controls detectors; @see MSDetectorControl
|
||||
MSDetectorControl* myDetectorControl;
|
||||
/// @brief Controls events executed at the begin of a time step; @see MSEventControl
|
||||
MSEventControl* myBeginOfTimestepEvents;
|
||||
/// @brief Controls events executed at the end of a time step; @see MSEventControl
|
||||
MSEventControl* myEndOfTimestepEvents;
|
||||
/// @brief Controls insertion events; @see MSEventControl
|
||||
MSEventControl* myInsertionEvents;
|
||||
/// @brief A container for geometrical shapes; @see ShapeContainer
|
||||
ShapeContainer* myShapeContainer;
|
||||
/// @brief The net's knowledge about edge efforts/travel times; @see MSEdgeWeightsStorage
|
||||
MSEdgeWeightsStorage* myEdgeWeights;
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @name data needed for computing performance values
|
||||
/// @{
|
||||
|
||||
/// @brief Information whether the simulation duration shall be logged
|
||||
bool myLogExecutionTime;
|
||||
|
||||
/// @brief Information whether the number of the simulation step shall be logged
|
||||
bool myLogStepNumber;
|
||||
/// @brief Period between successive step-log outputs
|
||||
int myLogStepPeriod;
|
||||
|
||||
/// @brief The last simulation step duration
|
||||
long myTraCIStepDuration = 0, mySimStepDuration = 0;
|
||||
|
||||
/// @brief The overall simulation duration
|
||||
long mySimBeginMillis;
|
||||
|
||||
/// @brief The overall number of vehicle movements
|
||||
long long int myVehiclesMoved;
|
||||
long long int myPersonsMoved;
|
||||
//}
|
||||
|
||||
|
||||
|
||||
/// @name State output variables
|
||||
/// @{
|
||||
|
||||
/// @brief Times at which a state shall be written
|
||||
std::vector<SUMOTime> myStateDumpTimes;
|
||||
/// @brief The names for the state files
|
||||
std::vector<std::string> myStateDumpFiles;
|
||||
/// @brief The period for writing state
|
||||
SUMOTime myStateDumpPeriod;
|
||||
/// @brief name components for periodic state
|
||||
std::string myStateDumpPrefix;
|
||||
std::string myStateDumpSuffix;
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @brief Whether the network contains edges which not all vehicles may pass
|
||||
bool myHavePermissions;
|
||||
|
||||
/// @brief The vehicle class specific speed restrictions
|
||||
std::map<std::string, std::map<SUMOVehicleClass, double> > myRestrictions;
|
||||
|
||||
/// @brief Whether the network contains internal links/lanes/edges
|
||||
bool myHasInternalLinks;
|
||||
|
||||
/// @brief Whether the network contains elevation data
|
||||
bool myHasElevation;
|
||||
|
||||
/// @brief Whether the network contains pedestrian network elements
|
||||
bool myHasPedestrianNetwork;
|
||||
|
||||
/// @brief Whether the network contains bidirectional rail edges
|
||||
bool myHasBidiEdges;
|
||||
|
||||
/// @brief Whether the network was built for left-hand traffic
|
||||
bool myLefthand;
|
||||
|
||||
/// @brief the network version
|
||||
double myVersion;
|
||||
|
||||
/// @brief end of loaded edgeData
|
||||
SUMOTime myEdgeDataEndTime;
|
||||
|
||||
/// @brief Dictionary of bus / container stops
|
||||
std::map<SumoXMLTag, NamedObjectCont<MSStoppingPlace*> > myStoppingPlaces;
|
||||
|
||||
/// @brief Dictionary of traction substations
|
||||
std::vector<MSTractionSubstation*> myTractionSubstations;
|
||||
|
||||
/// @brief Container for vehicle state listener
|
||||
std::vector<VehicleStateListener*> myVehicleStateListeners;
|
||||
|
||||
#ifdef HAVE_FOX
|
||||
/// @brief to avoid concurrent access to the state update function
|
||||
FXMutex myStateListenerMutex;
|
||||
#endif
|
||||
|
||||
/// @brief container to record warnings that shall only be issued once
|
||||
std::map<std::string, bool> myWarnedOnce;
|
||||
|
||||
/* @brief The router instance for routing by trigger and by traci
|
||||
* @note MSDevice_Routing has its own instance since it uses a different weight function
|
||||
* @note we provide one member for every switchable router type
|
||||
* because the class structure makes it inconvenient to use a superclass
|
||||
*/
|
||||
mutable std::map<int, SUMOAbstractRouter<MSEdge, SUMOVehicle>*> myRouterTT;
|
||||
mutable std::map<int, SUMOAbstractRouter<MSEdge, SUMOVehicle>*> myRouterEffort;
|
||||
mutable std::map<int, MSPedestrianRouter*> myPedestrianRouter;
|
||||
mutable std::map<int, MSIntermodalRouter*> myIntermodalRouter;
|
||||
|
||||
/// @brief An RTree structure holding lane IDs
|
||||
mutable std::pair<bool, NamedRTree> myLanesRTree;
|
||||
|
||||
/// @brief Updater for dynamic shapes that are tracking traffic objects
|
||||
/// (ensures removal of shape dynamics when the objects are removed)
|
||||
/// @see utils/shapes/PolygonDynamics
|
||||
std::unique_ptr<MSDynamicShapeUpdater> myDynamicShapeUpdater;
|
||||
|
||||
|
||||
/// @brief string constants for simstep stages
|
||||
static const std::string STAGE_EVENTS;
|
||||
static const std::string STAGE_MOVEMENTS;
|
||||
static const std::string STAGE_LANECHANGE;
|
||||
static const std::string STAGE_INSERTIONS;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated copy constructor.
|
||||
MSNet(const MSNet&);
|
||||
|
||||
/// @brief Invalidated assignment operator.
|
||||
MSNet& operator=(const MSNet&);
|
||||
|
||||
|
||||
};
|
|
@ -1,66 +0,0 @@
|
|||
set(netbuild_STAT_SRCS
|
||||
NBAlgorithms.cpp
|
||||
NBAlgorithms.h
|
||||
NBAlgorithms_Ramps.cpp
|
||||
NBAlgorithms_Ramps.h
|
||||
NBAlgorithms_Railway.cpp
|
||||
NBAlgorithms_Railway.h
|
||||
NBCapacity2Lanes.h
|
||||
NBConnection.cpp
|
||||
NBConnection.h
|
||||
NBConnectionDefs.h
|
||||
NBCont.h
|
||||
NBContHelper.cpp
|
||||
NBContHelper.h
|
||||
NBDistrict.cpp
|
||||
NBDistrict.h
|
||||
NBDistrictCont.cpp
|
||||
NBDistrictCont.h
|
||||
NBEdge.cpp
|
||||
NBEdge.h
|
||||
NBEdgeCont.cpp
|
||||
NBEdgeCont.h
|
||||
NBFrame.cpp
|
||||
NBFrame.h
|
||||
NBHeightMapper.cpp
|
||||
NBHeightMapper.h
|
||||
NBHelpers.cpp
|
||||
NBHelpers.h
|
||||
NBLinkPossibilityMatrix.h
|
||||
NBNode.cpp
|
||||
NBNode.h
|
||||
NBNodeCont.cpp
|
||||
NBNodeCont.h
|
||||
NBNodeShapeComputer.cpp
|
||||
NBNodeShapeComputer.h
|
||||
NBParking.cpp
|
||||
NBParking.h
|
||||
NBPTStop.cpp
|
||||
NBPTStop.h
|
||||
NBPTStopCont.cpp
|
||||
NBPTStopCont.h
|
||||
NBRequest.cpp
|
||||
NBRequest.h
|
||||
NBTrafficLightDefinition.cpp
|
||||
NBTrafficLightDefinition.h
|
||||
NBTrafficLightLogic.cpp
|
||||
NBTrafficLightLogic.h
|
||||
NBTrafficLightLogicCont.cpp
|
||||
NBTrafficLightLogicCont.h
|
||||
NBTypeCont.cpp
|
||||
NBTypeCont.h
|
||||
NBSign.cpp
|
||||
NBSign.h
|
||||
NBOwnTLDef.cpp
|
||||
NBOwnTLDef.h
|
||||
NBLoadedTLDef.cpp
|
||||
NBLoadedTLDef.h
|
||||
NBLoadedSUMOTLDef.cpp
|
||||
NBLoadedSUMOTLDef.h
|
||||
NBVehicle.h
|
||||
NBNetBuilder.cpp
|
||||
NBNetBuilder.h
|
||||
NBPTLine.cpp NBPTLine.h NBPTLineCont.cpp NBPTLineCont.h NBPTPlatform.cpp NBPTPlatform.h)
|
||||
|
||||
add_library(netbuild STATIC ${netbuild_STAT_SRCS})
|
||||
set_property(TARGET netbuild PROPERTY PROJECT_LABEL "z_netbuild")
|
|
@ -1,520 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBAlgorithms.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @date 02. March 2012
|
||||
///
|
||||
// Algorithms for network computation
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include <algorithm>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include "NBEdge.h"
|
||||
#include "NBOwnTLDef.h"
|
||||
#include "NBTrafficLightLogicCont.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBTypeCont.h"
|
||||
#include "NBNode.h"
|
||||
#include "NBAlgorithms.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBTurningDirectionsComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
void
|
||||
NBTurningDirectionsComputer::computeTurnDirections(NBNodeCont& nc, bool warn) {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
|
||||
computeTurnDirectionsForNode(i->second, warn);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NBTurningDirectionsComputer::computeTurnDirectionsForNode(NBNode* node, bool warn) {
|
||||
const std::vector<NBEdge*>& incoming = node->getIncomingEdges();
|
||||
const std::vector<NBEdge*>& outgoing = node->getOutgoingEdges();
|
||||
// reset turning directions since this may be called multiple times
|
||||
for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
|
||||
(*k)->setTurningDestination(nullptr);
|
||||
}
|
||||
std::vector<Combination> combinations;
|
||||
const bool geometryLike = node->geometryLike();
|
||||
for (std::vector<NBEdge*>::const_iterator j = outgoing.begin(); j != outgoing.end(); ++j) {
|
||||
NBEdge* outedge = *j;
|
||||
for (std::vector<NBEdge*>::const_iterator k = incoming.begin(); k != incoming.end(); ++k) {
|
||||
NBEdge* e = *k;
|
||||
// @todo: check whether NBHelpers::relAngle is properly defined and whether it should really be used, here
|
||||
const double signedAngle = NBHelpers::normRelAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node));
|
||||
if (signedAngle > 0 && signedAngle < 177 && e->getGeometry().back().distanceTo2D(outedge->getGeometry().front()) < POSITION_EPS) {
|
||||
// backwards curving edges can only be turnaround when there are
|
||||
// non-default endpoints
|
||||
continue;
|
||||
}
|
||||
double angle = fabs(signedAngle);
|
||||
// std::cout << "incoming=" << e->getID() << " outgoing=" << outedge->getID() << " relAngle=" << NBHelpers::relAngle(e->getAngleAtNode(node), outedge->getAngleAtNode(node)) << "\n";
|
||||
const bool badPermissions = ((outedge->getPermissions() & e->getPermissions() & ~SVC_PEDESTRIAN) == 0
|
||||
&& !geometryLike
|
||||
&& outedge->getPermissions() != e->getPermissions());
|
||||
if (e->getFromNode() == outedge->getToNode()
|
||||
&& (angle > 120 || e->getFromNode()->getPosition() == e->getToNode()->getPosition())
|
||||
&& !badPermissions) {
|
||||
// they connect the same nodes; should be the turnaround direction
|
||||
// we'll assign a maximum number
|
||||
//
|
||||
// @todo: indeed, we have observed some pathological intersections
|
||||
// see "294831560" in OSM/adlershof. Here, several edges are connecting
|
||||
// same nodes. We have to do the angle check before...
|
||||
//
|
||||
// @todo: and well, there are some other as well, see plain import
|
||||
// of delphi_muenchen (elmar), intersection "59534191". Not that it would
|
||||
// be realistic in any means; we will warn, here.
|
||||
angle += 360;
|
||||
}
|
||||
if (angle < 160) {
|
||||
continue;
|
||||
}
|
||||
if (badPermissions) {
|
||||
// penalty
|
||||
angle -= 90;
|
||||
}
|
||||
Combination c;
|
||||
c.from = e;
|
||||
c.to = outedge;
|
||||
c.angle = angle;
|
||||
combinations.push_back(c);
|
||||
}
|
||||
}
|
||||
// sort combinations so that the ones with the highest angle are at the begin
|
||||
std::sort(combinations.begin(), combinations.end(), combination_by_angle_sorter());
|
||||
std::set<NBEdge*> seen;
|
||||
//std::cout << "check combinations at " << node->getID() << "\n";
|
||||
for (std::vector<Combination>::const_iterator j = combinations.begin(); j != combinations.end(); ++j) {
|
||||
//std::cout << " from=" << (*j).from->getID() << " to=" << (*j).to->getID() << " a=" << (*j).angle << "\n";
|
||||
if (seen.find((*j).from) != seen.end() || seen.find((*j).to) != seen.end()) {
|
||||
// do not regard already set edges
|
||||
if ((*j).angle > 360 && warn) {
|
||||
WRITE_WARNINGF("Ambiguity in turnarounds computation at junction '%'.", node->getID());
|
||||
//std::cout << " already seen: " << toString(seen) << "\n";
|
||||
warn = false;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// mark as seen
|
||||
seen.insert((*j).from);
|
||||
seen.insert((*j).to);
|
||||
// set turnaround information
|
||||
bool onlyPossible = (*j).from->getConnections().size() != 0 && !(*j).from->isConnectedTo((*j).to);
|
||||
//std::cout << " setTurningDestination from=" << (*j).from->getID() << " to=" << (*j).to->getID() << " onlyPossible=" << onlyPossible << "\n";
|
||||
(*j).from->setTurningDestination((*j).to, onlyPossible);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBNodesEdgesSorter
|
||||
// ---------------------------------------------------------------------------
|
||||
void
|
||||
NBNodesEdgesSorter::sortNodesEdges(NBNodeCont& nc, bool useNodeShape) {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
|
||||
i->second->sortEdges(useNodeShape);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBNodesEdgesSorter::swapWhenReversed(const NBNode* const n,
|
||||
const std::vector<NBEdge*>::iterator& i1,
|
||||
const std::vector<NBEdge*>::iterator& i2) {
|
||||
NBEdge* e1 = *i1;
|
||||
NBEdge* e2 = *i2;
|
||||
// @todo: The difference between "isTurningDirectionAt" and "isTurnaround"
|
||||
// is not nice. Maybe we could get rid of it if we would always mark edges
|
||||
// as turnarounds, even if they do not have to be added, as mentioned in
|
||||
// notes on NBTurningDirectionsComputer::computeTurnDirectionsForNode
|
||||
if (e2->getToNode() == n && e2->isTurningDirectionAt(e1)) {
|
||||
std::swap(*i1, *i2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBNodeTypeComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
void
|
||||
NBNodeTypeComputer::computeNodeTypes(NBNodeCont& nc, NBTrafficLightLogicCont& tlc) {
|
||||
validateRailCrossings(nc, tlc);
|
||||
const OptionsCont& oc = OptionsCont::getOptions();
|
||||
const double rightBeforeLeftSpeed = oc.getFloat("junctions.right-before-left.speed-threshold");
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
|
||||
NBNode* const n = (*i).second;
|
||||
// the type may already be set from the data
|
||||
if (n->myType != SumoXMLNodeType::UNKNOWN && n->myType != SumoXMLNodeType::DEAD_END) {
|
||||
n->myTypeWasGuessed = false;
|
||||
continue;
|
||||
}
|
||||
// check whether the node was set to be unregulated by the user
|
||||
if (oc.getBool("keep-nodes-unregulated") || oc.isInStringVector("keep-nodes-unregulated.explicit", n->getID())
|
||||
|| (oc.getBool("keep-nodes-unregulated.district-nodes") && (n->isNearDistrict() || n->isDistrict()))) {
|
||||
n->myType = SumoXMLNodeType::NOJUNCTION;
|
||||
continue;
|
||||
}
|
||||
// check whether the node is a waterway node. Set to unregulated by default
|
||||
bool waterway = true;
|
||||
for (NBEdge* e : n->getEdges()) {
|
||||
if (!isWaterway(e->getPermissions())) {
|
||||
waterway = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (waterway && (n->myType == SumoXMLNodeType::UNKNOWN || n->myType == SumoXMLNodeType::DEAD_END)) {
|
||||
n->myType = SumoXMLNodeType::NOJUNCTION;
|
||||
continue;
|
||||
}
|
||||
|
||||
// check whether the junction is not a real junction
|
||||
if (n->myIncomingEdges.size() == 1) {
|
||||
n->myType = SumoXMLNodeType::PRIORITY;
|
||||
continue;
|
||||
}
|
||||
// @todo "isSimpleContinuation" should be revalidated
|
||||
if (n->isSimpleContinuation()) {
|
||||
n->myType = SumoXMLNodeType::PRIORITY;
|
||||
continue;
|
||||
}
|
||||
if (isRailwayNode(n)) {
|
||||
// priority instead of unregulated to ensure that collisions can be detected
|
||||
n->myType = SumoXMLNodeType::PRIORITY;
|
||||
continue;
|
||||
}
|
||||
// determine the type
|
||||
SumoXMLNodeType type = SumoXMLNodeType::RIGHT_BEFORE_LEFT;
|
||||
for (EdgeVector::const_iterator i = n->myIncomingEdges.begin(); i != n->myIncomingEdges.end(); i++) {
|
||||
for (EdgeVector::const_iterator j = i + 1; j != n->myIncomingEdges.end(); j++) {
|
||||
// @todo "getOppositeIncoming" should probably be refactored into something the edge knows
|
||||
if (n->getOppositeIncoming(*j) == *i && n->myIncomingEdges.size() > 2) {
|
||||
continue;
|
||||
}
|
||||
// @todo check against a legal document
|
||||
// @todo figure out when SumoXMLNodeType::PRIORITY_STOP is appropriate
|
||||
const double s1 = (*i)->getSpeed();
|
||||
const double s2 = (*j)->getSpeed();
|
||||
const int p1 = (*i)->getPriority();
|
||||
const int p2 = (*j)->getPriority();
|
||||
if (fabs(s1 - s2) > (9.5 / 3.6) || MAX2(s1, s2) >= rightBeforeLeftSpeed || p1 != p2) {
|
||||
type = SumoXMLNodeType::PRIORITY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// save type
|
||||
n->myType = type;
|
||||
n->myTypeWasGuessed = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBNodeTypeComputer::validateRailCrossings(NBNodeCont& nc, NBTrafficLightLogicCont& tlc) {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
|
||||
NBNode* n = (*i).second;
|
||||
if (n->myType == SumoXMLNodeType::RAIL_CROSSING) {
|
||||
// check if it really is a rail crossing
|
||||
int numRailway = 0;
|
||||
int numNonRailway = 0;
|
||||
int numNonRailwayNonPed = 0;
|
||||
for (NBEdge* e : n->getIncomingEdges()) {
|
||||
if ((e->getPermissions() & ~SVC_RAIL_CLASSES) != 0) {
|
||||
numNonRailway++;
|
||||
if (e->getPermissions() != SVC_PEDESTRIAN) {
|
||||
numNonRailwayNonPed++;
|
||||
}
|
||||
} else if ((e->getPermissions() & SVC_RAIL_CLASSES) != 0) {
|
||||
numRailway++;
|
||||
}
|
||||
}
|
||||
for (NBEdge* e : n->getOutgoingEdges()) {
|
||||
if (e->getPermissions() == SVC_PEDESTRIAN) {
|
||||
numNonRailway++;
|
||||
}
|
||||
}
|
||||
if (numNonRailway == 0 || numRailway == 0) {
|
||||
// not a crossing (maybe unregulated or rail_signal)
|
||||
n->myType = SumoXMLNodeType::PRIORITY;
|
||||
} else if (numNonRailwayNonPed > 2) {
|
||||
// does not look like a rail crossing (roads in conflict). maybe a traffic light?
|
||||
WRITE_WARNINGF("Converting invalid rail_crossing to traffic_light at junction '%'.", n->getID());
|
||||
TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(OptionsCont::getOptions().getString("tls.default-type"));
|
||||
NBTrafficLightDefinition* tlDef = new NBOwnTLDef(n->getID(), n, 0, type);
|
||||
n->myType = SumoXMLNodeType::TRAFFIC_LIGHT;
|
||||
if (!tlc.insert(tlDef)) {
|
||||
// actually, nothing should fail here
|
||||
n->removeTrafficLight(tlDef);
|
||||
n->myType = SumoXMLNodeType::PRIORITY;
|
||||
delete tlDef;
|
||||
WRITE_WARNINGF("Could not allocate tls '%'.", n->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBNodeTypeComputer::isRailwayNode(const NBNode* n) {
|
||||
bool hasRailway = false;
|
||||
for (NBEdge* e : n->getIncomingEdges()) {
|
||||
if ((e->getPermissions() & ~SVC_RAIL_CLASSES) != 0) {
|
||||
return false;
|
||||
} else if ((e->getPermissions() & SVC_RAIL_CLASSES) != 0) {
|
||||
hasRailway = true;
|
||||
}
|
||||
}
|
||||
return hasRailway;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBEdgePriorityComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
void
|
||||
NBEdgePriorityComputer::computeEdgePriorities(NBNodeCont& nc) {
|
||||
for (const auto& node : nc) {
|
||||
// preset all junction's edge priorities to zero
|
||||
for (NBEdge* const edge : node.second->myAllEdges) {
|
||||
edge->setJunctionPriority(node.second, NBEdge::JunctionPriority::MINOR_ROAD);
|
||||
}
|
||||
node.second->markBentPriority(false);
|
||||
// check if the junction is not a real junction
|
||||
if (node.second->myIncomingEdges.size() == 1 && node.second->myOutgoingEdges.size() == 1) {
|
||||
continue;
|
||||
}
|
||||
// compute the priorities on junction when needed
|
||||
if (node.second->getType() != SumoXMLNodeType::RIGHT_BEFORE_LEFT && node.second->getType() != SumoXMLNodeType::ALLWAY_STOP && node.second->getType() != SumoXMLNodeType::NOJUNCTION) {
|
||||
if (node.second->getRightOfWay() == RightOfWay::EDGEPRIORITY) {
|
||||
for (NBEdge* e : node.second->getIncomingEdges()) {
|
||||
e->setJunctionPriority(node.second, e->getPriority());
|
||||
}
|
||||
} else {
|
||||
setPriorityJunctionPriorities(*node.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBEdgePriorityComputer::setPriorityJunctionPriorities(NBNode& n) {
|
||||
if (n.myIncomingEdges.size() == 0 || n.myOutgoingEdges.size() == 0) {
|
||||
return;
|
||||
}
|
||||
EdgeVector incoming = n.myIncomingEdges;
|
||||
EdgeVector outgoing = n.myOutgoingEdges;
|
||||
// what we do want to have is to extract the pair of roads that are
|
||||
// the major roads for this junction
|
||||
// let's get the list of incoming edges with the highest priority
|
||||
std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_by_priority_sorter());
|
||||
EdgeVector bestIncoming;
|
||||
NBEdge* best = incoming[0];
|
||||
while (incoming.size() > 0 && samePriority(best, incoming[0])) {
|
||||
bestIncoming.push_back(*incoming.begin());
|
||||
incoming.erase(incoming.begin());
|
||||
}
|
||||
// now, let's get the list of best outgoing
|
||||
assert(outgoing.size() != 0);
|
||||
sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_by_priority_sorter());
|
||||
EdgeVector bestOutgoing;
|
||||
best = outgoing[0];
|
||||
while (outgoing.size() > 0 && samePriority(best, outgoing[0])) { //->getPriority()==best->getPriority()) {
|
||||
bestOutgoing.push_back(*outgoing.begin());
|
||||
outgoing.erase(outgoing.begin());
|
||||
}
|
||||
// special case: user input makes mainDirection unambiguous
|
||||
const bool mainDirectionExplicit = (
|
||||
bestIncoming.size() == 1 && n.myIncomingEdges.size() <= 2
|
||||
&& (incoming.size() == 0 || bestIncoming[0]->getPriority() > incoming[0]->getPriority())
|
||||
&& bestOutgoing.size() == 1 && n.myOutgoingEdges.size() <= 2
|
||||
&& (outgoing.size() == 0 || bestOutgoing[0]->getPriority() > outgoing[0]->getPriority())
|
||||
&& !bestIncoming[0]->isTurningDirectionAt(bestOutgoing[0]));
|
||||
// now, let's compute for each of the best incoming edges
|
||||
// the incoming which is most opposite
|
||||
// the outgoing which is most opposite
|
||||
EdgeVector::iterator i;
|
||||
std::map<NBEdge*, NBEdge*> counterIncomingEdges;
|
||||
std::map<NBEdge*, NBEdge*> counterOutgoingEdges;
|
||||
incoming = n.myIncomingEdges;
|
||||
outgoing = n.myOutgoingEdges;
|
||||
for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
|
||||
std::sort(incoming.begin(), incoming.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n, true));
|
||||
counterIncomingEdges[*i] = *incoming.begin();
|
||||
std::sort(outgoing.begin(), outgoing.end(), NBContHelper::edge_opposite_direction_sorter(*i, &n, true));
|
||||
counterOutgoingEdges[*i] = *outgoing.begin();
|
||||
}
|
||||
//std::cout << "n=" << n.getID() << " best=" << best->getID() << " bestIncoming=" << toString(bestIncoming) << "\n incoming=" << toString(incoming) << "\n outgoing=" << toString(outgoing) << "\n mainExplicit=" << mainDirectionExplicit << " counterBest=" << counterIncomingEdges.find(bestIncoming[0])->second->getID() << "\n";
|
||||
// ok, let's try
|
||||
// 1) there is one best incoming road
|
||||
if (bestIncoming.size() == 1) {
|
||||
// let's mark this road as the best
|
||||
NBEdge* best1 = extractAndMarkFirst(n, bestIncoming);
|
||||
if (!mainDirectionExplicit && counterIncomingEdges.find(best1) != counterIncomingEdges.end()) {
|
||||
// ok, look, what we want is the opposit of the straight continuation edge
|
||||
// but, what if such an edge does not exist? By now, we'll determine it
|
||||
// geometrically
|
||||
NBEdge* s = counterIncomingEdges.find(best1)->second;
|
||||
const double minAngleDiff = GeomHelper::getMinAngleDiff(best1->getAngleAtNode(&n), s->getAngleAtNode(&n));
|
||||
if (minAngleDiff > 180 - 45
|
||||
|| (minAngleDiff > 75 && s->getPriority() == best1->getPriority() && hasDifferentPriorities(incoming, best1))) {
|
||||
s->setJunctionPriority(&n, NBEdge::PRIORITY_ROAD);
|
||||
}
|
||||
}
|
||||
markBestParallel(n, best1, nullptr);
|
||||
assert(bestOutgoing.size() != 0);
|
||||
// mark the best outgoing as the continuation
|
||||
sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(best1));
|
||||
// assign extra priority if the priorities are unambiguous (regardless of geometry)
|
||||
NBEdge* bestOut = extractAndMarkFirst(n, bestOutgoing);
|
||||
if (!mainDirectionExplicit && counterOutgoingEdges.find(bestOut) != counterOutgoingEdges.end()) {
|
||||
NBEdge* s = counterOutgoingEdges.find(bestOut)->second;
|
||||
if (GeomHelper::getMinAngleDiff(bestOut->getAngleAtNode(&n), s->getAngleAtNode(&n)) > 180 - 45) {
|
||||
s->setJunctionPriority(&n, 1);
|
||||
}
|
||||
}
|
||||
n.markBentPriority(n.getDirection(best1, bestOut) != LinkDirection::STRAIGHT);
|
||||
return;
|
||||
}
|
||||
|
||||
// ok, what we want to do in this case is to determine which incoming
|
||||
// has the best continuation...
|
||||
// This means, when several incoming roads have the same priority,
|
||||
// we want a (any) straight connection to be more priorised than a turning
|
||||
double bestAngle = 0;
|
||||
NBEdge* bestFirst = nullptr;
|
||||
NBEdge* bestSecond = nullptr;
|
||||
bool hadBest = false;
|
||||
for (i = bestIncoming.begin(); i != bestIncoming.end(); ++i) {
|
||||
EdgeVector::iterator j;
|
||||
NBEdge* t1 = *i;
|
||||
double angle1 = t1->getAngleAtNode(&n) + 180;
|
||||
if (angle1 >= 360) {
|
||||
angle1 -= 360;
|
||||
}
|
||||
for (j = i + 1; j != bestIncoming.end(); ++j) {
|
||||
NBEdge* t2 = *j;
|
||||
double angle2 = t2->getAngleAtNode(&n) + 180;
|
||||
if (angle2 >= 360) {
|
||||
angle2 -= 360;
|
||||
}
|
||||
double angle = GeomHelper::getMinAngleDiff(angle1, angle2);
|
||||
if (!hadBest || angle > bestAngle) {
|
||||
bestAngle = angle;
|
||||
bestFirst = *i;
|
||||
bestSecond = *j;
|
||||
hadBest = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
bestFirst->setJunctionPriority(&n, 1);
|
||||
sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestFirst));
|
||||
if (bestOutgoing.size() != 0) {
|
||||
extractAndMarkFirst(n, bestOutgoing);
|
||||
}
|
||||
bestSecond->setJunctionPriority(&n, 1);
|
||||
sort(bestOutgoing.begin(), bestOutgoing.end(), NBContHelper::edge_similar_direction_sorter(bestSecond));
|
||||
if (bestOutgoing.size() != 0) {
|
||||
extractAndMarkFirst(n, bestOutgoing);
|
||||
}
|
||||
n.markBentPriority(GeomHelper::getMinAngleDiff(bestFirst->getAngleAtNode(&n), bestSecond->getAngleAtNode(&n)) < 135);
|
||||
markBestParallel(n, bestFirst, bestSecond);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBEdgePriorityComputer::markBestParallel(const NBNode& n, NBEdge* bestFirst, NBEdge* bestSecond) {
|
||||
// edges running parallel to the main direction should also be prioritised
|
||||
const double a1 = bestFirst->getAngleAtNode(&n);
|
||||
const double a2 = bestSecond == nullptr ? a1 : bestSecond->getAngleAtNode(&n);
|
||||
SVCPermissions p1 = bestFirst->getPermissions();
|
||||
SVCPermissions p2 = bestSecond == nullptr ? p1 : bestSecond->getPermissions();
|
||||
for (NBEdge* e : n.getIncomingEdges()) {
|
||||
// @note: this rule might also apply if there are common permissions but
|
||||
// then we would not further rules to resolve the priority between the best edge and its parallel edge
|
||||
SVCPermissions perm = e->getPermissions();
|
||||
if (((GeomHelper::getMinAngleDiff(e->getAngleAtNode(&n), a1) < 10
|
||||
|| GeomHelper::getMinAngleDiff(e->getAngleAtNode(&n), a2) < 10))
|
||||
&& (p1 & perm) == 0 && (p2 & perm) == 0) {
|
||||
e->setJunctionPriority(&n, 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBEdgePriorityComputer::extractAndMarkFirst(NBNode& n, std::vector<NBEdge*>& s, int prio) {
|
||||
if (s.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
NBEdge* ret = s.front();
|
||||
s.erase(s.begin());
|
||||
ret->setJunctionPriority(&n, prio);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBEdgePriorityComputer::samePriority(const NBEdge* const e1, const NBEdge* const e2) {
|
||||
if (e1 == e2) {
|
||||
return true;
|
||||
}
|
||||
if (e1->getPriority() != e2->getPriority()) {
|
||||
return false;
|
||||
}
|
||||
if ((int) e1->getSpeed() != (int) e2->getSpeed()) {
|
||||
return false;
|
||||
}
|
||||
return (int) e1->getNumLanes() == (int) e2->getNumLanes();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBEdgePriorityComputer::hasDifferentPriorities(const EdgeVector& edges, const NBEdge* excluded) {
|
||||
if (edges.size() < 2) {
|
||||
return false;
|
||||
}
|
||||
int prio = edges[0] == excluded ? edges[1]->getPriority() : edges[0]->getPriority();
|
||||
for (auto e : edges) {
|
||||
if (e != excluded && e->getPriority() != prio) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
NBNodesEdgesSorter::crossing_by_junction_angle_sorter::crossing_by_junction_angle_sorter(const NBNode* node, const EdgeVector& ordering) {
|
||||
// reorder based on getAngleAtNodeToCenter
|
||||
myOrdering = ordering;
|
||||
sort(myOrdering.begin(), myOrdering.end(), NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter(node));
|
||||
// let the first edge remain the first
|
||||
rotate(myOrdering.begin(), std::find(myOrdering.begin(), myOrdering.end(), ordering.front()), myOrdering.end());
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,258 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBAlgorithms.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @date 02. March 2012
|
||||
///
|
||||
// Algorithms for network computation
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <map>
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBNodeCont.h"
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBEdge;
|
||||
class NBNode;
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBTurningDirectionsComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBTurningDirectionsComputer
|
||||
* @brief Computes turnaround destinations for all edges (if exist)
|
||||
*/
|
||||
class NBTurningDirectionsComputer {
|
||||
public:
|
||||
/** @brief Computes turnaround destinations for all edges (if exist)
|
||||
* @param[in] nc The container of nodes to loop along
|
||||
* @param[in] warn Whether warnings shall be issued
|
||||
*/
|
||||
static void computeTurnDirections(NBNodeCont& nc, bool warn = true);
|
||||
|
||||
/** @brief Computes turnaround destinations for all incoming edges of the given nodes (if any)
|
||||
* @param[in] node The node for which to compute turnaround destinations
|
||||
* @param[in] warn Whether warnings shall be issued
|
||||
* @note: This is needed by NETEDIT
|
||||
*/
|
||||
static void computeTurnDirectionsForNode(NBNode* node, bool warn);
|
||||
|
||||
private:
|
||||
/** @struct Combination
|
||||
* @brief Stores the information about the angle between an incoming ("from") and an outgoing ("to") edge
|
||||
*
|
||||
* Note that the angle is increased by 360 if the edges connect the same two nodes in
|
||||
* opposite direction.
|
||||
*/
|
||||
struct Combination {
|
||||
NBEdge* from;
|
||||
NBEdge* to;
|
||||
double angle;
|
||||
};
|
||||
|
||||
|
||||
/** @class combination_by_angle_sorter
|
||||
* @brief Sorts "Combination"s by decreasing angle
|
||||
*/
|
||||
class combination_by_angle_sorter {
|
||||
public:
|
||||
explicit combination_by_angle_sorter() { }
|
||||
int operator()(const Combination& c1, const Combination& c2) const {
|
||||
if (c1.angle != c2.angle) {
|
||||
return c1.angle > c2.angle;
|
||||
}
|
||||
if (c1.from != c2.from) {
|
||||
return c1.from->getID() < c2.from->getID();
|
||||
}
|
||||
return c1.to->getID() < c2.to->getID();
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBNodesEdgesSorter
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBNodesEdgesSorter
|
||||
* @brief Sorts a node's edges clockwise regarding driving direction
|
||||
*/
|
||||
class NBNodesEdgesSorter {
|
||||
public:
|
||||
/** @brief Sorts a node's edges clockwise regarding driving direction
|
||||
* @param[in] nc The container of nodes to loop along
|
||||
* @param[in] useNodeShape Whether to sort based on the node shape (instead of only the edge angle)
|
||||
*/
|
||||
static void sortNodesEdges(NBNodeCont& nc, bool useNodeShape = false);
|
||||
|
||||
/** @class crossing_by_junction_angle_sorter
|
||||
* @brief Sorts crossings by minimum clockwise clockwise edge angle. Use the
|
||||
* ordering found in myAllEdges of the given node
|
||||
*/
|
||||
class crossing_by_junction_angle_sorter {
|
||||
public:
|
||||
explicit crossing_by_junction_angle_sorter(const NBNode* node, const EdgeVector& ordering);
|
||||
|
||||
int operator()(const std::unique_ptr<NBNode::Crossing>& c1, const std::unique_ptr<NBNode::Crossing>& c2) const {
|
||||
const int r1 = getMinRank(c1->edges);
|
||||
const int r2 = getMinRank(c2->edges);
|
||||
if (r1 == r2) {
|
||||
return c1->edges.size() > c2->edges.size();
|
||||
} else {
|
||||
return (int)(r1 < r2);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief retrieves the minimum index in myAllEdges
|
||||
int getMinRank(const EdgeVector& e) const {
|
||||
int result = (int)myOrdering.size();
|
||||
for (EdgeVector::const_iterator it = e.begin(); it != e.end(); ++it) {
|
||||
int rank = (int)std::distance(myOrdering.begin(), std::find(myOrdering.begin(), myOrdering.end(), *it));
|
||||
result = MIN2(result, rank);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private:
|
||||
EdgeVector myOrdering;
|
||||
|
||||
private:
|
||||
/// @brief invalidated assignment operator
|
||||
crossing_by_junction_angle_sorter& operator=(const crossing_by_junction_angle_sorter& s);
|
||||
|
||||
};
|
||||
/** @brief Assures correct order for same-angle opposite-direction edges
|
||||
* @param[in] n The currently processed node
|
||||
* @param[in] i1 Pointer to first edge
|
||||
* @param[in] i2 Pointer to second edge
|
||||
*/
|
||||
static void swapWhenReversed(const NBNode* const n,
|
||||
const std::vector<NBEdge*>::iterator& i1,
|
||||
const std::vector<NBEdge*>::iterator& i2);
|
||||
|
||||
|
||||
/** @class edge_by_junction_angle_sorter
|
||||
* @brief Sorts incoming and outgoing edges clockwise around the given node
|
||||
*/
|
||||
class edge_by_junction_angle_sorter {
|
||||
public:
|
||||
explicit edge_by_junction_angle_sorter(NBNode* n) : myNode(n) {}
|
||||
int operator()(NBEdge* e1, NBEdge* e2) const {
|
||||
return getConvAngle(e1) < getConvAngle(e2);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @brief Converts the angle of the edge if it is an incoming edge
|
||||
double getConvAngle(NBEdge* e) const {
|
||||
double angle = e->getAngleAtNode(myNode);
|
||||
if (angle < 0.) {
|
||||
angle = 360. + angle;
|
||||
}
|
||||
// convert angle if the edge is an outgoing edge
|
||||
if (e->getFromNode() == myNode) {
|
||||
angle += (double) 180.;
|
||||
if (angle >= (double) 360.) {
|
||||
angle -= (double) 360.;
|
||||
}
|
||||
}
|
||||
if (angle < 0.1 || angle > 359.9) {
|
||||
angle = (double) 0.;
|
||||
}
|
||||
assert(angle >= 0 && angle < (double)360);
|
||||
return angle;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief The node to compute the relative angle of
|
||||
NBNode* myNode;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBNodeTypeComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBNodeTypeComputer
|
||||
* @brief Computes node types
|
||||
*/
|
||||
class NBNodeTypeComputer {
|
||||
public:
|
||||
/** @brief Computes node types
|
||||
* @param[in] nc The container of nodes to loop along
|
||||
*/
|
||||
static void computeNodeTypes(NBNodeCont& nc, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/** @brief Checks rail_crossing for validity
|
||||
* @param[in] nc The container of nodes to loop along
|
||||
*/
|
||||
static void validateRailCrossings(NBNodeCont& nc, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/// @brief whether the given node only has rail edges
|
||||
static bool isRailwayNode(const NBNode* n);
|
||||
};
|
||||
|
||||
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBEdgePriorityComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBEdgePriorityComputer
|
||||
* @brief Computes edge priorities within a node
|
||||
*/
|
||||
class NBEdgePriorityComputer {
|
||||
public:
|
||||
/** @brief Computes edge priorities within a node
|
||||
* @param[in] nc The container of nodes to loop along
|
||||
*/
|
||||
static void computeEdgePriorities(NBNodeCont& nc);
|
||||
|
||||
private:
|
||||
/** @brief Sets the priorites in case of a priority junction
|
||||
* @param[in] n The node to set edges' priorities
|
||||
*/
|
||||
static void setPriorityJunctionPriorities(NBNode& n);
|
||||
|
||||
/// @brief set priority for edges that are parallel to the best edges
|
||||
static void markBestParallel(const NBNode& n, NBEdge* bestFirst, NBEdge* bestSecond);
|
||||
|
||||
/** @brief Sets the priorites in case of a priority junction
|
||||
* @param[in] n The node to set edges' priorities
|
||||
* @param[in] s The vector of edges to get and mark the first from
|
||||
* @param[in] prio The priority to assign
|
||||
* @return The vector's first edge
|
||||
*/
|
||||
static NBEdge* extractAndMarkFirst(NBNode& n, std::vector<NBEdge*>& s, int prio = 1);
|
||||
|
||||
/** @brief Returns whether both edges have the same priority
|
||||
* @param[in] e1 The first edge
|
||||
* @param[in] e2 The second edge
|
||||
* Whether both edges have the same priority
|
||||
*/
|
||||
static bool samePriority(const NBEdge* const e1, const NBEdge* const e2);
|
||||
|
||||
/// @brief return whether the priorite attribute can be used to distinguish the edges
|
||||
static bool hasDifferentPriorities(const EdgeVector& edges, const NBEdge* excluded);
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,146 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBAlgorithms_Railway.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Melanie Weber
|
||||
/// @date 29. March 2018
|
||||
///
|
||||
// Algorithms for railways
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include "NBEdge.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBNetBuilder;
|
||||
class OptionsCont;
|
||||
class NBVehicle;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBAlgorithms_Railway
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBRampsComputer
|
||||
* @brief Computes highway on-/off-ramps (if wished)
|
||||
*/
|
||||
class NBRailwayTopologyAnalyzer {
|
||||
public:
|
||||
/** @brief Computes highway on-/off-ramps (if wished)
|
||||
* @param[in, changed] nb The network builder which contains the current network representation
|
||||
* @param[in] oc The options container
|
||||
*/
|
||||
static void analyzeTopology(NBNetBuilder& nb);
|
||||
static void repairTopology(NBNetBuilder& nb);
|
||||
static void makeAllBidi(NBNetBuilder& nb);
|
||||
static void assignDirectionPriority(NBNetBuilder& nb);
|
||||
|
||||
/// routing edge
|
||||
class Track {
|
||||
public:
|
||||
Track(NBEdge* e, int i = -1, const std::string& _id = "") :
|
||||
edge(e),
|
||||
index(i < 0 ? edge->getNumericalID() : i),
|
||||
id(_id == "" ? edge->getID() : _id),
|
||||
minPermissions(edge->getPermissions()) {
|
||||
}
|
||||
|
||||
void addSuccessor(Track* track);
|
||||
const std::vector<Track*>& getSuccessors(SUMOVehicleClass svc = SVC_IGNORING) const;
|
||||
const std::vector<std::pair<const Track*, const Track*> >& getViaSuccessors(SUMOVehicleClass svc = SVC_IGNORING) const;
|
||||
|
||||
const std::string& getID() const {
|
||||
return id;
|
||||
}
|
||||
int getNumericalID() const {
|
||||
return index;
|
||||
}
|
||||
double getLength() const {
|
||||
return 0.;
|
||||
}
|
||||
const Track* getBidiEdge() const {
|
||||
return this;
|
||||
}
|
||||
bool isInternal() const {
|
||||
return false;
|
||||
}
|
||||
inline bool prohibits(const NBVehicle* const /*veh*/) const {
|
||||
return false;
|
||||
}
|
||||
inline bool restricts(const NBVehicle* const /*veh*/) const {
|
||||
return false;
|
||||
}
|
||||
|
||||
NBEdge* edge;
|
||||
|
||||
private:
|
||||
const int index;
|
||||
const std::string id;
|
||||
std::vector<Track*> successors;
|
||||
std::vector<std::pair<const Track*, const Track*> > viaSuccessors;
|
||||
SVCPermissions minPermissions;
|
||||
mutable std::map<SUMOVehicleClass, std::vector<Track*> > svcSuccessors;
|
||||
mutable std::map<SUMOVehicleClass, std::vector<std::pair<const Track*, const Track*> > > svcViaSuccessors;
|
||||
|
||||
Track& operator=(const Track&) = delete;
|
||||
};
|
||||
static double getTravelTimeStatic(const Track* const track, const NBVehicle* const veh, double time);
|
||||
|
||||
private:
|
||||
static std::set<NBNode*> getRailNodes(NBNetBuilder& nb, bool verbose = false);
|
||||
static std::set<NBNode*> getBrokenRailNodes(NBNetBuilder& nb, bool verbose = false);
|
||||
|
||||
/// @brief filter out rail edges among all edges of a the given node
|
||||
static void getRailEdges(const NBNode* node, EdgeVector& inEdges, EdgeVector& outEdges);
|
||||
|
||||
static bool isStraight(const NBNode* node, const NBEdge* e1, const NBEdge* e2);
|
||||
static bool hasStraightPair(const NBNode* node, const EdgeVector& edges, const EdgeVector& edges2);
|
||||
static bool allBroken(const NBNode* node, NBEdge* candOut, const EdgeVector& in, const EdgeVector& out);
|
||||
static bool allSharp(const NBNode* node, const EdgeVector& in, const EdgeVector& out, bool countBidiAsSharp = false);
|
||||
static bool allBidi(const EdgeVector& edges);
|
||||
static NBEdge* isBidiSwitch(const NBNode* n);
|
||||
|
||||
/// @brief add bidi-edge for the given edge
|
||||
static NBEdge* addBidiEdge(NBNetBuilder& nb, NBEdge* edge, bool update = true);
|
||||
|
||||
/// @brief add further bidi-edges near existing bidi-edges
|
||||
static int extendBidiEdges(NBNetBuilder& nb);
|
||||
static int extendBidiEdges(NBNetBuilder& nb, NBNode* node, NBEdge* bidiIn);
|
||||
|
||||
/// @brief reverse edges sequences that are to broken nodes on both sides
|
||||
static void reverseEdges(NBNetBuilder& nb);
|
||||
|
||||
/// @brief add bidi-edges to connect buffers stops in both directions
|
||||
static void addBidiEdgesForBufferStops(NBNetBuilder& nb);
|
||||
|
||||
/// @brief add bidi-edges to connect switches that are approached in both directions
|
||||
static void addBidiEdgesBetweenSwitches(NBNetBuilder& nb);
|
||||
|
||||
/// @brief add bidi-edges to connect successive public transport stops
|
||||
static void addBidiEdgesForStops(NBNetBuilder& nb);
|
||||
|
||||
/// @brief add bidi-edges to connect straight tracks
|
||||
static void addBidiEdgesForStraightConnectivity(NBNetBuilder& nb, bool geometryLike);
|
||||
|
||||
/// recompute turning directions for both nodes of the given edge
|
||||
static void updateTurns(NBEdge* edge);
|
||||
|
||||
};
|
|
@ -1,633 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBAlgorithms_Ramps.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date 29. March 2012
|
||||
///
|
||||
// Algorithms for highway on-/off-ramps computation
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include "NBNetBuilder.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBNode.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBAlgorithms_Ramps.h"
|
||||
|
||||
#define OFFRAMP_LOOKBACK 500
|
||||
|
||||
//#define DEBUG_RAMPS
|
||||
#define DEBUGNODEID "260479469"
|
||||
#define DEBUGCOND(obj) ((obj != 0 && (obj)->getID() == DEBUGNODEID))
|
||||
|
||||
// ===========================================================================
|
||||
// static members
|
||||
// ===========================================================================
|
||||
const std::string NBRampsComputer::ADDED_ON_RAMP_EDGE("-AddedOnRampEdge");
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBRampsComputer
|
||||
// ---------------------------------------------------------------------------
|
||||
void
|
||||
NBRampsComputer::computeRamps(NBNetBuilder& nb, OptionsCont& oc) {
|
||||
const bool guessAndAdd = oc.getBool("ramps.guess");
|
||||
const double minHighwaySpeed = oc.getFloat("ramps.min-highway-speed");
|
||||
const double maxRampSpeed = oc.getFloat("ramps.max-ramp-speed");
|
||||
const double rampLength = oc.getFloat("ramps.ramp-length");
|
||||
const double minWeaveLength = oc.getFloat("ramps.min-weave-length");
|
||||
const bool dontSplit = oc.getBool("ramps.no-split");
|
||||
NBEdgeCont& ec = nb.getEdgeCont();
|
||||
std::set<NBEdge*> incremented;
|
||||
// collect join exclusions
|
||||
std::set<std::string> noramps;
|
||||
if (oc.isSet("ramps.unset")) {
|
||||
std::vector<std::string> edges = oc.getStringVector("ramps.unset");
|
||||
noramps.insert(edges.begin(), edges.end());
|
||||
}
|
||||
// exclude roundabouts
|
||||
const std::set<EdgeSet>& roundabouts = ec.getRoundabouts();
|
||||
for (std::set<EdgeSet>::const_iterator it_round = roundabouts.begin();
|
||||
it_round != roundabouts.end(); ++it_round) {
|
||||
for (EdgeSet::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) {
|
||||
noramps.insert((*it_edge)->getID());
|
||||
}
|
||||
}
|
||||
// exclude public transport edges
|
||||
nb.getPTStopCont().addEdges2Keep(oc, noramps);
|
||||
nb.getPTLineCont().addEdges2Keep(oc, noramps);
|
||||
nb.getParkingCont().addEdges2Keep(oc, noramps);
|
||||
|
||||
// check whether on-off ramps shall be guessed
|
||||
if (guessAndAdd || oc.getBool("ramps.guess-acceleration-lanes")) {
|
||||
NBNodeCont& nc = nb.getNodeCont();
|
||||
NBEdgeCont& ec = nb.getEdgeCont();
|
||||
NBDistrictCont& dc = nb.getDistrictCont();
|
||||
for (auto it = ec.begin(); it != ec.end(); ++it) {
|
||||
it->second->markOffRamp(false);
|
||||
}
|
||||
|
||||
// if an edge is part of two ramps, ordering is important
|
||||
std::set<NBNode*, ComparatorIdLess> potOnRamps;
|
||||
std::set<NBNode*, ComparatorIdLess> potOffRamps;
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = nc.begin(); i != nc.end(); ++i) {
|
||||
NBNode* cur = (*i).second;
|
||||
if (mayNeedOnRamp(cur, minHighwaySpeed, maxRampSpeed, noramps, minWeaveLength)) {
|
||||
potOnRamps.insert(cur);
|
||||
}
|
||||
if (mayNeedOffRamp(cur, minHighwaySpeed, maxRampSpeed, noramps)) {
|
||||
potOffRamps.insert(cur);
|
||||
}
|
||||
}
|
||||
for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOnRamps.begin(); i != potOnRamps.end(); ++i) {
|
||||
buildOnRamp(*i, nc, ec, dc, rampLength, dontSplit || !guessAndAdd, guessAndAdd);
|
||||
}
|
||||
for (std::set<NBNode*, ComparatorIdLess>::const_iterator i = potOffRamps.begin(); i != potOffRamps.end(); ++i) {
|
||||
buildOffRamp(*i, nc, ec, dc, rampLength, dontSplit || !guessAndAdd, guessAndAdd, potOnRamps);
|
||||
}
|
||||
}
|
||||
// check whether on-off ramps are specified
|
||||
if (oc.isSet("ramps.set")) {
|
||||
std::vector<std::string> edges = oc.getStringVector("ramps.set");
|
||||
NBNodeCont& nc = nb.getNodeCont();
|
||||
NBEdgeCont& ec = nb.getEdgeCont();
|
||||
NBDistrictCont& dc = nb.getDistrictCont();
|
||||
std::set<NBNode*, ComparatorIdLess> potOnRamps;
|
||||
for (std::vector<std::string>::iterator i = edges.begin(); i != edges.end(); ++i) {
|
||||
NBEdge* e = ec.retrieve(*i);
|
||||
if (noramps.count(*i) != 0) {
|
||||
WRITE_WARNING("Can not build ramp on edge '" + *i + "' - the edge is unsuitable.");
|
||||
continue;
|
||||
}
|
||||
if (e == nullptr) {
|
||||
WRITE_WARNING("Can not build on ramp on edge '" + *i + "' - the edge is not known.");
|
||||
continue;
|
||||
}
|
||||
NBNode* from = e->getFromNode();
|
||||
if (from->getIncomingEdges().size() == 2 && from->getOutgoingEdges().size() == 1) {
|
||||
buildOnRamp(from, nc, ec, dc, rampLength, dontSplit, true);
|
||||
potOnRamps.insert(from);
|
||||
}
|
||||
// load edge again to check offramps
|
||||
e = ec.retrieve(*i);
|
||||
if (e == nullptr) {
|
||||
WRITE_WARNING("Can not build off ramp on edge '" + *i + "' - the edge is not known.");
|
||||
continue;
|
||||
}
|
||||
NBNode* to = e->getToNode();
|
||||
if (to->getIncomingEdges().size() == 1 && to->getOutgoingEdges().size() == 2) {
|
||||
buildOffRamp(to, nc, ec, dc, rampLength, dontSplit, true, potOnRamps);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::mayNeedOnRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed, const std::set<std::string>& noramps, double minWeaveLength) {
|
||||
if (cur->getOutgoingEdges().size() != 1 || cur->getIncomingEdges().size() != 2) {
|
||||
return false;
|
||||
}
|
||||
NBEdge* potHighway, *potRamp, *cont;
|
||||
getOnRampEdges(cur, &potHighway, &potRamp, &cont);
|
||||
// may be an on-ramp
|
||||
if (fulfillsRampConstraints(potHighway, potRamp, cont, minHighwaySpeed, maxRampSpeed, noramps)) {
|
||||
// prevent short weaving section
|
||||
double seen = cont->getLength();
|
||||
while (seen < minWeaveLength) {
|
||||
if (cont->getToNode()->getOutgoingEdges().size() > 1) {
|
||||
return false;
|
||||
} else if (cont->getToNode()->getOutgoingEdges().size() == 0) {
|
||||
return true;
|
||||
}
|
||||
cont = cont->getToNode()->getOutgoingEdges().front();
|
||||
seen += cont->getLength();
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::mayNeedOffRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed, const std::set<std::string>& noramps) {
|
||||
if (cur->getIncomingEdges().size() != 1 || cur->getOutgoingEdges().size() != 2) {
|
||||
return false;
|
||||
}
|
||||
// may be an off-ramp
|
||||
NBEdge* potHighway, *potRamp, *prev;
|
||||
getOffRampEdges(cur, &potHighway, &potRamp, &prev);
|
||||
return fulfillsRampConstraints(potHighway, potRamp, prev, minHighwaySpeed, maxRampSpeed, noramps);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBRampsComputer::buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit, bool addLanes) {
|
||||
NBEdge* potHighway, *potRamp, *cont;
|
||||
getOnRampEdges(cur, &potHighway, &potRamp, &cont);
|
||||
#ifdef DEBUG_RAMPS
|
||||
if (DEBUGCOND(cur)) {
|
||||
std::cout << "buildOnRamp cur=" << cur->getID() << " hw=" << potHighway->getID() << " ramp=" << potRamp->getID() << " cont=" << cont->getID() << "\n";
|
||||
}
|
||||
#endif
|
||||
// compute the number of lanes to append
|
||||
const int firstLaneNumber = cont->getNumLanes();
|
||||
int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber;
|
||||
NBEdge* first = cont;
|
||||
NBEdge* last = cont;
|
||||
NBEdge* curr = cont;
|
||||
std::set<NBEdge*> incremented;
|
||||
if (addLanes && toAdd > 0 && std::find(incremented.begin(), incremented.end(), cont) == incremented.end()) {
|
||||
double currLength = 0;
|
||||
while (curr != nullptr && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
|
||||
if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
|
||||
curr->incLaneNo(toAdd);
|
||||
if (curr->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER) {
|
||||
curr->invalidateConnections(true);
|
||||
}
|
||||
incremented.insert(curr);
|
||||
moveRampRight(curr, toAdd);
|
||||
currLength += curr->getGeometry().length(); // !!! loaded length?
|
||||
last = curr;
|
||||
// mark acceleration lanes
|
||||
for (int i = 0; i < curr->getNumLanes() - potHighway->getNumLanes(); ++i) {
|
||||
curr->setAcceleration(i, true);
|
||||
}
|
||||
}
|
||||
NBNode* nextN = curr->getToNode();
|
||||
if (nextN->getOutgoingEdges().size() == 1 && nextN->getIncomingEdges().size() == 1) {
|
||||
curr = nextN->getOutgoingEdges()[0];
|
||||
if (curr->getNumLanes() != firstLaneNumber) {
|
||||
// the number of lanes changes along the computation; we'll stop...
|
||||
curr = nullptr;
|
||||
} else if (curr->isTurningDirectionAt(last)) {
|
||||
// turnarounds certainly should not be included in a ramp
|
||||
curr = nullptr;
|
||||
} else if (curr == potHighway || curr == potRamp) {
|
||||
// circular connectivity. do not split!
|
||||
curr = nullptr;
|
||||
}
|
||||
} else {
|
||||
// ambigous; and, in fact, what should it be? ...stop
|
||||
curr = nullptr;
|
||||
}
|
||||
}
|
||||
// check whether a further split is necessary
|
||||
if (curr != nullptr && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
|
||||
// there is enough place to build a ramp; do it
|
||||
bool wasFirst = first == curr;
|
||||
NBNode* rn = new NBNode(curr->getID() + "-AddedOnRampNode", curr->getGeometry().positionAtOffset(rampLength - currLength));
|
||||
if (!nc.insert(rn)) {
|
||||
throw ProcessError("Ups - could not build on-ramp for edge '" + curr->getID() + "' (node could not be build)!");
|
||||
}
|
||||
std::string name = curr->getID();
|
||||
bool ok = ec.splitAt(dc, curr, rn, curr->getID() + ADDED_ON_RAMP_EDGE, curr->getID(), curr->getNumLanes() + toAdd, curr->getNumLanes());
|
||||
if (!ok) {
|
||||
WRITE_ERROR("Ups - could not build on-ramp for edge '" + curr->getID() + "'!");
|
||||
return;
|
||||
}
|
||||
//ec.retrieve(name)->invalidateConnections();
|
||||
curr = ec.retrieve(name + ADDED_ON_RAMP_EDGE);
|
||||
incremented.insert(curr);
|
||||
last = curr;
|
||||
moveRampRight(curr, toAdd);
|
||||
if (wasFirst) {
|
||||
first = curr;
|
||||
}
|
||||
// mark acceleration lanes
|
||||
for (int i = 0; i < curr->getNumLanes() - potHighway->getNumLanes(); ++i) {
|
||||
curr->setAcceleration(i, true);
|
||||
}
|
||||
}
|
||||
if (curr == cont && dontSplit && addLanes) {
|
||||
WRITE_WARNING("Could not build on-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'");
|
||||
return;
|
||||
}
|
||||
} else {
|
||||
// mark acceleration lanes
|
||||
for (int i = 0; i < firstLaneNumber - potHighway->getNumLanes(); ++i) {
|
||||
cont->setAcceleration(i, true);
|
||||
}
|
||||
}
|
||||
// set connections from ramp/highway to added ramp
|
||||
if (addLanes) {
|
||||
if (potHighway->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER) {
|
||||
if (!potHighway->addLane2LaneConnections(0, first, potRamp->getNumLanes(), MIN2(first->getNumLanes() - potRamp->getNumLanes(), potHighway->getNumLanes()), NBEdge::Lane2LaneInfoType::VALIDATED, true)) {
|
||||
throw ProcessError("Could not set connection!");
|
||||
}
|
||||
}
|
||||
if (potRamp->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER) {
|
||||
if (!potRamp->addLane2LaneConnections(0, first, 0, potRamp->getNumLanes(), NBEdge::Lane2LaneInfoType::VALIDATED, true)) {
|
||||
throw ProcessError("Could not set connection!");
|
||||
}
|
||||
}
|
||||
patchRampGeometry(potRamp, first, potHighway, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBRampsComputer::buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit, bool addLanes,
|
||||
const std::set<NBNode*, ComparatorIdLess>& potOnRamps) {
|
||||
NBEdge* potHighway, *potRamp, *prev;
|
||||
getOffRampEdges(cur, &potHighway, &potRamp, &prev);
|
||||
#ifdef DEBUG_RAMPS
|
||||
if (DEBUGCOND(cur)) {
|
||||
std::cout << "buildOffRamp cur=" << cur->getID() << " hw=" << potHighway->getID() << " ramp=" << potRamp->getID() << " prev=" << prev->getID() << "\n";
|
||||
}
|
||||
#endif
|
||||
// compute the number of lanes to append
|
||||
const int firstLaneNumber = prev->getNumLanes();
|
||||
int toAdd = (potRamp->getNumLanes() + potHighway->getNumLanes()) - firstLaneNumber;
|
||||
NBEdge* first = prev;
|
||||
NBEdge* last = prev;
|
||||
NBEdge* curr = prev;
|
||||
std::set<NBEdge*> incremented;
|
||||
if (addLanes && toAdd > 0 && std::find(incremented.begin(), incremented.end(), prev) == incremented.end()) {
|
||||
double currLength = 0;
|
||||
while (curr != nullptr && currLength + curr->getGeometry().length() - POSITION_EPS < rampLength) {
|
||||
if (find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
|
||||
curr->incLaneNo(toAdd);
|
||||
if (curr->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER) {
|
||||
curr->invalidateConnections(true);
|
||||
}
|
||||
incremented.insert(curr);
|
||||
moveRampRight(curr, toAdd);
|
||||
currLength += curr->getGeometry().length(); // !!! loaded length?
|
||||
last = curr;
|
||||
}
|
||||
NBNode* prevN = curr->getFromNode();
|
||||
if (prevN->getIncomingEdges().size() == 1 && prevN->getOutgoingEdges().size() == 1) {
|
||||
curr = prevN->getIncomingEdges()[0];
|
||||
if (curr->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER && toAdd != 0) {
|
||||
// curr might be an onRamp. In this case connections need to be rebuilt
|
||||
curr->invalidateConnections();
|
||||
}
|
||||
if (curr->getNumLanes() != firstLaneNumber) {
|
||||
// the number of lanes changes along the computation; we'll stop...
|
||||
curr = nullptr;
|
||||
} else if (last->isTurningDirectionAt(curr)) {
|
||||
// turnarounds certainly should not be included in a ramp
|
||||
curr = nullptr;
|
||||
} else if (curr == potHighway || curr == potRamp) {
|
||||
// circular connectivity. do not split!
|
||||
curr = nullptr;
|
||||
}
|
||||
} else {
|
||||
// ambigous; and, in fact, what should it be? ...stop
|
||||
curr = nullptr;
|
||||
}
|
||||
}
|
||||
// check whether a further split is necessary
|
||||
if (curr != nullptr && !dontSplit && currLength - POSITION_EPS < rampLength && curr->getNumLanes() == firstLaneNumber && std::find(incremented.begin(), incremented.end(), curr) == incremented.end()) {
|
||||
// there is enough place to build a ramp; do it
|
||||
bool wasFirst = first == curr;
|
||||
Position pos = curr->getGeometry().positionAtOffset(curr->getGeometry().length() - (rampLength - currLength));
|
||||
NBNode* rn = new NBNode(curr->getID() + "-AddedOffRampNode", pos);
|
||||
if (!nc.insert(rn)) {
|
||||
throw ProcessError("Ups - could not build off-ramp for edge '" + curr->getID() + "' (node could not be build)!");
|
||||
}
|
||||
std::string name = curr->getID();
|
||||
bool ok = ec.splitAt(dc, curr, rn, curr->getID(), curr->getID() + "-AddedOffRampEdge", curr->getNumLanes(), curr->getNumLanes() + toAdd);
|
||||
if (!ok) {
|
||||
WRITE_ERROR("Ups - could not build off-ramp for edge '" + curr->getID() + "'!");
|
||||
return;
|
||||
}
|
||||
curr = ec.retrieve(name + "-AddedOffRampEdge");
|
||||
incremented.insert(curr);
|
||||
last = curr;
|
||||
moveRampRight(curr, toAdd);
|
||||
if (wasFirst) {
|
||||
first = curr;
|
||||
}
|
||||
}
|
||||
if (curr == prev && dontSplit && addLanes) {
|
||||
WRITE_WARNING("Could not build off-ramp for edge '" + curr->getID() + "' due to option '--ramps.no-split'");
|
||||
return;
|
||||
}
|
||||
}
|
||||
NBEdge* toMark = first;
|
||||
toMark->markOffRamp(true);
|
||||
double markedLength = toMark->getLoadedLength();
|
||||
while (markedLength < OFFRAMP_LOOKBACK) {
|
||||
if (toMark != first && toMark->getToNode()->getOutgoingEdges().size() != 1) {
|
||||
break;
|
||||
}
|
||||
NBNode* from = toMark->getFromNode();
|
||||
if (from->getIncomingEdges().size() == 1) {
|
||||
toMark = from->getIncomingEdges()[0];
|
||||
} else if (potOnRamps.count(from) == 1) {
|
||||
NBEdge* potOnRamp, *cont;
|
||||
getOnRampEdges(from, &toMark, &potOnRamp, &cont);
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
toMark->markOffRamp(true);
|
||||
markedLength += toMark->getLoadedLength();
|
||||
}
|
||||
// set connections from added ramp to ramp/highway
|
||||
if (addLanes) {
|
||||
if (first->getStep() < NBEdge::EdgeBuildingStep::LANES2LANES_USER) {
|
||||
if (!first->addLane2LaneConnections(potRamp->getNumLanes(), potHighway, 0, MIN2(first->getNumLanes() - 1, potHighway->getNumLanes()), NBEdge::Lane2LaneInfoType::VALIDATED, true)) {
|
||||
throw ProcessError("Could not set connection!");
|
||||
}
|
||||
if (!first->addLane2LaneConnections(0, potRamp, 0, potRamp->getNumLanes(), NBEdge::Lane2LaneInfoType::VALIDATED, false)) {
|
||||
throw ProcessError("Could not set connection!");
|
||||
}
|
||||
}
|
||||
patchRampGeometry(potRamp, first, potHighway, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBRampsComputer::moveRampRight(NBEdge* ramp, int addedLanes) {
|
||||
if (ramp->getLaneSpreadFunction() != LaneSpreadFunction::CENTER) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
PositionVector g = ramp->getGeometry();
|
||||
const double offset = (0.5 * addedLanes *
|
||||
(ramp->getLaneWidth() == NBEdge::UNSPECIFIED_WIDTH ? SUMO_const_laneWidth : ramp->getLaneWidth()));
|
||||
g.move2side(offset);
|
||||
ramp->setGeometry(g);
|
||||
} catch (InvalidArgument&) {
|
||||
WRITE_WARNING("For edge '" + ramp->getID() + "': could not compute shape.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::determinedBySpeed(NBEdge** potHighway, NBEdge** potRamp) {
|
||||
if (fabs((*potHighway)->getSpeed() - (*potRamp)->getSpeed()) < .1) {
|
||||
return false;
|
||||
}
|
||||
if ((*potHighway)->getSpeed() < (*potRamp)->getSpeed()) {
|
||||
std::swap(*potHighway, *potRamp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::determinedByLaneNumber(NBEdge** potHighway, NBEdge** potRamp) {
|
||||
if ((*potHighway)->getNumLanes() == (*potRamp)->getNumLanes()) {
|
||||
return false;
|
||||
}
|
||||
if ((*potHighway)->getNumLanes() < (*potRamp)->getNumLanes()) {
|
||||
std::swap(*potHighway, *potRamp);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBRampsComputer::getOnRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other) {
|
||||
*other = n->getOutgoingEdges()[0];
|
||||
const std::vector<NBEdge*>& edges = n->getIncomingEdges();
|
||||
assert(edges.size() == 2);
|
||||
*potHighway = edges[0];
|
||||
*potRamp = edges[1];
|
||||
/*
|
||||
// heuristic: highway is faster than ramp
|
||||
if(determinedBySpeed(potHighway, potRamp)) {
|
||||
return;
|
||||
}
|
||||
// heuristic: highway has more lanes than ramp
|
||||
if(determinedByLaneNumber(potHighway, potRamp)) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// heuristic: ramp comes from right
|
||||
if (NBContHelper::relative_incoming_edge_sorter(*other)(*potRamp, *potHighway)) {
|
||||
std::swap(*potHighway, *potRamp);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBRampsComputer::getOffRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other) {
|
||||
*other = n->getIncomingEdges()[0];
|
||||
const std::vector<NBEdge*>& edges = n->getOutgoingEdges();
|
||||
*potHighway = edges[0];
|
||||
*potRamp = edges[1];
|
||||
assert(edges.size() == 2);
|
||||
/*
|
||||
// heuristic: highway is faster than ramp
|
||||
if(determinedBySpeed(potHighway, potRamp)) {
|
||||
return;
|
||||
}
|
||||
// heuristic: highway has more lanes than ramp
|
||||
if(determinedByLaneNumber(potHighway, potRamp)) {
|
||||
return;
|
||||
}
|
||||
*/
|
||||
// heuristic: ramp goes to right
|
||||
const std::vector<NBEdge*>& edges2 = n->getEdges();
|
||||
#ifdef DEBUG_RAMPS
|
||||
if (DEBUGCOND(n)) {
|
||||
std::cout << " edges=" << toString(edges) << " edges2=" << toString(edges2) << "\n";
|
||||
}
|
||||
#endif
|
||||
std::vector<NBEdge*>::const_iterator i = std::find(edges2.begin(), edges2.end(), *other);
|
||||
NBContHelper::nextCW(edges2, i);
|
||||
if ((*i) == *potRamp) {
|
||||
std::swap(*potHighway, *potRamp);
|
||||
}
|
||||
// the following would be better but runs afoul of misleading angles when both edges
|
||||
// have the same geometry start point but different references lanes are
|
||||
// chosen for NBEdge::computeAngle()
|
||||
//if (NBContHelper::relative_outgoing_edge_sorter(*other)(*potHighway, *potRamp)) {
|
||||
// std::swap(*potHighway, *potRamp);
|
||||
//}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::fulfillsRampConstraints(
|
||||
NBEdge* potHighway, NBEdge* potRamp, NBEdge* other, double minHighwaySpeed, double maxRampSpeed,
|
||||
const std::set<std::string>& noramps) {
|
||||
// check modes that are not appropriate for rampsdo not build ramps on rail edges
|
||||
if (hasWrongMode(potHighway) || hasWrongMode(potRamp) || hasWrongMode(other)) {
|
||||
return false;
|
||||
}
|
||||
// do not build ramps at traffic lights
|
||||
if (NBNode::isTrafficLight(potRamp->getToNode()->getType())) {
|
||||
return false;
|
||||
}
|
||||
// do not build ramps on connectors
|
||||
if (potHighway->isMacroscopicConnector() || potRamp->isMacroscopicConnector() || other->isMacroscopicConnector()) {
|
||||
return false;
|
||||
}
|
||||
// check whether a lane is missing
|
||||
if (potHighway->getNumLanes() + potRamp->getNumLanes() < other->getNumLanes()) {
|
||||
return false;
|
||||
}
|
||||
// is it really a highway?
|
||||
double maxSpeed = MAX3(potHighway->getSpeed(), other->getSpeed(), potRamp->getSpeed());
|
||||
if (maxSpeed < minHighwaySpeed) {
|
||||
return false;
|
||||
}
|
||||
// is any of the connections a turnaround?
|
||||
if (other->getToNode() == potHighway->getFromNode()) {
|
||||
// off ramp
|
||||
if (other->isTurningDirectionAt(potHighway) ||
|
||||
other->isTurningDirectionAt(potRamp)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
// on ramp
|
||||
if (other->isTurningDirectionAt(potHighway) ||
|
||||
other->isTurningDirectionAt(potRamp)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// are the angles between highway and other / ramp and other more or less straight?
|
||||
const NBNode* node = ((potHighway->getToNode() == potRamp->getToNode() && potHighway->getToNode() == other->getFromNode())
|
||||
? potHighway->getToNode() : potHighway->getFromNode());
|
||||
double angle = fabs(NBHelpers::relAngle(potHighway->getAngleAtNode(node), other->getAngleAtNode(node)));
|
||||
if (angle >= 60) {
|
||||
return false;
|
||||
}
|
||||
angle = fabs(NBHelpers::relAngle(potRamp->getAngleAtNode(node), other->getAngleAtNode(node)));
|
||||
if (angle >= 60) {
|
||||
return false;
|
||||
}
|
||||
/*
|
||||
if (potHighway->getSpeed() < minHighwaySpeed || other->getSpeed() < minHighwaySpeed) {
|
||||
return false;
|
||||
}
|
||||
*/
|
||||
// is it really a ramp?
|
||||
if (maxRampSpeed > 0 && maxRampSpeed < potRamp->getSpeed()) {
|
||||
return false;
|
||||
}
|
||||
if (noramps.find(other->getID()) != noramps.end()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBRampsComputer::hasWrongMode(NBEdge* edge) {
|
||||
// must allow passenger vehicles
|
||||
if ((edge->getPermissions() & SVC_PASSENGER) == 0) {
|
||||
return true;
|
||||
}
|
||||
// must not have a green verge or a lane that is only for soft modes
|
||||
for (int i = 0; i < (int)edge->getNumLanes(); ++i) {
|
||||
if ((edge->getPermissions(i) & ~(SVC_PEDESTRIAN | SVC_BICYCLE)) == 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NBRampsComputer::patchRampGeometry(NBEdge* potRamp, NBEdge* first, NBEdge* potHighway, bool onRamp) {
|
||||
// geometry of first and highway should allign on the left side
|
||||
if (first->getLaneSpreadFunction() == LaneSpreadFunction::CENTER && first->hasDefaultGeometryEndpoints()) {
|
||||
const NBNode* n = onRamp ? potHighway->getToNode() : potHighway->getFromNode();
|
||||
if (potHighway->hasDefaultGeometryEndpointAtNode(n)) {
|
||||
PositionVector p2 = first->getGeometry();
|
||||
try {
|
||||
p2.move2side((first->getNumLanes() - potHighway->getNumLanes()) * first->getLaneWidth(0) * 0.5);
|
||||
first->setGeometry(p2);
|
||||
} catch (InvalidArgument&) {}
|
||||
}
|
||||
}
|
||||
|
||||
// ramp should merge smoothly with first
|
||||
PositionVector p = potRamp->getGeometry();
|
||||
double offset = 0;
|
||||
int firstIndex = MAX2(0, MIN2(potRamp->getNumLanes(), first->getNumLanes()) - 1);
|
||||
if (potRamp->getLaneSpreadFunction() == LaneSpreadFunction::RIGHT) {
|
||||
offset = -first->getLaneWidth(firstIndex) / 2;
|
||||
} else {
|
||||
if (firstIndex % 2 == 1) {
|
||||
// even number of lanes
|
||||
offset = -first->getLaneWidth(firstIndex / 2) / 2;
|
||||
}
|
||||
firstIndex /= 2; // integer division
|
||||
}
|
||||
// reset lane shape (might be affected by earlier junctions.join step. see #947)
|
||||
first->resetLaneShapes();
|
||||
PositionVector l = first->getLaneShape(firstIndex);
|
||||
try {
|
||||
l.move2side(offset);
|
||||
} catch (InvalidArgument&) {}
|
||||
//std::cout << " ramp=" << potRamp->getID() << " firstIndex=" << firstIndex << " offset=" << offset << " l=" << l << "\n";
|
||||
|
||||
if (onRamp) {
|
||||
p[0] = l[-1];
|
||||
} else {
|
||||
p.pop_back();
|
||||
p.push_back(l[0]);
|
||||
}
|
||||
potRamp->setGeometry(p);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,139 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2012-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBAlgorithms_Ramps.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @date 29. March 2012
|
||||
///
|
||||
// Algorithms for highway on-/off-ramps computation
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBNetBuilder;
|
||||
class OptionsCont;
|
||||
class NBNode;
|
||||
class NBEdgeCont;
|
||||
class NBDistrictCont;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
// ---------------------------------------------------------------------------
|
||||
// NBAlgorithms_Ramps
|
||||
// ---------------------------------------------------------------------------
|
||||
/* @class NBRampsComputer
|
||||
* @brief Computes highway on-/off-ramps (if wished)
|
||||
*/
|
||||
class NBRampsComputer {
|
||||
public:
|
||||
/** @brief Computes highway on-/off-ramps (if wished)
|
||||
* @param[in, changed] nb The network builder which contains the current network representation
|
||||
* @param[in] oc The options container
|
||||
*/
|
||||
static void computeRamps(NBNetBuilder& nb, OptionsCont& oc);
|
||||
|
||||
/// @brief suffix for newly generated on-ramp edges
|
||||
static const std::string ADDED_ON_RAMP_EDGE;
|
||||
|
||||
private:
|
||||
/** @brief Determines whether the given node may be an on-ramp begin
|
||||
* @param[in] cur The node to check
|
||||
* @param[in] minHighwaySpeed The minimum speed limit a highway must have for being a highway
|
||||
* @param[in] maxRampSpeed The maximum speed limit a ramp must have for being a ramp
|
||||
* @param[in] noramps Edges that shall not be treated as ramps
|
||||
* @param[in] minWeaveLength The minimum length for weaving areas
|
||||
* @return Whether the node is assumed to be an on-ramp begin
|
||||
*/
|
||||
static bool mayNeedOnRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed,
|
||||
const std::set<std::string>& noramps, double minWeaveLength);
|
||||
|
||||
|
||||
/** @brief Determines whether the given node may be an off-ramp end
|
||||
* @param[in] cur The node to check
|
||||
* @param[in] minHighwaySpeed The minimum speed limit a highway must have for being a highway
|
||||
* @param[in] maxRampSpeed The maximum speed limit a ramp must have for being a ramp
|
||||
* @param[in] noramps Edges that shall not be treated as ramps
|
||||
* @return Whether the node is assumed to be an off-ramp end
|
||||
*/
|
||||
static bool mayNeedOffRamp(NBNode* cur, double minHighwaySpeed, double maxRampSpeed,
|
||||
const std::set<std::string>& noramps);
|
||||
|
||||
|
||||
/** @brief Builds an on-ramp starting at the given node
|
||||
* @param[in] cur The node at which the on-ramp shall begin
|
||||
* @param[in] nc The container of nodes
|
||||
* @param[in] ec The container of edges
|
||||
* @param[in] dc The container of districts
|
||||
* @param[in] rampLength The wished ramp length
|
||||
* @param[in] dontSplit Whether no edges shall be split
|
||||
* @param[in, filled] incremented The list of edges which lane number was already incremented
|
||||
*/
|
||||
static void buildOnRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit, bool addLanes);
|
||||
|
||||
|
||||
/** @brief Builds an off-ramp ending at the given node
|
||||
* @param[in] cur The node at which the off-ramp shall end
|
||||
* @param[in] nc The container of nodes
|
||||
* @param[in] ec The container of edges
|
||||
* @param[in] dc The container of districts
|
||||
* @param[in] rampLength The wished ramp length
|
||||
* @param[in] dontSplit Whether no edges shall be split
|
||||
* @param[in, filled] incremented The list of edges which lane number was already incremented
|
||||
*/
|
||||
static void buildOffRamp(NBNode* cur, NBNodeCont& nc, NBEdgeCont& ec, NBDistrictCont& dc, double rampLength, bool dontSplit, bool addLanes,
|
||||
const std::set<NBNode*, ComparatorIdLess>& potOnRamps);
|
||||
|
||||
|
||||
static void getOnRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other);
|
||||
static void getOffRampEdges(NBNode* n, NBEdge** potHighway, NBEdge** potRamp, NBEdge** other);
|
||||
static bool determinedBySpeed(NBEdge** potHighway, NBEdge** potRamp);
|
||||
static bool determinedByLaneNumber(NBEdge** potHighway, NBEdge** potRamp);
|
||||
|
||||
/** @brief Checks whether an on-/off-ramp can be bult here
|
||||
*
|
||||
* - none of the participating edges must be a macroscopic connector
|
||||
* - ramp+highways together must have more lanes than the continuation
|
||||
* - speeds must match the defined swells
|
||||
* @param[in] potHighway The highway part to check
|
||||
* @param[in] potRamp The ramp part to check
|
||||
* @param[in] other The successor/predecessor edge
|
||||
* @param[in] minHighwaySpeed The minimum speed limit a highway must have for being a highway
|
||||
* @param[in] maxRampSpeed The maximum speed limit a ramp must have for being a ramp
|
||||
* @param[in] noramps Edges that shall not be treated as ramps
|
||||
* @return Whether a ramp can be built here
|
||||
*/
|
||||
static bool fulfillsRampConstraints(NBEdge* potHighway, NBEdge* potRamp, NBEdge* other, double minHighwaySpeed, double maxRampSpeed,
|
||||
const std::set<std::string>& noramps);
|
||||
|
||||
|
||||
/** @brief Moves the ramp to the right, as new lanes were added
|
||||
* @param[in] ramp The ramp to move
|
||||
* @param[in] addedLanes The number of added lanes
|
||||
*/
|
||||
static void moveRampRight(NBEdge* ramp, int addedLanes);
|
||||
|
||||
/// @brief whether the edge has a mode that does not indicate a ramp edge
|
||||
static bool hasWrongMode(NBEdge* edge);
|
||||
|
||||
/// @brief shift ramp geometry to merge smoothly with the motorway
|
||||
static void patchRampGeometry(NBEdge* potRamp, NBEdge* first, NBEdge* potHighway, bool onRamp);
|
||||
};
|
|
@ -1,74 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBCapacity2Lanes.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @date Fri, 19 Jul 2002
|
||||
///
|
||||
// A helper class which computes the lane number from given capacity
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBCapacity2Lanes
|
||||
* @brief A helper class which computes the lane number from given capacity
|
||||
*
|
||||
* A helper class for the computation of the number of lanes an edge has
|
||||
* in dependence to this edge's capacity. The computation is done by the
|
||||
* (trivial) assumption, the number of lanes increases linear with the
|
||||
* number of lanes.
|
||||
*/
|
||||
class NBCapacity2Lanes {
|
||||
public:
|
||||
/** @brief Donstructor
|
||||
*
|
||||
* @param[in] divider Value for the norming divider
|
||||
*/
|
||||
NBCapacity2Lanes(double divider) : myDivider(divider) { }
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBCapacity2Lanes() { }
|
||||
|
||||
|
||||
/** @brief Returns the number of lanes computed from the given capacity
|
||||
*
|
||||
* Returns the estimated number of lanes by returning the given capacity
|
||||
* divided by the norming divider given in the constructor.
|
||||
*
|
||||
* @param[in] capacity The capacity to convert
|
||||
* @return The capacity converted to the number of lanes
|
||||
*/
|
||||
int get(double capacity) const {
|
||||
capacity /= myDivider;
|
||||
if (capacity > (int) capacity) {
|
||||
capacity += 1;
|
||||
}
|
||||
// just assure that the number of lanes is not zero
|
||||
if (capacity == 0) {
|
||||
capacity = 1;
|
||||
}
|
||||
return (int) capacity;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief The norming divider
|
||||
double myDivider;
|
||||
|
||||
};
|
|
@ -1,267 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBConnection.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// The class holds a description of a connection between two edges
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <cassert>
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBConnection.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// static members
|
||||
// ===========================================================================
|
||||
const int NBConnection::InvalidTlIndex = -1;
|
||||
const NBConnection NBConnection::InvalidConnection("invalidFrom", nullptr, "invalidTo", nullptr);
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBConnection::NBConnection(NBEdge* from, NBEdge* to) :
|
||||
myFrom(from), myTo(to),
|
||||
myFromID(from->getID()), myToID(to->getID()),
|
||||
myFromLane(-1), myToLane(-1),
|
||||
myTlIndex(InvalidTlIndex),
|
||||
myTlIndex2(InvalidTlIndex) {
|
||||
}
|
||||
|
||||
|
||||
NBConnection::NBConnection(const std::string& fromID, NBEdge* from,
|
||||
const std::string& toID, NBEdge* to) :
|
||||
myFrom(from), myTo(to),
|
||||
myFromID(fromID), myToID(toID),
|
||||
myFromLane(-1), myToLane(-1),
|
||||
myTlIndex(InvalidTlIndex),
|
||||
myTlIndex2(InvalidTlIndex) {
|
||||
}
|
||||
|
||||
|
||||
NBConnection::NBConnection(NBEdge* from, int fromLane,
|
||||
NBEdge* to, int toLane, int tlIndex, int tlIndex2) :
|
||||
myFrom(from), myTo(to),
|
||||
myFromLane(fromLane), myToLane(toLane),
|
||||
myTlIndex(tlIndex),
|
||||
myTlIndex2(tlIndex2) {
|
||||
/* @todo what should we assert here?
|
||||
assert(myFromLane<0||from->getNumLanes()>(int) myFromLane);
|
||||
assert(myToLane<0||to->getNumLanes()>(int) myToLane);
|
||||
*/
|
||||
myFromID = from != nullptr ? from->getID() : "";
|
||||
myToID = to != nullptr ? to->getID() : "";
|
||||
}
|
||||
|
||||
|
||||
NBConnection::~NBConnection() {}
|
||||
|
||||
|
||||
NBConnection::NBConnection(const NBConnection& c) :
|
||||
myFrom(c.myFrom), myTo(c.myTo),
|
||||
myFromID(c.myFromID), myToID(c.myToID),
|
||||
myFromLane(c.myFromLane), myToLane(c.myToLane),
|
||||
myTlIndex(c.myTlIndex),
|
||||
myTlIndex2(c.myTlIndex2) {
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBConnection::getFrom() const {
|
||||
return myFrom;
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBConnection::getTo() const {
|
||||
return myTo;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::replaceFrom(NBEdge* which, NBEdge* by) {
|
||||
if (myFrom == which) {
|
||||
myFrom = by;
|
||||
if (myFrom != nullptr) {
|
||||
myFromID = myFrom->getID();
|
||||
} else {
|
||||
myFromID = "invalidFrom";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::replaceFrom(NBEdge* which, int whichLane,
|
||||
NBEdge* by, int byLane) {
|
||||
if (myFrom == which && (myFromLane == whichLane || myFromLane < 0 || whichLane < 0)) {
|
||||
myFrom = by;
|
||||
if (myFrom != nullptr) {
|
||||
myFromID = myFrom->getID();
|
||||
} else {
|
||||
myFromID = "invalidFrom";
|
||||
}
|
||||
if (byLane >= 0) {
|
||||
myFromLane = byLane;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::replaceTo(NBEdge* which, NBEdge* by) {
|
||||
if (myTo == which) {
|
||||
myTo = by;
|
||||
if (myTo != nullptr) {
|
||||
myToID = myTo->getID();
|
||||
} else {
|
||||
myToID = "invalidTo";
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::replaceTo(NBEdge* which, int whichLane,
|
||||
NBEdge* by, int byLane) {
|
||||
if (myTo == which && (myToLane == whichLane || myFromLane < 0 || whichLane < 0)) {
|
||||
myTo = by;
|
||||
if (myTo != nullptr) {
|
||||
myToID = myTo->getID();
|
||||
} else {
|
||||
myToID = "invalidTo";
|
||||
}
|
||||
if (byLane >= 0) {
|
||||
myToLane = byLane;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
operator<(const NBConnection& c1, const NBConnection& c2) {
|
||||
if (c1.myFromID != c2.myFromID) {
|
||||
return c1.myFromID < c2.myFromID;
|
||||
}
|
||||
if (c1.myToID != c2.myToID) {
|
||||
return c1.myToID < c2.myToID;
|
||||
}
|
||||
if (c1.myFromLane != c2.myFromLane) {
|
||||
return c1.myFromLane < c2.myFromLane;
|
||||
}
|
||||
return c1.myToLane < c2.myToLane;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::operator==(const NBConnection& c) const {
|
||||
return (myFrom == c.myFrom && myTo == c.myTo &&
|
||||
myFromID == c.myFromID && myToID == c.myToID &&
|
||||
myFromLane == c.myFromLane && myToLane == c.myToLane &&
|
||||
myTlIndex == c.myTlIndex &&
|
||||
myTlIndex2 == c.myTlIndex2);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBConnection::check(const NBEdgeCont& ec) {
|
||||
myFrom = checkFrom(ec);
|
||||
myTo = checkTo(ec);
|
||||
return myFrom != nullptr && myTo != nullptr;
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBConnection::checkFrom(const NBEdgeCont& ec) {
|
||||
NBEdge* e = ec.retrieve(myFromID);
|
||||
// ok, the edge was not changed
|
||||
if (e == myFrom) {
|
||||
return myFrom;
|
||||
}
|
||||
// try to get the edge
|
||||
return ec.retrievePossiblySplit(myFromID, myToID, true);
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBConnection::checkTo(const NBEdgeCont& ec) {
|
||||
NBEdge* e = ec.retrieve(myToID);
|
||||
// ok, the edge was not changed
|
||||
if (e == myTo) {
|
||||
return myTo;
|
||||
}
|
||||
// try to get the edge
|
||||
return ec.retrievePossiblySplit(myToID, myFromID, false);
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
NBConnection::getID() const {
|
||||
std::stringstream str;
|
||||
str << myFromID << "_" << myFromLane << "->" << myToID << "_" << myToLane;
|
||||
return str.str();
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBConnection::getFromLane() const {
|
||||
return myFromLane;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBConnection::getToLane() const {
|
||||
return myToLane;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBConnection::shiftLaneIndex(NBEdge* edge, int offset, int threshold) {
|
||||
if (myFrom == edge && myFromLane > threshold) {
|
||||
myFromLane += offset;
|
||||
} else if (myTo == edge && myToLane > threshold) {
|
||||
myToLane += offset;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const NBConnection& c) {
|
||||
os
|
||||
<< "Con(from=" << Named::getIDSecure(c.getFrom())
|
||||
<< " fromLane=" << c.getFromLane()
|
||||
<< " to=" << Named::getIDSecure(c.getTo())
|
||||
<< " toLane=" << c.getToLane()
|
||||
<< " tlIndex=" << c.getTLIndex()
|
||||
<< ")";
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,147 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBConnection.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Sascha Krieg
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// The class holds a description of a connection between two edges
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include "NBEdge.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBNode;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBConnection
|
||||
*/
|
||||
class NBConnection {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
NBConnection(NBEdge* from, NBEdge* to);
|
||||
|
||||
/// @brief Constructor
|
||||
NBConnection(NBEdge* from, int fromLane, NBEdge* to, int toLane, int tlIndex = InvalidTlIndex, int tlIndex2 = InvalidTlIndex);
|
||||
|
||||
/// @brief Constructor
|
||||
NBConnection(const std::string& fromID, NBEdge* from,
|
||||
const std::string& toID, NBEdge* to);
|
||||
|
||||
/// @brief Constructor
|
||||
NBConnection(const NBConnection& c);
|
||||
|
||||
/// @brief Destructor
|
||||
virtual ~NBConnection();
|
||||
|
||||
/// @brief returns the from-edge (start of the connection)
|
||||
NBEdge* getFrom() const;
|
||||
|
||||
/// @brief returns the to-edge (end of the connection)
|
||||
NBEdge* getTo() const;
|
||||
|
||||
/// @brief replaces the from-edge by the one given
|
||||
bool replaceFrom(NBEdge* which, NBEdge* by);
|
||||
|
||||
/// @brief replaces the from-edge by the one given
|
||||
bool replaceFrom(NBEdge* which, int whichLane, NBEdge* by, int byLane);
|
||||
|
||||
/// @brief replaces the to-edge by the one given
|
||||
bool replaceTo(NBEdge* which, NBEdge* by);
|
||||
|
||||
/// @brief replaces the to-edge by the one given
|
||||
bool replaceTo(NBEdge* which, int whichLane, NBEdge* by, int byLane);
|
||||
|
||||
/** @brief patches lane indices refering to the given edge and above the
|
||||
* threshold by the given offset */
|
||||
void shiftLaneIndex(NBEdge* edge, int offset, int threshold = -1);
|
||||
|
||||
/// @brief checks whether the edges are still valid
|
||||
bool check(const NBEdgeCont& ec);
|
||||
|
||||
/// @brief returns the from-lane
|
||||
int getFromLane() const;
|
||||
|
||||
/// @brief returns the to-lane
|
||||
int getToLane() const;
|
||||
|
||||
/// @brief returns the index within the controlling tls or InvalidTLIndex if this link is unontrolled
|
||||
int getTLIndex() const {
|
||||
return myTlIndex;
|
||||
}
|
||||
int getTLIndex2() const {
|
||||
return myTlIndex2;
|
||||
}
|
||||
|
||||
// @brief reset the tlIndex
|
||||
void setTLIndex(int tlIndex) {
|
||||
myTlIndex = tlIndex;
|
||||
}
|
||||
void setTLIndex2(int tlIndex) {
|
||||
myTlIndex2 = tlIndex;
|
||||
}
|
||||
|
||||
/// @brief returns the id of the connection (!!! not really pretty)
|
||||
std::string getID() const;
|
||||
|
||||
/// @brief Compares both connections in order to allow sorting
|
||||
friend bool operator<(const NBConnection& c1, const NBConnection& c2);
|
||||
|
||||
/// @brief Comparison operator
|
||||
bool operator==(const NBConnection& c) const;
|
||||
|
||||
/// @brief Comparison operator
|
||||
bool operator!=(const NBConnection& c) const {
|
||||
return !(*this == c);
|
||||
}
|
||||
|
||||
/// @brief Output operator
|
||||
friend std::ostream& operator<<(std::ostream& os, const NBConnection& c);
|
||||
|
||||
const static int InvalidTlIndex;
|
||||
const static NBConnection InvalidConnection;
|
||||
|
||||
private:
|
||||
/// @brief Checks whether the from-edge is still valid
|
||||
NBEdge* checkFrom(const NBEdgeCont& ec);
|
||||
|
||||
/// @brief Checks whether the to-edge is still valid
|
||||
NBEdge* checkTo(const NBEdgeCont& ec);
|
||||
|
||||
private:
|
||||
/// @brief The from- and the to-edges
|
||||
NBEdge* myFrom, *myTo;
|
||||
|
||||
/// @brief The names of both edges, needed for verification of validity
|
||||
std::string myFromID, myToID;
|
||||
|
||||
/// @brief The lanes; may be -1 if no certain lane was specified
|
||||
int myFromLane, myToLane;
|
||||
|
||||
// @brief the index within the controlling tls if this connection is tls-controlled
|
||||
int myTlIndex;
|
||||
/// @brief The index of the internal junction within the controlling traffic light (optional)
|
||||
int myTlIndex2;
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBConnectionDefs.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// Some container for connections
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "NBConnection.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// definitions
|
||||
// ===========================================================================
|
||||
/// Definition of a connection vector
|
||||
typedef std::vector<NBConnection> NBConnectionVector;
|
||||
|
||||
|
||||
/** @brief Definition of a container for connection block dependencies
|
||||
Includes a list of all connections which prohibit the key connection */
|
||||
typedef std::map<NBConnection, NBConnectionVector> NBConnectionProhibits;
|
|
@ -1,54 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBCont.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @date Mon, 17 Dec 2001
|
||||
///
|
||||
// Some typedef definitions fir containers
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utils/common/Named.h>
|
||||
|
||||
#include <config.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBEdge;
|
||||
class NBNode;
|
||||
class NBRouterEdge;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// container definitions
|
||||
// ===========================================================================
|
||||
/// @brief container for (sorted) edges
|
||||
typedef std::vector<NBEdge*> EdgeVector;
|
||||
typedef std::vector<NBRouterEdge*> RouterEdgeVector;
|
||||
typedef std::vector<const NBRouterEdge*> ConstRouterEdgeVector;
|
||||
|
||||
typedef std::vector<std::pair<const NBRouterEdge*, const NBRouterEdge*> > ConstRouterEdgePairVector;
|
||||
typedef std::vector<std::pair<const NBRouterEdge*, const NBRouterEdge*> > NBViaSuccessor;
|
||||
|
||||
/// @brief container for unique edges
|
||||
typedef std::set<NBEdge*> EdgeSet;
|
||||
|
||||
typedef std::set<NBNode*, ComparatorIdLess> NodeSet;
|
||||
|
||||
/// @brief container for (sorted) lanes. The lanes are sorted from rightmost (id=0) to leftmost (id=nolanes-1)
|
||||
typedef std::vector<int> LaneVector;
|
|
@ -1,286 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBContHelper.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// Some methods for traversing lists of edges
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <cassert>
|
||||
#include "NBContHelper.h"
|
||||
#include <utils/geom/GeomHelper.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
/* -------------------------------------------------------------------------
|
||||
* utility methods
|
||||
* ----------------------------------------------------------------------- */
|
||||
void
|
||||
NBContHelper::nextCW(const EdgeVector& edges, EdgeVector::const_iterator& from) {
|
||||
from++;
|
||||
if (from == edges.end()) {
|
||||
from = edges.begin();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBContHelper::nextCCW(const EdgeVector& edges, EdgeVector::const_iterator& from) {
|
||||
if (from == edges.begin()) {
|
||||
from = edges.end() - 1;
|
||||
} else {
|
||||
--from;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::ostream&
|
||||
NBContHelper::out(std::ostream& os, const std::vector<bool>& v) {
|
||||
for (std::vector<bool>::const_iterator i = v.begin(); i != v.end(); i++) {
|
||||
os << *i;
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
NBEdge*
|
||||
NBContHelper::findConnectingEdge(const EdgeVector& edges,
|
||||
NBNode* from, NBNode* to) {
|
||||
for (EdgeVector::const_iterator i = edges.begin(); i != edges.end(); i++) {
|
||||
if ((*i)->getToNode() == to && (*i)->getFromNode() == from) {
|
||||
return *i;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
|
||||
double
|
||||
NBContHelper::maxSpeed(const EdgeVector& ev) {
|
||||
assert(ev.size() > 0);
|
||||
double max = (*(ev.begin()))->getSpeed();
|
||||
for (EdgeVector::const_iterator i = ev.begin() + 1; i != ev.end(); i++) {
|
||||
max =
|
||||
max > (*i)->getSpeed()
|
||||
? max : (*i)->getSpeed();
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* methods from node_with_incoming_finder
|
||||
* ----------------------------------------------------------------------- */
|
||||
NBContHelper::node_with_incoming_finder::node_with_incoming_finder(const NBEdge* const e)
|
||||
: myEdge(e) {}
|
||||
|
||||
|
||||
bool
|
||||
NBContHelper::node_with_incoming_finder::operator()(const NBNode* const n) const {
|
||||
const EdgeVector& incoming = n->getIncomingEdges();
|
||||
return std::find(incoming.begin(), incoming.end(), myEdge) != incoming.end();
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* methods from node_with_outgoing_finder
|
||||
* ----------------------------------------------------------------------- */
|
||||
NBContHelper::node_with_outgoing_finder::node_with_outgoing_finder(const NBEdge* const e)
|
||||
: myEdge(e) {}
|
||||
|
||||
|
||||
bool
|
||||
NBContHelper::node_with_outgoing_finder::operator()(const NBNode* const n) const {
|
||||
const EdgeVector& outgoing = n->getOutgoingEdges();
|
||||
return std::find(outgoing.begin(), outgoing.end(), myEdge) != outgoing.end();
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* methods from edge_with_destination_finder
|
||||
* ----------------------------------------------------------------------- */
|
||||
NBContHelper::edge_with_destination_finder::edge_with_destination_finder(NBNode* dest)
|
||||
: myDestinationNode(dest) {}
|
||||
|
||||
|
||||
bool
|
||||
NBContHelper::edge_with_destination_finder::operator()(NBEdge* e) const {
|
||||
return e->getToNode() == myDestinationNode;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* methods from relative_outgoing_edge_sorter
|
||||
* ----------------------------------------------------------------------- */
|
||||
bool
|
||||
NBContHelper::relative_outgoing_edge_sorter::operator()(const NBEdge* e1, const NBEdge* e2) const {
|
||||
assert(e1 != nullptr && e2 != nullptr);
|
||||
double relAngle1 = NBHelpers::normRelAngle(myAngle, e1->getStartAngle());
|
||||
double relAngle2 = NBHelpers::normRelAngle(myAngle, e2->getStartAngle());
|
||||
const double length1 = e1->getGeometry().length2D();
|
||||
const double length2 = e2->getGeometry().length2D();
|
||||
|
||||
double lookAhead = 2 * NBEdge::ANGLE_LOOKAHEAD;
|
||||
while (fabs(relAngle1 - relAngle2) < 3.0) {
|
||||
// look at further geometry segments to resolve ambiguity
|
||||
const double offset1 = MAX2(0.0, MIN2(length1, lookAhead));
|
||||
const double offset2 = MAX2(0.0, MIN2(length2, lookAhead));
|
||||
const Position referencePos1 = e1->getGeometry().positionAtOffset2D(offset1);
|
||||
const Position referencePos2 = e2->getGeometry().positionAtOffset2D(offset2);
|
||||
const double angle1 = GeomHelper::legacyDegree(e1->getFromNode()->getPosition().angleTo2D(referencePos1), true);
|
||||
const double angle2 = GeomHelper::legacyDegree(e2->getFromNode()->getPosition().angleTo2D(referencePos2), true);
|
||||
relAngle1 = NBHelpers::normRelAngle(myAngle, angle1);
|
||||
relAngle2 = NBHelpers::normRelAngle(myAngle, angle2);
|
||||
if (lookAhead > MAX2(length1, length2)) {
|
||||
break;
|
||||
}
|
||||
lookAhead *= 2;
|
||||
}
|
||||
if (fabs(relAngle1 - relAngle2) < NUMERICAL_EPS) {
|
||||
// need to break ties for windows debug version, numerical id may be -1 for both
|
||||
return e1->getID() > e2->getID();
|
||||
}
|
||||
return relAngle1 > relAngle2;
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* methods from relative_incoming_edge_sorter
|
||||
* ----------------------------------------------------------------------- */
|
||||
bool
|
||||
NBContHelper::relative_incoming_edge_sorter::operator()(const NBEdge* e1, const NBEdge* e2) const {
|
||||
assert(e1 != nullptr && e2 != nullptr);
|
||||
double relAngle1 = NBHelpers::normRelAngle(myAngle, e1->getEndAngle());
|
||||
double relAngle2 = NBHelpers::normRelAngle(myAngle, e2->getEndAngle());
|
||||
const double length1 = e1->getGeometry().length2D();
|
||||
const double length2 = e2->getGeometry().length2D();
|
||||
|
||||
double lookAhead = 2 * NBEdge::ANGLE_LOOKAHEAD;
|
||||
while (fabs(relAngle1 - relAngle2) < 3.0) {
|
||||
// look at further geometry segments to resolve ambiguity
|
||||
const double offset1 = MAX2(0.0, MIN2(length1, length1 - lookAhead));
|
||||
const double offset2 = MAX2(0.0, MIN2(length2, length2 - lookAhead));
|
||||
const Position referencePos1 = e1->getGeometry().positionAtOffset2D(offset1);
|
||||
const Position referencePos2 = e2->getGeometry().positionAtOffset2D(offset2);
|
||||
const double angle1 = GeomHelper::legacyDegree(referencePos1.angleTo2D(e1->getToNode()->getPosition()), true);
|
||||
const double angle2 = GeomHelper::legacyDegree(referencePos2.angleTo2D(e2->getToNode()->getPosition()), true);
|
||||
relAngle1 = NBHelpers::normRelAngle(myAngle, angle1);
|
||||
relAngle2 = NBHelpers::normRelAngle(myAngle, angle2);
|
||||
if (lookAhead > MAX2(length1, length2)) {
|
||||
break;
|
||||
}
|
||||
lookAhead *= 2;
|
||||
}
|
||||
if (fabs(relAngle1 - relAngle2) < NUMERICAL_EPS) {
|
||||
// need to break ties for windows debug version, numerical id may be -1 for both
|
||||
return e1->getID() > e2->getID();
|
||||
}
|
||||
return relAngle1 > relAngle2;
|
||||
}
|
||||
|
||||
|
||||
std::ostream&
|
||||
operator<<(std::ostream& os, const EdgeVector& ev) {
|
||||
for (EdgeVector::const_iterator i = ev.begin(); i != ev.end(); i++) {
|
||||
if (i != ev.begin()) {
|
||||
os << ", ";
|
||||
}
|
||||
os << (*i)->getID();
|
||||
}
|
||||
return os;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBContHelper::getMaxSpeed(const EdgeVector& edges) {
|
||||
if (edges.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
double ret = (*(edges.begin()))->getSpeed();
|
||||
for (EdgeVector::const_iterator i = edges.begin() + 1; i != edges.end(); i++) {
|
||||
if ((*i)->getSpeed() > ret) {
|
||||
ret = (*i)->getSpeed();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBContHelper::getMinSpeed(const EdgeVector& edges) {
|
||||
if (edges.size() == 0) {
|
||||
return -1;
|
||||
}
|
||||
double ret = (*(edges.begin()))->getSpeed();
|
||||
for (EdgeVector::const_iterator i = edges.begin() + 1; i != edges.end(); i++) {
|
||||
if ((*i)->getSpeed() < ret) {
|
||||
ret = (*i)->getSpeed();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBContHelper::edge_by_angle_to_nodeShapeCentroid_sorter::operator()(const NBEdge* e1, const NBEdge* e2) const {
|
||||
assert(e1->getFromNode() == myNode || e1->getToNode() == myNode);
|
||||
assert(e2->getFromNode() == myNode || e2->getToNode() == myNode);
|
||||
const double angle1 = e1->getAngleAtNodeToCenter(myNode);
|
||||
const double angle2 = e2->getAngleAtNodeToCenter(myNode);
|
||||
const double absDiff = fabs(angle1 - angle2);
|
||||
|
||||
// cannot trust the angle difference hence a heuristic:
|
||||
if (absDiff < 2 || absDiff > (360 - 2)) {
|
||||
const bool sameDir = ((e1->getFromNode() == myNode && e2->getFromNode() == myNode)
|
||||
|| (e1->getToNode() == myNode && e2->getToNode() == myNode));
|
||||
if (sameDir) {
|
||||
// put edges that allow pedestrians on the 'outside', but be aware if both allow / disallow
|
||||
const bool e1Peds = (e1->getPermissions() & SVC_PEDESTRIAN) != 0;
|
||||
const bool e2Peds = (e2->getPermissions() & SVC_PEDESTRIAN) != 0;
|
||||
if (e1->getToNode() == myNode) {
|
||||
if (e1Peds && !e2Peds) {
|
||||
return true;
|
||||
} else if (!e1Peds && e2Peds) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!e1Peds && e2Peds) {
|
||||
return true;
|
||||
} else if (e1Peds && !e2Peds) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// break ties to ensure strictly weak ordering
|
||||
return e1->getID() < e2->getID();
|
||||
} else {
|
||||
// sort incoming before outgoing, no need to break ties here
|
||||
return e1->getToNode() == myNode;
|
||||
}
|
||||
}
|
||||
return angle1 < angle2;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,414 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBContHelper.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Mon, 17 Dec 2001
|
||||
///
|
||||
// Some methods for traversing lists of edges
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
#include <cassert>
|
||||
#include "NBHelpers.h"
|
||||
#include "NBCont.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBNode.h"
|
||||
#include <utils/common/StdDefs.h>
|
||||
#include <utils/geom/GeomHelper.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* NBContHelper
|
||||
* Some static helper methods that traverse a sorted list of edges in both
|
||||
* directions
|
||||
*/
|
||||
class NBContHelper {
|
||||
public:
|
||||
/** Moves the given iterator clockwise within the given container
|
||||
of edges sorted clockwise */
|
||||
static void nextCW(const EdgeVector& edges,
|
||||
EdgeVector::const_iterator& from);
|
||||
|
||||
/** Moves the given iterator counter clockwise within the given container
|
||||
of edges sorted clockwise */
|
||||
static void nextCCW(const EdgeVector& edges,
|
||||
EdgeVector::const_iterator& from);
|
||||
|
||||
static double getMaxSpeed(const EdgeVector& edges);
|
||||
|
||||
static double getMinSpeed(const EdgeVector& edges);
|
||||
|
||||
/** writes the vector of bools to the given stream */
|
||||
static std::ostream& out(std::ostream& os, const std::vector<bool>& v);
|
||||
|
||||
|
||||
/**
|
||||
* relative_outgoing_edge_sorter
|
||||
* Class to sort edges by their angle in relation to the node the
|
||||
* edge using this class is incoming into. This is normally done to
|
||||
* sort edges outgoing from the node the using edge is incoming in
|
||||
* by their angle in relation to the using edge's angle (this angle
|
||||
* is the reference angle).
|
||||
*/
|
||||
class relative_outgoing_edge_sorter {
|
||||
public:
|
||||
/// constructor
|
||||
explicit relative_outgoing_edge_sorter(NBEdge* e) : myAngle(e->getEndAngle()) {}
|
||||
/// constructor
|
||||
explicit relative_outgoing_edge_sorter(double angle) : myAngle(angle) {}
|
||||
|
||||
public:
|
||||
/// comparing operation
|
||||
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
|
||||
|
||||
private:
|
||||
/// @brief the reference angle to compare edges agains
|
||||
double myAngle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* relative_incoming_edge_sorter
|
||||
* Class to sort edges by their angle in relation to an outgoing edge.
|
||||
* This is normally done to sort edges incoming at the starting node of this edge
|
||||
* by their angle in relation to the using edge's angle (this angle
|
||||
* is the reference angle).
|
||||
*/
|
||||
class relative_incoming_edge_sorter {
|
||||
public:
|
||||
/// constructor
|
||||
explicit relative_incoming_edge_sorter(NBEdge* e) : myAngle(e->getStartAngle()) {}
|
||||
/// constructor
|
||||
explicit relative_incoming_edge_sorter(double angle) : myAngle(angle) {}
|
||||
|
||||
public:
|
||||
/// comparing operation
|
||||
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
|
||||
|
||||
private:
|
||||
/// @brief the reference angle to compare edges agains
|
||||
double myAngle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* edge_by_priority_sorter
|
||||
* Class to sort edges by their priority
|
||||
*/
|
||||
class edge_by_priority_sorter {
|
||||
public:
|
||||
/// comparing operator
|
||||
int operator()(NBEdge* e1, NBEdge* e2) const {
|
||||
if (e1->getPriority() != e2->getPriority()) {
|
||||
return e1->getPriority() > e2->getPriority();
|
||||
}
|
||||
if (e1->getSpeed() != e2->getSpeed()) {
|
||||
return e1->getSpeed() > e2->getSpeed();
|
||||
}
|
||||
return e1->getNumLanes() > e2->getNumLanes();
|
||||
}
|
||||
};
|
||||
|
||||
// ---------------------------
|
||||
|
||||
/**
|
||||
* @class edge_opposite_direction_sorter
|
||||
* @brief Class to sort edges by their angle in relation to the given edge
|
||||
*
|
||||
* The resulting sorted list has the edge in the most opposite direction
|
||||
* to the given edge as her first entry.
|
||||
*/
|
||||
class edge_opposite_direction_sorter {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] e The edge to which the sorting relates
|
||||
* @param[in] n The node to consider
|
||||
*/
|
||||
explicit edge_opposite_direction_sorter(const NBEdge* const e, const NBNode* const n, bool regardPriority) :
|
||||
myNode(n),
|
||||
myEdge(e),
|
||||
myRegardPriority(regardPriority) {
|
||||
myAngle = getEdgeAngleAt(e, n);
|
||||
}
|
||||
|
||||
/** @brief Comparing operation
|
||||
* @param[in] e1 The first edge to compare
|
||||
* @param[in] e2 The second edge to compare
|
||||
* @return Which edge is more opposite to the related one
|
||||
*/
|
||||
int operator()(NBEdge* e1, NBEdge* e2) const {
|
||||
if (!myRegardPriority || e1->getPriority() == e2->getPriority() || e1 == myEdge || e2 == myEdge) {
|
||||
return getDiff(e1) > getDiff(e2);
|
||||
} else {
|
||||
return e1->getPriority() > e2->getPriority();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
/** @brief Computes the angle difference between the related and the given edge
|
||||
* @param[in] e The edge to compare the angle difference of
|
||||
* @return The angle difference
|
||||
*/
|
||||
double getDiff(const NBEdge* const e) const {
|
||||
return fabs(GeomHelper::angleDiff(getEdgeAngleAt(e, myNode), myAngle));
|
||||
}
|
||||
|
||||
/** @brief Returns the given edge's angle at the given node
|
||||
*
|
||||
* Please note that we always consider the "outgoing direction".
|
||||
* @param[in] e The edge to which the sorting relates
|
||||
* @param[in] n The node to consider
|
||||
*/
|
||||
double getEdgeAngleAt(const NBEdge* const e, const NBNode* const n) const {
|
||||
if (e->getFromNode() == n) {
|
||||
return e->getGeometry().angleAt2D(0);
|
||||
} else {
|
||||
return e->getGeometry()[-1].angleTo2D(e->getGeometry()[-2]);
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
/// @brief The related node
|
||||
const NBNode* const myNode;
|
||||
|
||||
/// @brief the reference edge
|
||||
const NBEdge* const myEdge;
|
||||
|
||||
/// @brief The angle of the related edge at the given node
|
||||
double myAngle;
|
||||
|
||||
/// @brief Whether edge priority may override closer angles
|
||||
bool myRegardPriority;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated assignment operator
|
||||
edge_opposite_direction_sorter& operator=(const edge_opposite_direction_sorter& s);
|
||||
|
||||
};
|
||||
|
||||
// ---------------------------
|
||||
|
||||
/**
|
||||
* edge_similar_direction_sorter
|
||||
* Class to sort edges by their angle in relation to the given edge
|
||||
* The resulting list should have the edge in the most similar direction
|
||||
* to the given edge as its first entry
|
||||
*/
|
||||
class edge_similar_direction_sorter {
|
||||
public:
|
||||
/// constructor
|
||||
explicit edge_similar_direction_sorter(const NBEdge* const e, bool outgoing = true) :
|
||||
myCompareOutgoing(outgoing),
|
||||
myAngle(outgoing ? e->getShapeEndAngle() : e->getShapeStartAngle())
|
||||
{}
|
||||
|
||||
/// comparing operation
|
||||
int operator()(const NBEdge* e1, const NBEdge* e2) const {
|
||||
const double d1 = angleDiff(myCompareOutgoing ? e1->getShapeStartAngle() : e1->getShapeEndAngle(), myAngle);
|
||||
const double d2 = angleDiff(myCompareOutgoing ? e2->getShapeStartAngle() : e2->getShapeEndAngle(), myAngle);
|
||||
if (fabs(fabs(d1) - fabs(d2)) < NUMERICAL_EPS) {
|
||||
if (fabs(d1 - d2) > NUMERICAL_EPS) {
|
||||
return d1 < d2;
|
||||
} else {
|
||||
return e1->getNumericalID() < e2->getNumericalID();
|
||||
}
|
||||
}
|
||||
return fabs(d1) < fabs(d2);
|
||||
}
|
||||
|
||||
private:
|
||||
double angleDiff(const double angle1, const double angle2) const {
|
||||
double d = angle2 - angle1;
|
||||
while (d >= 180.) {
|
||||
d -= 360.;
|
||||
}
|
||||
while (d < -180.) {
|
||||
d += 360.;
|
||||
}
|
||||
return d;
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
/// the angle to find the edge with the opposite direction
|
||||
bool myCompareOutgoing;
|
||||
double myAngle;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class node_with_incoming_finder
|
||||
*/
|
||||
class node_with_incoming_finder {
|
||||
public:
|
||||
/// constructor
|
||||
node_with_incoming_finder(const NBEdge* const e);
|
||||
|
||||
bool operator()(const NBNode* const n) const;
|
||||
|
||||
private:
|
||||
const NBEdge* const myEdge;
|
||||
|
||||
private:
|
||||
/// @brief invalidated assignment operator
|
||||
node_with_incoming_finder& operator=(const node_with_incoming_finder& s);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @class node_with_outgoing_finder
|
||||
*/
|
||||
class node_with_outgoing_finder {
|
||||
public:
|
||||
/// constructor
|
||||
node_with_outgoing_finder(const NBEdge* const e);
|
||||
|
||||
bool operator()(const NBNode* const n) const;
|
||||
|
||||
private:
|
||||
const NBEdge* const myEdge;
|
||||
|
||||
private:
|
||||
/// @brief invalidated assignment operator
|
||||
node_with_outgoing_finder& operator=(const node_with_outgoing_finder& s);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
class edge_with_destination_finder {
|
||||
public:
|
||||
/// constructor
|
||||
edge_with_destination_finder(NBNode* dest);
|
||||
|
||||
bool operator()(NBEdge* e) const;
|
||||
|
||||
private:
|
||||
NBNode* myDestinationNode;
|
||||
|
||||
private:
|
||||
/// @brief invalidated assignment operator
|
||||
edge_with_destination_finder& operator=(const edge_with_destination_finder& s);
|
||||
|
||||
};
|
||||
|
||||
|
||||
/** Tries to return the first edge within the given container which
|
||||
connects both given nodes */
|
||||
static NBEdge* findConnectingEdge(const EdgeVector& edges,
|
||||
NBNode* from, NBNode* to);
|
||||
|
||||
|
||||
/** returns the maximum speed allowed on the edges */
|
||||
static double maxSpeed(const EdgeVector& ev);
|
||||
|
||||
/**
|
||||
* same_connection_edge_sorter
|
||||
* This class is used to sort edges which connect the same nodes.
|
||||
* The edges are sorted in dependence to edges connecting them. The
|
||||
* rightmost will be the first in the list; the leftmost the last one.
|
||||
*/
|
||||
class same_connection_edge_sorter {
|
||||
public:
|
||||
/// constructor
|
||||
explicit same_connection_edge_sorter() { }
|
||||
|
||||
/// comparing operation
|
||||
int operator()(NBEdge* e1, NBEdge* e2) const {
|
||||
std::pair<double, double> mm1 = getMinMaxRelAngles(e1);
|
||||
std::pair<double, double> mm2 = getMinMaxRelAngles(e2);
|
||||
if (mm1.first == mm2.first && mm1.second == mm2.second) {
|
||||
// ok, let's simply sort them arbitrarily
|
||||
return e1->getID() < e2->getID();
|
||||
}
|
||||
|
||||
assert(
|
||||
(mm1.first <= mm2.first && mm1.second <= mm2.second)
|
||||
||
|
||||
(mm1.first >= mm2.first && mm1.second >= mm2.second));
|
||||
return (mm1.first >= mm2.first && mm1.second >= mm2.second);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
std::pair<double, double> getMinMaxRelAngles(NBEdge* e) const {
|
||||
double min = 360;
|
||||
double max = 360;
|
||||
const EdgeVector& ev = e->getConnectedEdges();
|
||||
for (EdgeVector::const_iterator i = ev.begin(); i != ev.end(); ++i) {
|
||||
double angle = NBHelpers::normRelAngle(
|
||||
e->getTotalAngle(), (*i)->getTotalAngle());
|
||||
if (min == 360 || min > angle) {
|
||||
min = angle;
|
||||
}
|
||||
if (max == 360 || max < angle) {
|
||||
max = angle;
|
||||
}
|
||||
}
|
||||
return std::pair<double, double>(min, max);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
friend std::ostream& operator<<(std::ostream& os, const EdgeVector& ev);
|
||||
|
||||
class opposite_finder {
|
||||
public:
|
||||
/// constructor
|
||||
opposite_finder(NBEdge* edge)
|
||||
: myReferenceEdge(edge) { }
|
||||
|
||||
bool operator()(NBEdge* e) const {
|
||||
return e->isTurningDirectionAt(myReferenceEdge) ||
|
||||
myReferenceEdge->isTurningDirectionAt(e);
|
||||
}
|
||||
|
||||
private:
|
||||
NBEdge* myReferenceEdge;
|
||||
|
||||
};
|
||||
|
||||
/**
|
||||
* edge_by_angle_to_nodeShapeCentroid_sorter
|
||||
* Class to sort edges by their angle in relation to the node shape
|
||||
* */
|
||||
class edge_by_angle_to_nodeShapeCentroid_sorter {
|
||||
public:
|
||||
/// constructor
|
||||
explicit edge_by_angle_to_nodeShapeCentroid_sorter(const NBNode* n) : myNode(n) {}
|
||||
|
||||
public:
|
||||
/// comparing operation
|
||||
bool operator()(const NBEdge* e1, const NBEdge* e2) const;
|
||||
|
||||
private:
|
||||
/// the edge to compute the relative angle of
|
||||
const NBNode* myNode;
|
||||
};
|
||||
|
||||
};
|
|
@ -1,187 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBDistrict.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A class representing a single district
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <cassert>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <iostream>
|
||||
#include <algorithm>
|
||||
#include <utils/common/Named.h>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include "NBEdge.h"
|
||||
#include "NBDistrict.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// member method definitions
|
||||
// ===========================================================================
|
||||
NBDistrict::NBDistrict(const std::string& id, const Position& pos)
|
||||
: Named(StringUtils::convertUmlaute(id)),
|
||||
myPosition(pos) {}
|
||||
|
||||
|
||||
NBDistrict::NBDistrict(const std::string& id)
|
||||
: Named(id), myPosition(0, 0) {}
|
||||
|
||||
|
||||
NBDistrict::~NBDistrict() {}
|
||||
|
||||
|
||||
// ----------- Applying offset
|
||||
void
|
||||
NBDistrict::reshiftPosition(double xoff, double yoff) {
|
||||
myPosition.add(xoff, yoff, 0);
|
||||
myShape.add(xoff, yoff, 0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::mirrorX() {
|
||||
myPosition.mul(1, -1);
|
||||
myShape.mirrorX();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBDistrict::addSource(NBEdge* const source, double weight) {
|
||||
EdgeVector::iterator i = std::find(mySources.begin(), mySources.end(), source);
|
||||
if (i != mySources.end()) {
|
||||
return false;
|
||||
}
|
||||
mySources.push_back(source);
|
||||
mySourceWeights.push_back(weight);
|
||||
assert(source->getID() != "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBDistrict::addSink(NBEdge* const sink, double weight) {
|
||||
EdgeVector::iterator i = std::find(mySinks.begin(), mySinks.end(), sink);
|
||||
if (i != mySinks.end()) {
|
||||
return false;
|
||||
}
|
||||
mySinks.push_back(sink);
|
||||
mySinkWeights.push_back(weight);
|
||||
assert(sink->getID() != "");
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::setCenter(const Position& pos) {
|
||||
myPosition = pos;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::replaceIncoming(const EdgeVector& which, NBEdge* const by) {
|
||||
// temporary structures
|
||||
EdgeVector newList;
|
||||
WeightsCont newWeights;
|
||||
double joinedVal = 0;
|
||||
// go through the list of sinks
|
||||
EdgeVector::iterator i = mySinks.begin();
|
||||
WeightsCont::iterator j = mySinkWeights.begin();
|
||||
for (; i != mySinks.end(); i++, j++) {
|
||||
NBEdge* tmp = (*i);
|
||||
double val = (*j);
|
||||
if (find(which.begin(), which.end(), tmp) == which.end()) {
|
||||
// if the current edge shall not be replaced, add to the
|
||||
// temporary list
|
||||
newList.push_back(tmp);
|
||||
newWeights.push_back(val);
|
||||
} else {
|
||||
// otherwise, skip it and add its weight to the one to be inserted
|
||||
// instead
|
||||
joinedVal += val;
|
||||
}
|
||||
}
|
||||
// add the one to be inserted instead
|
||||
newList.push_back(by);
|
||||
newWeights.push_back(joinedVal);
|
||||
// assign to values
|
||||
mySinks = newList;
|
||||
mySinkWeights = newWeights;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::replaceOutgoing(const EdgeVector& which, NBEdge* const by) {
|
||||
// temporary structures
|
||||
EdgeVector newList;
|
||||
WeightsCont newWeights;
|
||||
double joinedVal = 0;
|
||||
// go through the list of sinks
|
||||
EdgeVector::iterator i = mySources.begin();
|
||||
WeightsCont::iterator j = mySourceWeights.begin();
|
||||
for (; i != mySources.end(); i++, j++) {
|
||||
NBEdge* tmp = (*i);
|
||||
double val = (*j);
|
||||
if (find(which.begin(), which.end(), tmp) == which.end()) {
|
||||
// if the current edge shall not be replaced, add to the
|
||||
// temporary list
|
||||
newList.push_back(tmp);
|
||||
newWeights.push_back(val);
|
||||
} else {
|
||||
// otherwise, skip it and add its weight to the one to be inserted
|
||||
// instead
|
||||
joinedVal += val;
|
||||
}
|
||||
}
|
||||
// add the one to be inserted instead
|
||||
newList.push_back(by);
|
||||
newWeights.push_back(joinedVal);
|
||||
// assign to values
|
||||
mySources = newList;
|
||||
mySourceWeights = newWeights;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::removeFromSinksAndSources(NBEdge* const e) {
|
||||
int i;
|
||||
for (i = 0; i < (int)mySinks.size(); ++i) {
|
||||
if (mySinks[i] == e) {
|
||||
mySinks.erase(mySinks.begin() + i);
|
||||
mySinkWeights.erase(mySinkWeights.begin() + i);
|
||||
}
|
||||
}
|
||||
for (i = 0; i < (int)mySources.size(); ++i) {
|
||||
if (mySources[i] == e) {
|
||||
mySources.erase(mySources.begin() + i);
|
||||
mySourceWeights.erase(mySourceWeights.begin() + i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrict::addShape(const PositionVector& p) {
|
||||
myShape = p;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,266 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBDistrict.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A class representing a single district
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include "NBCont.h"
|
||||
#include <utils/common/Named.h>
|
||||
#include <utils/common/VectorHelper.h>
|
||||
#include <utils/geom/Position.h>
|
||||
#include <utils/geom/PositionVector.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBEdge;
|
||||
class OutputDevice;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBDistrict
|
||||
* @brief A class representing a single district
|
||||
*
|
||||
* A "district" is an area within the network which may be referenced by
|
||||
* O/D-matrices. It stems from importing VISUM-networks. Work with VISUM-
|
||||
* -networks also made it necessary that a district knows the edges at
|
||||
* which new vehicles shall approach the simulated network (sources) and
|
||||
* those to use when leaving the network (sinks). These connections to the
|
||||
* network are weighted.
|
||||
*
|
||||
* Later work on VISUM required also parsing the shape of a district. This
|
||||
* information is used by some external tools only, it is even not shown
|
||||
* within the GUI.
|
||||
*
|
||||
* @todo Recheck whether this can be somehow joined with ODDistrict
|
||||
*/
|
||||
class NBDistrict : public Named {
|
||||
public:
|
||||
/** @brief Constructor with id, and position
|
||||
*
|
||||
* @param[in] id The id of the district
|
||||
* @param[in] pos The position of the district
|
||||
*/
|
||||
NBDistrict(const std::string& id, const Position& pos);
|
||||
|
||||
|
||||
/** @brief Constructor without position
|
||||
*
|
||||
* The position must be computed later
|
||||
*
|
||||
* @param[in] id The id of the district
|
||||
*/
|
||||
NBDistrict(const std::string& id);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBDistrict();
|
||||
|
||||
|
||||
/** @brief Adds a source
|
||||
*
|
||||
* It is checked whether the edge has already been added as a source. false
|
||||
* is returned in this case. Otherwise, the source is pushed into
|
||||
* the list of sources and the weight into the list of source weights.
|
||||
* both lists stay sorted this way. true is returned.
|
||||
*
|
||||
* @param[in] source An edge that shall be used as source
|
||||
* @param[in] weight The weight of the source
|
||||
* @return Whether the source could be added (was not added before)
|
||||
* @todo Consider using only one list for sources/weights
|
||||
*/
|
||||
bool addSource(NBEdge* const source, double weight);
|
||||
|
||||
|
||||
/** @brief Adds a sink
|
||||
*
|
||||
* It is checked whether the edge has already been added as a sink. false
|
||||
* is returned in this case. Otherwise, the sink is pushed into
|
||||
* the list of sink and the weight into the list of sink weights.
|
||||
* both lists stay sorted this way. true is returned.
|
||||
*
|
||||
* @param[in] sink An edge that shall be used as sink
|
||||
* @param[in] weight The weight of the sink
|
||||
* @return Whether the sink could be added (was not added before)
|
||||
* @todo Consider using only one list for sinks/weights
|
||||
*/
|
||||
bool addSink(NBEdge* const sink, double weight);
|
||||
|
||||
|
||||
/** @brief Returns the position of this district's center
|
||||
*
|
||||
* @return The position of this district's center
|
||||
* @todo Recheck when this information is set/needed
|
||||
*/
|
||||
const Position& getPosition() const {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Sets the center coordinates
|
||||
*
|
||||
* @param[in] pos The new center to assign
|
||||
* @todo Recheck when this information is set/needed
|
||||
*/
|
||||
void setCenter(const Position& pos);
|
||||
|
||||
|
||||
/** @brief Replaces incoming edges from the vector (sinks) by the given edge
|
||||
*
|
||||
* When an edge is split/joined/removed/etc., it may get necessary to replace prior
|
||||
* edges by new ones. This method replaces all occurences of the edges from
|
||||
* "which" within incoming edges (sinks) by the given edge.
|
||||
*
|
||||
* The new sink edge's weight is the sum of the weights of the replaced edges.
|
||||
*
|
||||
* @param[in] which List of edges to replace
|
||||
* @param[in] by The replacement
|
||||
*/
|
||||
void replaceIncoming(const EdgeVector& which, NBEdge* const by);
|
||||
|
||||
|
||||
/** @brief Replaces outgoing edges from the vector (source) by the given edge
|
||||
*
|
||||
* When an edge is split/joined/removed/etc., it may get necessary to replace prior
|
||||
* edges by new ones. This method replaces all occurences of the edges from
|
||||
* "which" within outgoing edges (sources) by the given edge.
|
||||
*
|
||||
* The new source edge's weight is the sum of the weights of the replaced edges.
|
||||
*
|
||||
* @param[in] which List of edges to replace
|
||||
* @param[in] by The replacement
|
||||
*/
|
||||
void replaceOutgoing(const EdgeVector& which, NBEdge* const by);
|
||||
|
||||
|
||||
/** @brief Removes the given edge from the lists of sources and sinks
|
||||
*
|
||||
* The according weights are removed, too.
|
||||
*
|
||||
* @param[in] e The edge to remove from sinks/sources
|
||||
*/
|
||||
void removeFromSinksAndSources(NBEdge* const e);
|
||||
|
||||
|
||||
/** @brief Sets the shape of this district
|
||||
*
|
||||
* @param[in] p The new shape
|
||||
*/
|
||||
void addShape(const PositionVector& p);
|
||||
|
||||
|
||||
/** @brief Returns the weights of the sources
|
||||
* @return The source weights
|
||||
*/
|
||||
const std::vector<double>& getSourceWeights() const {
|
||||
return mySourceWeights;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the sources
|
||||
* @return The source edges
|
||||
*/
|
||||
const std::vector<NBEdge*>& getSourceEdges() const {
|
||||
return mySources;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the weights of the sinks
|
||||
* @return The sink weights
|
||||
*/
|
||||
const std::vector<double>& getSinkWeights() const {
|
||||
return mySinkWeights;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the sinks
|
||||
* @return The sink edges
|
||||
*/
|
||||
const std::vector<NBEdge*>& getSinkEdges() const {
|
||||
return mySinks;
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the shape
|
||||
* @return The district's shape
|
||||
*/
|
||||
const PositionVector& getShape() const {
|
||||
return myShape;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// @name Applying offset
|
||||
/// @{
|
||||
|
||||
/** @brief Applies an offset to the district
|
||||
* @param[in] xoff The x-offset to apply
|
||||
* @param[in] yoff The y-offset to apply
|
||||
*/
|
||||
void reshiftPosition(double xoff, double yoff);
|
||||
|
||||
/// @brief mirror coordinates along the x-axis
|
||||
void mirrorX();
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
private:
|
||||
/// @brief Definition of a vector of connection weights
|
||||
typedef std::vector<double> WeightsCont;
|
||||
|
||||
/// @brief The sources (connection from district to network)
|
||||
EdgeVector mySources;
|
||||
|
||||
/// @brief The weights of the sources
|
||||
WeightsCont mySourceWeights;
|
||||
|
||||
/// @brief The sinks (connection from network to district)
|
||||
EdgeVector mySinks;
|
||||
|
||||
/// @brief The weights of the sinks
|
||||
WeightsCont mySinkWeights;
|
||||
|
||||
/// @brief The position of the district
|
||||
Position myPosition;
|
||||
|
||||
/// @brief The shape of the dsitrict
|
||||
PositionVector myShape;
|
||||
|
||||
|
||||
private:
|
||||
/** invalid copy constructor */
|
||||
NBDistrict(const NBDistrict& s);
|
||||
|
||||
/** invalid assignment operator */
|
||||
NBDistrict& operator=(const NBDistrict& s);
|
||||
|
||||
|
||||
};
|
|
@ -1,103 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBDistrictCont.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// A container for districts
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include "NBDistrict.h"
|
||||
#include "NBDistrictCont.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBDistrictCont::NBDistrictCont() {}
|
||||
|
||||
|
||||
NBDistrictCont::~NBDistrictCont() {
|
||||
for (DistrictCont::iterator i = myDistricts.begin(); i != myDistricts.end(); i++) {
|
||||
delete ((*i).second);
|
||||
}
|
||||
myDistricts.clear();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBDistrictCont::insert(NBDistrict* const district) {
|
||||
DistrictCont::const_iterator i = myDistricts.find(district->getID());
|
||||
if (i != myDistricts.end()) {
|
||||
return false;
|
||||
}
|
||||
myDistricts.insert(DistrictCont::value_type(district->getID(), district));
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NBDistrict*
|
||||
NBDistrictCont::retrieve(const std::string& id) const {
|
||||
DistrictCont::const_iterator i = myDistricts.find(id);
|
||||
if (i == myDistricts.end()) {
|
||||
return nullptr;
|
||||
}
|
||||
return (*i).second;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBDistrictCont::size() const {
|
||||
return (int)myDistricts.size();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBDistrictCont::addSource(const std::string& dist, NBEdge* const source,
|
||||
double weight) {
|
||||
NBDistrict* o = retrieve(dist);
|
||||
if (o == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return o->addSource(source, weight);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBDistrictCont::addSink(const std::string& dist, NBEdge* const destination,
|
||||
double weight) {
|
||||
NBDistrict* o = retrieve(dist);
|
||||
if (o == nullptr) {
|
||||
return false;
|
||||
}
|
||||
return o->addSink(destination, weight);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBDistrictCont::removeFromSinksAndSources(NBEdge* const e) {
|
||||
for (DistrictCont::iterator i = myDistricts.begin(); i != myDistricts.end(); i++) {
|
||||
(*i).second->removeFromSinksAndSources(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,155 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBDistrictCont.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A container for districts
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBDistrict;
|
||||
class NBEdge;
|
||||
class NBNodeCont;
|
||||
class OutputDevice;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBDistrictCont
|
||||
* @brief A container for districts
|
||||
*
|
||||
* A simple storage for district instances. Allows addition an retrieval of
|
||||
* districts, filling them with sources/sinks, and some other methods which
|
||||
* operate at all stored districts.
|
||||
*
|
||||
* @see NBDistrict
|
||||
*/
|
||||
class NBDistrictCont {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
NBDistrictCont();
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBDistrictCont();
|
||||
|
||||
|
||||
/** @brief Adds a district to the dictionary
|
||||
*
|
||||
* @param[in] district The district to add
|
||||
* @return false if the districts already was in the dictionary
|
||||
*/
|
||||
bool insert(NBDistrict* const district);
|
||||
|
||||
|
||||
/** @brief Returns the districts with the given id
|
||||
*
|
||||
* @param[in] id The id of the district to retrieve
|
||||
* @return The district with the given id if there was one having it, 0 otherwise
|
||||
*/
|
||||
NBDistrict* retrieve(const std::string& id) const;
|
||||
|
||||
|
||||
/** @brief Returns the pointer to the begin of the stored districts
|
||||
* @return The iterator to the beginning of stored edges
|
||||
*/
|
||||
std::map<std::string, NBDistrict*>::const_iterator begin() const {
|
||||
return myDistricts.begin();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the pointer to the end of the stored districts
|
||||
* @return The iterator to the end of stored edges
|
||||
*/
|
||||
std::map<std::string, NBDistrict*>::const_iterator end() const {
|
||||
return myDistricts.end();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the number of districts inside the container */
|
||||
int size() const;
|
||||
|
||||
|
||||
/** @brief Adds a source to the named district
|
||||
*
|
||||
* At first, the district is tried to be retrieved. If this fails, false is
|
||||
* returned. Otherwise the retrieved districts NBDistrict::addSource-method
|
||||
* is called.
|
||||
*
|
||||
* @see NBDistrict::addSource
|
||||
* @param[in] dist The id of the district to add the source to
|
||||
* @param[in] source An edge that shall be used as source
|
||||
* @param[in] weight An optional weight of the source
|
||||
* @return Whether the source could be added (the district exists and the suorce was not added to it before)
|
||||
*/
|
||||
bool addSource(const std::string& dist, NBEdge* const source,
|
||||
double weight);
|
||||
|
||||
|
||||
/** @brief Adds a sink to the named district
|
||||
*
|
||||
* At first, the district is tried to be retrieved. If this fails, false is
|
||||
* returned. Otherwise the retrieved districts NBDistrict::addSink-method
|
||||
* is called.
|
||||
*
|
||||
* @see NBDistrict::addSink
|
||||
* @param[in] dist The id of the district to add the sink to
|
||||
* @param[in] source An edge that shall be used as sink
|
||||
* @param[in] weight An optional weight of the source
|
||||
* @return Whether the source could be added (the district exists and the suorce was not added to it before)
|
||||
*/
|
||||
bool addSink(const std::string& dist, NBEdge* const destination,
|
||||
double weight);
|
||||
|
||||
|
||||
/** @brief Removes the given edge from the lists of sources and sinks in all stored districts
|
||||
*
|
||||
* This method simply goes through all stored districts and calls their method
|
||||
* NBDistrict::removeFromSinksAndSources.
|
||||
*
|
||||
* @see NBDistrict::removeFromSinksAndSources
|
||||
* @param[in] e The edge to remove from sinks/sources
|
||||
*/
|
||||
void removeFromSinksAndSources(NBEdge* const e);
|
||||
|
||||
|
||||
private:
|
||||
/// @brief The type of the dictionary where a node may be found by her id
|
||||
typedef std::map<std::string, NBDistrict*> DistrictCont;
|
||||
|
||||
/// @brief The instance of the dictionary
|
||||
DistrictCont myDistricts;
|
||||
|
||||
|
||||
private:
|
||||
/** invalid copy constructor */
|
||||
NBDistrictCont(const NBDistrictCont& s);
|
||||
|
||||
/** invalid assignment operator */
|
||||
NBDistrictCont& operator=(const NBDistrictCont& s);
|
||||
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -1,758 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBEdgeCont.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// Storage for edges, including some functionality operating on multiple edges
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <map>
|
||||
#include <iostream>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "NBCont.h"
|
||||
#include <utils/common/SUMOVehicleClass.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/geom/PositionVector.h>
|
||||
#include <utils/common/NamedRTree.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OptionsCont;
|
||||
class OutputDevice;
|
||||
class NBNodeCont;
|
||||
class NBTypeCont;
|
||||
class NBEdge;
|
||||
class NBNode;
|
||||
class NBDistrictCont;
|
||||
class NBTrafficLightLogicCont;
|
||||
class NBPTStopCont;
|
||||
class NBPTLineCont;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBEdgeCont
|
||||
* @brief Storage for edges, including some functionality operating on multiple edges
|
||||
*/
|
||||
class NBEdgeCont {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] tc The net builded; used to obtain types
|
||||
*/
|
||||
NBEdgeCont(NBTypeCont& tc);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBEdgeCont();
|
||||
|
||||
|
||||
/** @brief Initialises the storage by applying given options
|
||||
*
|
||||
* Options, mainly steering the acceptance of edges, are parsed
|
||||
* and the according internal variables are set.
|
||||
*
|
||||
* @param[in] oc The options container to read options from
|
||||
* @todo Recheck exceptions
|
||||
*/
|
||||
void applyOptions(OptionsCont& oc);
|
||||
|
||||
|
||||
/** @brief Deletes all edges */
|
||||
void clear();
|
||||
|
||||
|
||||
|
||||
|
||||
/// @name edge access methods
|
||||
/// @{
|
||||
|
||||
/** @brief Adds an edge to the dictionary
|
||||
*
|
||||
* First, it is determined whether the edge shall not be discarded due to any
|
||||
* reasons (being outside a boundary, or not in the optional list of edges to
|
||||
* import, etc.). If so, the edge is deleted and "true" is returned.
|
||||
* "true" is also returned if the edge is accepted - no edge with the same
|
||||
* name exists within this container. If another edge with the same name
|
||||
* exists, false is returned.
|
||||
*
|
||||
* @param[in] edge The edge to add
|
||||
* @param[in] ignorePrunning Whether this edge must not be prunned
|
||||
* @return Whether the edge was valid (no edge with the same id is already known)
|
||||
*/
|
||||
bool insert(NBEdge* edge, bool ignorePrunning = false);
|
||||
|
||||
|
||||
/** @brief Returns the edge that has the given id
|
||||
*
|
||||
* If no edge that has the given id is known, 0 is returned.
|
||||
*
|
||||
* @param[in] id The id of the edge to retrieve
|
||||
* @param[in] bool Whether extracted edges shall be retrieved as well
|
||||
* @return The edge with the given id, 0 if no such edge exists
|
||||
*/
|
||||
NBEdge* retrieve(const std::string& id, bool retrieveExtracted = false) const;
|
||||
|
||||
|
||||
/** @brief Tries to retrieve an edge, even if it is splitted
|
||||
*
|
||||
* The edge given with the id should exist and is followed downstream or upstream,
|
||||
* depending on the parameter to the last edge still starting with the id.
|
||||
*
|
||||
* @param[in] id The id of the edge to retrieve
|
||||
* @param[in] downstream search direction
|
||||
* @return The searched edge
|
||||
* @todo Recheck usage
|
||||
*/
|
||||
NBEdge* retrievePossiblySplit(const std::string& id, bool downstream) const;
|
||||
|
||||
|
||||
/** @brief Tries to retrieve an edge, even if it is splitted
|
||||
*
|
||||
* To describe which part of the edge shall be returned, the
|
||||
* id of a second edge, participating at the node and the information
|
||||
* whether to return the outgoing or the incoming is needed.
|
||||
*
|
||||
* @param[in] id The id of the edge to retrieve
|
||||
* @param[in] hint An additional information which helps to retrieve the correct edge
|
||||
* @param[in] incoming Whether the edge to find is an incoming edge at the node "hint" participates
|
||||
* @return The searched edge
|
||||
* @todo Recheck usage
|
||||
*/
|
||||
NBEdge* retrievePossiblySplit(const std::string& id, const std::string& hint, bool incoming) const;
|
||||
|
||||
|
||||
/** @brief Tries to retrieve an edge, even if it is splitted
|
||||
*
|
||||
* To describe which part of the edge shall be returned, a
|
||||
* position hint is supplied.
|
||||
*
|
||||
* @param[in] id The id of the edge to retrieve
|
||||
* @param[in] pos An additional about the position of the basic edge's subpart
|
||||
* @return The searched edge
|
||||
* @todo Recheck usage
|
||||
*/
|
||||
NBEdge* retrievePossiblySplit(const std::string& id, double pos) const;
|
||||
|
||||
|
||||
/** @brief Removes the given edge from the container (deleting it)
|
||||
*
|
||||
* @param[in] dc The district container, in order to remove the edge from sources/sinks
|
||||
* @param[in] edge The edge to remove
|
||||
* @todo Recheck whether the district cont is needed - if districts are processed using an external tool
|
||||
*/
|
||||
void erase(NBDistrictCont& dc, NBEdge* edge);
|
||||
|
||||
|
||||
/** @brief Removes the given edge from the container like erase but does not
|
||||
* delete it
|
||||
*
|
||||
* @param[in] dc The district container, in order to remove the edge from sources/sinks
|
||||
* @param[in] edge The edge to remove
|
||||
* @param[in] remember Whether to keep this edge for future reference
|
||||
* @todo Recheck whether the district cont is needed - if districts are processed using an external tool
|
||||
* @todo Recheck whether this is used at all and why
|
||||
*/
|
||||
void extract(NBDistrictCont& dc, NBEdge* edge, bool remember = false);
|
||||
|
||||
|
||||
/** @brief Returns the pointer to the begin of the stored edges
|
||||
* @return The iterator to the beginning of stored edges
|
||||
*/
|
||||
std::map<std::string, NBEdge*>::const_iterator begin() const {
|
||||
return myEdges.begin();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns the pointer to the end of the stored edges
|
||||
* @return The iterator to the end of stored edges
|
||||
*/
|
||||
std::map<std::string, NBEdge*>::const_iterator end() const {
|
||||
return myEdges.end();
|
||||
}
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @name explicit edge manipulation methods
|
||||
/// @{
|
||||
|
||||
/** @struct Split
|
||||
* @brief A structure which describes changes of lane number or speed along the road
|
||||
*/
|
||||
struct Split {
|
||||
/// @brief The lanes after this change
|
||||
std::vector<int> lanes;
|
||||
/// @brief The position of this change
|
||||
double pos = INVALID_DOUBLE;
|
||||
/// @brief The speed after this change
|
||||
double speed = INVALID_DOUBLE;
|
||||
/// @brief The new node that is created for this split
|
||||
NBNode* node = nullptr;
|
||||
/// @brief The id for the edge before the split
|
||||
std::string idBefore;
|
||||
/// @brief The id for the edge after the split
|
||||
std::string idAfter;
|
||||
/// @brief the default node id
|
||||
std::string nameID;
|
||||
/// @brief lateral offset to edge geometry
|
||||
double offset = 0.;
|
||||
/// @brief direction in which to apply the offset (used by netgenerate for lefthand networks)
|
||||
int offsetFactor = 1;
|
||||
};
|
||||
|
||||
void processSplits(NBEdge* e, std::vector<Split> splits,
|
||||
NBNodeCont& nc, NBDistrictCont& dc, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
|
||||
/** @brief Splits the edge at the position nearest to the given node
|
||||
*
|
||||
* Uses "splitAt(NBDistrictCont &, NBEdge *, NBNode *, const std::string &, const std::string &, int , int)"
|
||||
* to perform the split; the edge names are built by appending "[0]" and "[1]",
|
||||
* respectively. Both edges will have the same number of lanes.
|
||||
*
|
||||
* @param[in] dc The district container, in order to remove/add the edge from/to sources/sinks
|
||||
* @param[in] edge The edge to split
|
||||
* @param[in] node The node to split the edge at
|
||||
* @return Whether the edge could be split
|
||||
* @exception ProcessError If connections between the edges can not be built
|
||||
* @see NBEdge::splitAt(NBDistrictCont &, NBEdge *, NBNode *, const std::string &, const std::string &, int , int)
|
||||
*/
|
||||
bool splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node);
|
||||
|
||||
|
||||
/** @brief Splits the edge at the position nearest to the given node using the given modifications
|
||||
*
|
||||
* Determines the position of the split by finding the nearest position on the
|
||||
* edge to the given node. If this position is too near to the edges begin/end,
|
||||
* false is returned.
|
||||
*
|
||||
* Otherwise, "splitAt(NBDistrictCont &, NBEdge *, double, NBNode *, const std::string &, const std::string &, int , int)"
|
||||
* is used to perform the split.
|
||||
*
|
||||
* @param[in] dc The district container, in order to remove/add the edge from/to sources/sinks
|
||||
* @param[in] edge The edge to split
|
||||
* @param[in] node The node to split the edge at
|
||||
* @param[in] firstEdgeName The id the first part of the split edge shall have
|
||||
* @param[in] secondEdgeName The id the second part of the split edge shall have
|
||||
* @param[in] noLanesFirstEdge The number of lanes the second part of the split edge shall have
|
||||
* @param[in] noLanesSecondEdge The number of lanes the second part of the split edge shall have
|
||||
* @param[in] speed The speed for the edge after the split
|
||||
* @param[in] changedLeft The number of lanes that is added or removed on the left side of the edge
|
||||
* (By default all added/removed lanes are assumed to be on the right when computing connections)
|
||||
* @return Whether the edge could be split
|
||||
* @exception ProcessError If connections between the edges can not be built
|
||||
* @see NBEdge::splitAt(NBDistrictCont &, NBEdge *, double, NBNode *, const std::string &, const std::string &, int , int)
|
||||
*/
|
||||
bool splitAt(NBDistrictCont& dc, NBEdge* edge, NBNode* node,
|
||||
const std::string& firstEdgeName, const std::string& secondEdgeName,
|
||||
int noLanesFirstEdge, int noLanesSecondEdge,
|
||||
const double speed = -1., const int changedLeft = 0);
|
||||
|
||||
|
||||
/** @brief Splits the edge at the position nearest to the given node using the given modifications
|
||||
*
|
||||
* @param[in] dc The district container, in order to remove/add the edge from/to sources/sinks
|
||||
* @param[in] edge The edge to split
|
||||
* @param[in] node The node to split the edge at
|
||||
* @param[in] firstEdgeName The id the first part of the split edge shall have
|
||||
* @param[in] secondEdgeName The id the second part of the split edge shall have
|
||||
* @param[in] noLanesFirstEdge The number of lanes the second part of the split edge shall have
|
||||
* @param[in] noLanesSecondEdge The number of lanes the second part of the split edge shall have
|
||||
* @param[in] speed The speed for the edge after the split
|
||||
* @param[in] changedLeft The number of lanes that is added or removed on the left side of the edge
|
||||
* (By default all added/removed lanes are assumed to be on the right when computing connections)
|
||||
* @return Whether the edge could be split
|
||||
* @exception ProcessError If connections between the edges can not be built
|
||||
*/
|
||||
bool splitAt(NBDistrictCont& dc, NBEdge* edge, double edgepos, NBNode* node,
|
||||
const std::string& firstEdgeName, const std::string& secondEdgeName,
|
||||
int noLanesFirstEdge, int noLanesSecondEdge,
|
||||
const double speed = -1., const int changedLeft = 0);
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @name container access methods
|
||||
/// @{
|
||||
|
||||
/** @brief Returns the number of edges
|
||||
* @return The number of edges stored in this container
|
||||
*/
|
||||
int size() const {
|
||||
return (int) myEdges.size();
|
||||
}
|
||||
|
||||
|
||||
/** @brief Returns all ids of known edges
|
||||
* @return All ids of known edges
|
||||
* @todo Recheck usage, probably, filling a given vector would be better...
|
||||
*/
|
||||
std::vector<std::string> getAllNames() const;
|
||||
|
||||
|
||||
/** @brief Returns the number of edge splits
|
||||
* @return How often an edge was split
|
||||
*/
|
||||
int getNoEdgeSplits() const {
|
||||
return myEdgesSplit;
|
||||
}
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @name Adapting the input
|
||||
/// @{
|
||||
|
||||
/** @brief Removes unwished edges (not in keep-edges)
|
||||
* @param[in, opt. changed] dc The district container needed to remove edges
|
||||
* @todo Recheck usage; check whether keep-edges.postload is really useful
|
||||
*/
|
||||
void removeUnwishedEdges(NBDistrictCont& dc);
|
||||
|
||||
|
||||
/** @brief Splits edges into multiple if they have a complex geometry
|
||||
*
|
||||
* Calls "NBEdge::splitGeometry" for all edges within the container which
|
||||
* have more than three positions in their geometry.
|
||||
*
|
||||
* @param[in] nc The node container needed to build (geometry) nodes
|
||||
* @see NBEdge::splitGeometry
|
||||
*/
|
||||
void splitGeometry(NBDistrictCont& dc, NBNodeCont& nc);
|
||||
|
||||
|
||||
/** @brief
|
||||
* @param[in] nc The node container needed to build (geometry) nodes
|
||||
* @see NBEdge::reduceGeometry
|
||||
*/
|
||||
void reduceGeometries(const double minDist);
|
||||
|
||||
|
||||
/** @brief
|
||||
* @param[in] maxAngle The maximum geometry angle allowed
|
||||
* @param[in] minRadius The minimum turning radius allowed at the start and end
|
||||
* @param[in] fix Whether to prune geometry points to avoid sharp turns at start and end
|
||||
* @see NBEdge::checkGeometry
|
||||
*/
|
||||
void checkGeometries(const double maxAngle, const double minRadius, bool fix, bool fixRailways, bool silent = false);
|
||||
/// @}
|
||||
|
||||
|
||||
|
||||
/// @name processing methods
|
||||
/// @{
|
||||
|
||||
/** @brief Sorts all lanes of all edges within the container by their direction
|
||||
*
|
||||
* Calls "NBEdge::sortOutgoingLanesConnections" for all edges within the container.
|
||||
*
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @see NBEdge::sortOutgoingLanesConnections
|
||||
*/
|
||||
void sortOutgoingLanesConnections();
|
||||
|
||||
|
||||
/** @brief Computes for each edge the approached edges
|
||||
*
|
||||
* Calls "NBEdge::computeEdge2Edges" for all edges within the container.
|
||||
*
|
||||
* @param[in] noLeftMovers Whether left-moving connections shall be omitted
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @see NBEdge::computeEdge2Edges
|
||||
*/
|
||||
void computeEdge2Edges(bool noLeftMovers);
|
||||
|
||||
|
||||
/** @brief Computes for each edge which lanes approach the next edges
|
||||
*
|
||||
* Calls "NBEdge::computeLanes2Edges" for all edges within the container.
|
||||
*
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @see NBEdge::computeLanes2Edges
|
||||
*/
|
||||
void computeLanes2Edges();
|
||||
|
||||
|
||||
/** @brief Rechecks whether all lanes have a successor for each of the stored edges
|
||||
*
|
||||
* Calls "NBEdge::recheckLanes" for all edges within the container.
|
||||
*
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @see NBEdge::recheckLanes
|
||||
*/
|
||||
void recheckLanes();
|
||||
|
||||
|
||||
/** @brief Appends turnarounds to all edges stored in the container
|
||||
*
|
||||
* Calls "NBEdge::appendTurnaround" for all edges within the container.
|
||||
*
|
||||
* @param[in] noTLSControlled Whether the turnaround shall not be connected if the edge is controlled by a tls
|
||||
* @param[in] noFringe Whether the turnaround shall not be connected if the junction is at the (outer) fringe
|
||||
* @param[in] onlyDeadends Whether the turnaround shall only be built at deadends
|
||||
* @param[in] onlyTurnlane Whether the turnaround shall only be built when there is an exclusive (left) turn lane
|
||||
* @param[in] noGeometryLike Whether the turnaround shall be built at geometry-like nodes
|
||||
* @see NBEdge::appendTurnaround
|
||||
*/
|
||||
void appendTurnarounds(bool noTLSControlled, bool noFringe, bool onlyDeadends, bool onlyTurnlane, bool noGeometryLike);
|
||||
|
||||
|
||||
/** @brief Appends turnarounds to all edges stored in the container
|
||||
* Calls "NBEdge::appendTurnaround" for edges with the given ids
|
||||
* @param[in] ids The list of ids for which to append a turnaround
|
||||
* @param[in] noTLSControlled Whether the turnaround shall not be connected if the edge is controlled by a tls
|
||||
* @see NBEdge::appendTurnaround
|
||||
*/
|
||||
void appendTurnarounds(const std::set<std::string>& ids, bool noTLSControlled);
|
||||
|
||||
/** @brief Appends turnarounds to all bidiRail edges with stops
|
||||
*/
|
||||
void appendRailwayTurnarounds(const NBPTStopCont& sc);
|
||||
|
||||
|
||||
/** @brief Computes the shapes of all edges stored in the container
|
||||
*
|
||||
* Calls "NBEdge::computeEdgeShape" for all edges within the container.
|
||||
*
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @todo Recheck usage
|
||||
* @see NBEdge::computeEdgeShape
|
||||
*/
|
||||
void computeEdgeShapes(double smoothElevationThreshold = -1);
|
||||
|
||||
|
||||
/** @brief Computes the shapes of all lanes of all edges stored in the container
|
||||
*
|
||||
* Calls "NBEdge::computeLaneShapes" for all edges within the container.
|
||||
*
|
||||
* @todo Recheck whether a visitor-pattern should be used herefor
|
||||
* @todo Recheck usage
|
||||
* @see NBEdge::computeLaneShapes
|
||||
*/
|
||||
void computeLaneShapes();
|
||||
|
||||
|
||||
/** @brief Clears information about controlling traffic lights for all connenections of all edges
|
||||
*/
|
||||
void clearControllingTLInformation() const;
|
||||
|
||||
|
||||
/** @brief Joins the given edges because they connect the same nodes
|
||||
*
|
||||
* @param[in] dc The district container needed to remove edges
|
||||
* @param[in] tlc The tls container needed to remove edges
|
||||
* @param[in] edges The edges to join
|
||||
* @todo Recheck and describe usage
|
||||
*/
|
||||
void joinSameNodeConnectingEdges(NBDistrictCont& dc,
|
||||
NBTrafficLightLogicCont& tlc, EdgeVector edges);
|
||||
|
||||
|
||||
/** @brief Sets opposite lane information for geometrically close edges
|
||||
*/
|
||||
void guessOpposites();
|
||||
|
||||
|
||||
/** @brief Rechecks whether the lane spread is proper
|
||||
*
|
||||
* @todo Recheck usage; check whether this is really needed and whether it works at all
|
||||
*/
|
||||
void recheckLaneSpread();
|
||||
|
||||
/// @}
|
||||
|
||||
/// @brief Returns the edge with negated id if it exists
|
||||
NBEdge* getOppositeByID(const std::string& edgeID) const;
|
||||
|
||||
/// @brief Returns the edge with id if it exists
|
||||
NBEdge* getByID(const std::string& edgeID) const;
|
||||
|
||||
/** @brief Determines which edges belong to roundabouts and increases their priority
|
||||
* @param[out] marked Edges which belong to a roundabout are stored here
|
||||
* @return The number of guessed roundabouts
|
||||
*/
|
||||
int guessRoundabouts();
|
||||
|
||||
|
||||
/** @brief Returns whether the edge with the id was ignored during parsing
|
||||
* @return Whether the edge with the id was ignored during parsing
|
||||
*/
|
||||
bool wasIgnored(std::string id) const {
|
||||
return myIgnoredEdges.count(id) != 0;
|
||||
}
|
||||
|
||||
/// @brief mark the given edge id as ignored
|
||||
void ignore(std::string id) {
|
||||
myIgnoredEdges.insert(id);
|
||||
}
|
||||
|
||||
/** @brief Returns whether the edge with the id was deleted explicitly
|
||||
*/
|
||||
bool wasRemoved(std::string id) const {
|
||||
return myExtractedEdges.count(id) != 0;
|
||||
}
|
||||
|
||||
/** @brief Renames the edge. Throws exception if newID already exists
|
||||
*/
|
||||
void rename(NBEdge* edge, const std::string& newID);
|
||||
|
||||
|
||||
|
||||
/// @name Connections handling
|
||||
/// @{
|
||||
|
||||
/** @brief Adds a connection which could not be set during loading
|
||||
* @param[in] from The id of the edge the connection starts at
|
||||
* @param[in] fromLane The number of the lane the connection starts at
|
||||
* @param[in] to The id of the edge the connection ends at
|
||||
* @param[in] toLane The number of the lane the connection ends at
|
||||
* @param[in] mayDefinitelyPass Whether the connection may be passed without braking
|
||||
* @param[in] keepClear Whether the connection must check to keep the junction clear
|
||||
* @param[in] contPos Custom position for internal junction
|
||||
* @param[in] visibility Custom foe visiblity connection
|
||||
* @param[in] speed Custom speed
|
||||
* @param[in] customShape Custom shape
|
||||
* @param[in] warnOnly Whether a failure to set this connection should only result in a warning
|
||||
*/
|
||||
void addPostProcessConnection(const std::string& from, int fromLane, const std::string& to, int toLane, bool mayDefinitelyPass,
|
||||
bool keepClear, double contPos, double visibility,
|
||||
double speed, double length,
|
||||
const PositionVector& customShape,
|
||||
bool uncontrolled,
|
||||
bool warnOnly,
|
||||
SVCPermissions permissions = SVC_UNSPECIFIED);
|
||||
|
||||
bool hasPostProcessConnection(const std::string& from, const std::string& to = "");
|
||||
|
||||
|
||||
/** @brief Try to set any stored connections
|
||||
*/
|
||||
void recheckPostProcessConnections();
|
||||
/// @}
|
||||
|
||||
/// @brief assigns street signs to edges based on toNode types
|
||||
void generateStreetSigns();
|
||||
|
||||
/// @brief add sidwalks to edges within the given limits or permissions and return the number of edges affected
|
||||
int guessSpecialLanes(SUMOVehicleClass svc, double width, double minSpeed, double maxSpeed, bool fromPermissions, const std::string& excludeOpt);
|
||||
|
||||
|
||||
/** @brief Returns the determined roundabouts
|
||||
* @return The list of roundabout edges
|
||||
*/
|
||||
const std::set<EdgeSet> getRoundabouts() const;
|
||||
|
||||
/// @brief add user specified roundabout
|
||||
void addRoundabout(const EdgeSet& roundabout);
|
||||
|
||||
/// @brief remove roundabout that contains the given node
|
||||
void removeRoundabout(const NBNode* node);
|
||||
|
||||
/// @brief mark edge priorities and prohibit turn-arounds for all roundabout edges
|
||||
void markRoundabouts();
|
||||
|
||||
/// @brief fix roundabout information after splitting an edge
|
||||
void patchRoundabouts(NBEdge* orig, NBEdge* part1, NBEdge* part2, std::set<EdgeSet>& roundabouts);
|
||||
|
||||
/// @brief Returns true if this edge matches one of the removal criteria
|
||||
bool ignoreFilterMatch(NBEdge* edge);
|
||||
|
||||
/// @brief remap node IDs accoring to options --numerical-ids and --reserved-ids
|
||||
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string& prefix, NBPTStopCont& sc);
|
||||
|
||||
/// @brief check whether edges overlap
|
||||
void checkOverlap(double threshold, double zThreshold) const;
|
||||
|
||||
/// @brief check whether edges are to steep
|
||||
void checkGrade(double threshold) const;
|
||||
|
||||
|
||||
/** @brief Returns the edges which have been built by splitting the edge of the given id
|
||||
*
|
||||
* @param[in] id The id of the original edge
|
||||
* @return List of all edges which have been built by splitting the original edge
|
||||
* @todo Recheck usage
|
||||
*/
|
||||
EdgeVector getGeneratedFrom(const std::string& id) const;
|
||||
|
||||
/// @brief join adjacent lanes with the given permissions
|
||||
int joinLanes(SVCPermissions perms);
|
||||
|
||||
/// @brief join tram edges into adjacent lanes
|
||||
int joinTramEdges(NBDistrictCont& dc, NBPTLineCont& lc, double maxDist);
|
||||
|
||||
/// @brief return all edges
|
||||
EdgeVector getAllEdges() const;
|
||||
RouterEdgeVector getAllRouterEdges() const;
|
||||
|
||||
/// @brief ensure that all edges have valid nodes
|
||||
bool checkConsistency(const NBNodeCont& nc);
|
||||
|
||||
private:
|
||||
/// @brief compute the form factor for a loop of edges
|
||||
static double formFactor(const EdgeVector& loopEdges);
|
||||
|
||||
private:
|
||||
/// @brief The network builder; used to obtain type information
|
||||
NBTypeCont& myTypeCont;
|
||||
|
||||
/** @struct PostProcessConnection
|
||||
* @brief A structure representing a connection between two lanes
|
||||
*/
|
||||
struct PostProcessConnection {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] from The id of the edge the connection starts at
|
||||
* @param[in] fromLane The number of the lane the connection starts at
|
||||
* @param[in] to The id of the edge the connection ends at
|
||||
* @param[in] toLane The number of the lane the connection ends at
|
||||
* @param[in] mayDefinitelyPass Whether the connection may be passed without braking
|
||||
*/
|
||||
PostProcessConnection(const std::string& from_, int fromLane_, const std::string& to_, int toLane_,
|
||||
bool mayDefinitelyPass_, bool keepClear_, double contPos_, double visibility_, double speed_,
|
||||
double length_,
|
||||
const PositionVector& customShape_,
|
||||
bool uncontrolled_,
|
||||
bool warnOnly_, SVCPermissions permissions_) :
|
||||
from(from_), fromLane(fromLane_), to(to_), toLane(toLane_), mayDefinitelyPass(mayDefinitelyPass_), keepClear(keepClear_), contPos(contPos_),
|
||||
visibility(visibility_),
|
||||
speed(speed_),
|
||||
customLength(length_),
|
||||
customShape(customShape_),
|
||||
uncontrolled(uncontrolled_),
|
||||
permissions(permissions_),
|
||||
warnOnly(warnOnly_)
|
||||
{}
|
||||
/// @brief The id of the edge the connection starts at
|
||||
std::string from;
|
||||
/// @brief The number of the lane the connection starts at
|
||||
int fromLane;
|
||||
/// @brief The id of the edge the connection ends at
|
||||
std::string to;
|
||||
/// @brief The number of the lane the connection ends at
|
||||
int toLane;
|
||||
/// @brief Whether the connection may be passed without braking
|
||||
bool mayDefinitelyPass;
|
||||
/// @brief Whether the connection may be passed without braking
|
||||
bool keepClear;
|
||||
/// @brief custom position for internal junction on this connection
|
||||
double contPos;
|
||||
/// @brief custom foe visiblity for connection
|
||||
double visibility;
|
||||
/// @brief custom speed for connection
|
||||
double speed;
|
||||
/// @brief custom length for connection
|
||||
double customLength;
|
||||
/// @brief custom shape for connection
|
||||
PositionVector customShape;
|
||||
/// @brief whether this connection shall not be controlled by a traffic light
|
||||
bool uncontrolled;
|
||||
/// @brief custom permissions for connection
|
||||
SVCPermissions permissions;
|
||||
/// @brief whether a failure to set this connection is a warning or an error
|
||||
bool warnOnly;
|
||||
};
|
||||
|
||||
/// @brief The list of connections to recheck
|
||||
std::map<std::string, std::vector<PostProcessConnection> > myConnections;
|
||||
|
||||
|
||||
/// @brief The type of the dictionary where an edge may be found by its id
|
||||
typedef std::map<std::string, NBEdge*> EdgeCont;
|
||||
|
||||
/// @brief The instance of the dictionary (id->edge)
|
||||
EdgeCont myEdges;
|
||||
|
||||
/// @brief The extracted nodes which are kept for reference
|
||||
EdgeCont myExtractedEdges;
|
||||
|
||||
/// @brief The ids of ignored edges
|
||||
std::set<std::string> myIgnoredEdges;
|
||||
|
||||
/// @brief the number of splits of edges during the building
|
||||
int myEdgesSplit;
|
||||
|
||||
/// @name Settings for accepting/dismissing edges
|
||||
/// @{
|
||||
|
||||
/// @brief The minimum speed an edge may have in order to be kept (default: -1)
|
||||
double myEdgesMinSpeed;
|
||||
|
||||
/// @brief Whether edges shall be joined first, then removed
|
||||
bool myRemoveEdgesAfterJoining;
|
||||
|
||||
/// @brief Set of ids of edges which shall explicitly be kept
|
||||
std::set<std::string> myEdges2Keep;
|
||||
|
||||
/// @brief Set of ids of edges which shall explicitly be removed
|
||||
std::set<std::string> myEdges2Remove;
|
||||
|
||||
/// @brief Set of vehicle types which must be allowed on edges in order to keep them
|
||||
SVCPermissions myVehicleClasses2Keep;
|
||||
|
||||
/// @brief Set of vehicle types which need not be supported (edges which allow ONLY these are removed)
|
||||
SVCPermissions myVehicleClasses2Remove;
|
||||
|
||||
/// @brief Set of edges types which shall be kept
|
||||
std::set<std::string> myTypes2Keep;
|
||||
|
||||
/// @brief Set of edges types which shall be removed
|
||||
std::set<std::string> myTypes2Remove;
|
||||
|
||||
/// @brief Boundary within which an edge must be located in order to be kept
|
||||
PositionVector myPruningBoundary;
|
||||
|
||||
/// @brief whether a geo transform has been applied to the pruning boundary
|
||||
bool myNeedGeoTransformedPruningBoundary;
|
||||
/// @}
|
||||
|
||||
/// @brief Edges marked as belonging to a roundabout by the user (each EdgeVector is a roundabout)
|
||||
std::set<EdgeSet> myRoundabouts;
|
||||
/// @brief Edges marked as belonging to a roundabout after guessing
|
||||
std::set<EdgeSet> myGuessedRoundabouts;
|
||||
|
||||
/** @class split_sorter
|
||||
* @brief Sorts splits by their position (increasing)
|
||||
*/
|
||||
class split_sorter {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
explicit split_sorter() { }
|
||||
|
||||
/// @brief Comparing operator
|
||||
int operator()(const Split& e1, const Split& e2) const {
|
||||
return e1.pos < e2.pos;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
/// @brief invalidated copy constructor
|
||||
NBEdgeCont(const NBEdgeCont& s);
|
||||
|
||||
/// @brief invalidated assignment operator
|
||||
NBEdgeCont& operator=(const NBEdgeCont& s);
|
||||
|
||||
};
|
|
@ -1,706 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBFrame.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date 09.05.2011
|
||||
///
|
||||
// Sets and checks options for netbuild
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "NBFrame.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBTrafficLightLogicCont.h"
|
||||
#include "NBDistrictCont.h"
|
||||
#include "NBRequest.h"
|
||||
#include "NBTypeCont.h"
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/common/StringTokenizer.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/geom/GeoConvHelper.h>
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include <utils/xml/SUMOXMLDefinitions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
void
|
||||
NBFrame::fillOptions(bool forNetgen) {
|
||||
OptionsCont& oc = OptionsCont::getOptions();
|
||||
// register building defaults
|
||||
oc.doRegister("default.lanenumber", 'L', new Option_Integer(1));
|
||||
oc.addSynonyme("default.lanenumber", "lanenumber", true);
|
||||
oc.addDescription("default.lanenumber", "Building Defaults", "The default number of lanes in an edge");
|
||||
|
||||
oc.doRegister("default.lanewidth", new Option_Float(NBEdge::UNSPECIFIED_WIDTH));
|
||||
oc.addSynonyme("default.lanewidth", "lanewidth", true);
|
||||
oc.addDescription("default.lanewidth", "Building Defaults", "The default width of lanes");
|
||||
|
||||
oc.doRegister("default.spreadtype", new Option_String("right"));
|
||||
oc.addDescription("default.spreadtype", "Building Defaults", "The default method for computing lane shapes from edge shapes");
|
||||
|
||||
oc.doRegister("default.speed", 'S', new Option_Float((double) 13.89));
|
||||
oc.addSynonyme("default.speed", "speed", true);
|
||||
oc.addDescription("default.speed", "Building Defaults", "The default speed on an edge (in m/s)");
|
||||
|
||||
oc.doRegister("default.priority", 'P', new Option_Integer(-1));
|
||||
oc.addSynonyme("default.priority", "priority", true);
|
||||
oc.addDescription("default.priority", "Building Defaults", "The default priority of an edge");
|
||||
|
||||
oc.doRegister("default.type", new Option_String());
|
||||
oc.addDescription("default.type", "Building Defaults", "The default edge type");
|
||||
|
||||
oc.doRegister("default.sidewalk-width", new Option_Float((double) 2.0));
|
||||
oc.addDescription("default.sidewalk-width", "Building Defaults", "The default width of added sidewalks");
|
||||
|
||||
oc.doRegister("default.bikelane-width", new Option_Float((double) 1.0));
|
||||
oc.addDescription("default.bikelane-width", "Building Defaults", "The default width of added bike lanes");
|
||||
|
||||
oc.doRegister("default.crossing-width", new Option_Float((double) 4.0));
|
||||
oc.addDescription("default.crossing-width", "Building Defaults", "The default width of a pedestrian crossing");
|
||||
|
||||
oc.doRegister("default.disallow", new Option_String());
|
||||
oc.addDescription("default.disallow", "Building Defaults", "The default for disallowed vehicle classes");
|
||||
|
||||
oc.doRegister("default.junctions.keep-clear", new Option_Bool(true));
|
||||
oc.addDescription("default.junctions.keep-clear", "Building Defaults", "Whether junctions should be kept clear by default");
|
||||
|
||||
oc.doRegister("default.junctions.radius", new Option_Float(4));
|
||||
oc.addDescription("default.junctions.radius", "Building Defaults", "The default turning radius of intersections");
|
||||
|
||||
oc.doRegister("default.connection-length", new Option_Float((double) NBEdge::UNSPECIFIED_LOADED_LENGTH));
|
||||
oc.addDescription("default.connection-length", "Building Defaults", "The default length when overriding connection lengths");
|
||||
|
||||
oc.doRegister("default.right-of-way", new Option_String("default"));
|
||||
oc.addDescription("default.right-of-way", "Building Defaults", "The default algorithm for computing right of way rules ('default', 'edgePriority')");
|
||||
|
||||
oc.doRegister("junctions.right-before-left.speed-threshold", new Option_Float(49 / 3.6));
|
||||
oc.addDescription("junctions.right-before-left.speed-threshold", "Junctions", "Allow building right-before-left junctions when the incoming edge speeds are below FLOAT (m/s)");
|
||||
|
||||
// register the data processing options
|
||||
oc.doRegister("no-internal-links", new Option_Bool(false)); // !!! not described
|
||||
oc.addDescription("no-internal-links", "Junctions", "Omits internal links");
|
||||
|
||||
oc.doRegister("numerical-ids", new Option_Bool(false));
|
||||
oc.addDescription("numerical-ids", "Processing", "Remaps alphanumerical IDs of nodes and edges to ensure that all IDs are integers");
|
||||
|
||||
oc.doRegister("numerical-ids.node-start", new Option_Integer(std::numeric_limits<int>::max()));
|
||||
oc.addDescription("numerical-ids.node-start", "Processing", "Remaps IDs of nodes to integers starting at INT");
|
||||
|
||||
oc.doRegister("numerical-ids.edge-start", new Option_Integer(std::numeric_limits<int>::max()));
|
||||
oc.addDescription("numerical-ids.edge-start", "Processing", "Remaps IDs of edges to integers starting at INT");
|
||||
|
||||
/// @todo not working for netgen
|
||||
oc.doRegister("reserved-ids", new Option_FileName());
|
||||
oc.addDescription("reserved-ids", "Processing", "Ensures that generated ids do not included any of the typed IDs from FILE (SUMO-GUI selection file format)");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("dismiss-vclasses", new Option_Bool(false));
|
||||
oc.addDescription("dismiss-vclasses", "Processing", "Removes vehicle class restrictions from imported edges");
|
||||
}
|
||||
|
||||
oc.doRegister("no-turnarounds", new Option_Bool(false));
|
||||
oc.addDescription("no-turnarounds", "Junctions", "Disables building turnarounds");
|
||||
|
||||
oc.doRegister("no-turnarounds.tls", new Option_Bool(false));
|
||||
oc.addSynonyme("no-turnarounds.tls", "no-tls-turnarounds", true);
|
||||
oc.addDescription("no-turnarounds.tls", "Junctions", "Disables building turnarounds at tls-controlled junctions");
|
||||
|
||||
oc.doRegister("no-turnarounds.geometry", new Option_Bool(true));
|
||||
oc.addDescription("no-turnarounds.geometry", "Junctions", "Disables building turnarounds at geometry-like junctions");
|
||||
|
||||
oc.doRegister("no-turnarounds.except-deadend", new Option_Bool(false));
|
||||
oc.addDescription("no-turnarounds.except-deadend", "Junctions", "Disables building turnarounds except at dead end junctions");
|
||||
|
||||
oc.doRegister("no-turnarounds.except-turnlane", new Option_Bool(false));
|
||||
oc.addDescription("no-turnarounds.except-turnlane", "Junctions", "Disables building turnarounds except at at junctions with a dedicated turning lane");
|
||||
|
||||
oc.doRegister("no-turnarounds.fringe", new Option_Bool(false));
|
||||
oc.addDescription("no-turnarounds.fringe", "Junctions", "Disables building turnarounds at fringe junctions");
|
||||
|
||||
oc.doRegister("no-left-connections", new Option_Bool(false));
|
||||
oc.addDescription("no-left-connections", "Junctions", "Disables building connections to left");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("geometry.split", new Option_Bool(false)); // !!!not described
|
||||
oc.addSynonyme("geometry.split", "split-geometry", true);
|
||||
oc.addDescription("geometry.split", "Processing", "Splits edges across geometry nodes");
|
||||
|
||||
oc.doRegister("geometry.remove", 'R', new Option_Bool(false));
|
||||
oc.addSynonyme("geometry.remove", "remove-geometry", true);
|
||||
oc.addDescription("geometry.remove", "Processing", "Replace nodes which only define edge geometry by geometry points (joins edges)");
|
||||
|
||||
oc.doRegister("geometry.remove.keep-edges.explicit", new Option_StringVector());
|
||||
oc.addDescription("geometry.remove.keep-edges.explicit", "Processing", "Ensure that the given list of edges is not modified");
|
||||
|
||||
oc.doRegister("geometry.remove.keep-edges.input-file", new Option_FileName());
|
||||
oc.addDescription("geometry.remove.keep-edges.input-file", "Processing",
|
||||
"Ensure that the edges in FILE are not modified (Each id on a single line. Selection files from SUMO-GUI are also supported)");
|
||||
|
||||
oc.doRegister("geometry.remove.min-length", new Option_Float(0));
|
||||
oc.addDescription("geometry.remove.min-length", "Processing",
|
||||
"Allow merging edges with differing attributes when their length is below min-length");
|
||||
|
||||
oc.doRegister("geometry.remove.width-tolerance", new Option_Float(0));
|
||||
oc.addDescription("geometry.remove.width-tolerance", "Processing",
|
||||
"Allow merging edges with differing lane widths if the difference is below FLOAT");
|
||||
|
||||
oc.doRegister("geometry.max-segment-length", new Option_Float(0));
|
||||
oc.addDescription("geometry.max-segment-length", "Processing", "splits geometry to restrict segment length");
|
||||
|
||||
oc.doRegister("geometry.min-dist", new Option_Float(-1));
|
||||
oc.addDescription("geometry.min-dist", "Processing", "reduces too similar geometry points");
|
||||
|
||||
oc.doRegister("geometry.max-angle", new Option_Float(99));
|
||||
oc.addDescription("geometry.max-angle", "Processing", "Warn about edge geometries with an angle above DEGREES in successive segments");
|
||||
|
||||
oc.doRegister("geometry.min-radius", new Option_Float(9));
|
||||
oc.addDescription("geometry.min-radius", "Processing", "Warn about edge geometries with a turning radius less than METERS at the start or end");
|
||||
|
||||
oc.doRegister("geometry.min-radius.fix", new Option_Bool(false));
|
||||
oc.addDescription("geometry.min-radius.fix", "Processing", "Straighten edge geometries to avoid turning radii less than geometry.min-radius");
|
||||
|
||||
oc.doRegister("geometry.min-radius.fix.railways", new Option_Bool(true));
|
||||
oc.addDescription("geometry.min-radius.fix.railways", "Processing", "Straighten edge geometries to avoid turning radii less than geometry.min-radius (only railways)");
|
||||
|
||||
oc.doRegister("geometry.junction-mismatch-threshold", new Option_Float(20));
|
||||
oc.addDescription("geometry.junction-mismatch-threshold", "Processing", "Warn if the junction shape is to far away from the original node position");
|
||||
|
||||
oc.doRegister("geometry.check-overlap", new Option_Float(0));
|
||||
oc.addDescription("geometry.check-overlap", "Processing", "Warn if edges overlap by more than the given threshold value");
|
||||
|
||||
oc.doRegister("geometry.check-overlap.vertical-threshold", new Option_Float(4));
|
||||
oc.addDescription("geometry.check-overlap.vertical-threshold", "Processing", "Ignore overlapping edges if they are separated vertically by the given threshold.");
|
||||
|
||||
oc.doRegister("geometry.avoid-overlap", new Option_Bool(true));
|
||||
oc.addDescription("geometry.avoid-overlap", "Processing", "Modify edge geometries to avoid overlap at junctions");
|
||||
|
||||
oc.doRegister("join-lanes", new Option_Bool(false));
|
||||
oc.addDescription("join-lanes", "Processing", "join adjacent lanes that have the same permissions and which do not admit lane-changing (sidewalks and disallowed lanes)");
|
||||
|
||||
oc.doRegister("ptline.match-dist", new Option_Float(100));
|
||||
oc.addDescription("ptline.match-dist", "Processing", "Matches stops outside the road network to the referencing pt line when below the given distance");
|
||||
// railway processing options
|
||||
|
||||
oc.doRegister("railway.topology.repair", new Option_Bool(false));
|
||||
oc.addDescription("railway.topology.repair", "Railway", "Repair topology of the railway network");
|
||||
|
||||
oc.doRegister("railway.topology.repair.connect-straight", new Option_Bool(false));
|
||||
oc.addDescription("railway.topology.repair.connect-straight", "Railway", "Allow bidiretional rail use wherever rails with opposite directions meet at a straight angle");
|
||||
|
||||
oc.doRegister("railway.topology.repair.stop-turn", new Option_Bool(false));
|
||||
oc.addDescription("railway.topology.repair.stop-turn", "Railway", "Add turn-around connections at all loaded stops.");
|
||||
|
||||
oc.doRegister("railway.topology.all-bidi", new Option_Bool(false));
|
||||
oc.addDescription("railway.topology.all-bidi", "Railway", "Make all rails usable in both direction");
|
||||
|
||||
oc.doRegister("railway.topology.all-bidi.input-file", new Option_FileName());
|
||||
oc.addDescription("railway.topology.all-bidi.input-file", "Railway", "Make all rails edge ids from FILE usable in both direction");
|
||||
|
||||
oc.doRegister("railway.topology.direction-priority", new Option_Bool(false));
|
||||
oc.addDescription("railway.topology.direction-priority", "Railway", "Set edge priority values based on estimated main direction");
|
||||
|
||||
oc.doRegister("railway.access-distance", new Option_Float(150.f));
|
||||
oc.addDescription("railway.access-distance", "Railway", "The search radius for finding suitable road accesses for rail stops");
|
||||
oc.addSynonyme("railway.access-distance", "osm.stop-output.footway-access-distance", true);
|
||||
|
||||
oc.doRegister("railway.max-accesses", new Option_Integer(5));
|
||||
oc.addDescription("railway.max-accesses", "Railway", "The maximum roud accesses registered per rail stops");
|
||||
oc.addSynonyme("railway.max-accesses", "osm.stop-output.footway-max-accesses", true);
|
||||
|
||||
oc.doRegister("railway.access-factor", new Option_Float(1.5));
|
||||
oc.addDescription("railway.access-factor", "Railway", "The walking length of the access is computed as air-line distance multiplied by FLOAT");
|
||||
oc.addSynonyme("railway.access-factor", "osm.stop-output.footway-access-factor", true);
|
||||
|
||||
oc.doRegister("ptstop-output.no-bidi", new Option_Bool(false));
|
||||
oc.addDescription("ptstop-output.no-bidi", "Processing", "Skips automatic generation of stops on the bidi-edge of a loaded stop");
|
||||
}
|
||||
|
||||
oc.doRegister("geometry.max-grade", new Option_Float(10));
|
||||
oc.addDescription("geometry.max-grade", "Processing", "Warn about edge geometries with a grade in % above FLOAT.");
|
||||
|
||||
oc.doRegister("geometry.max-grade.fix", new Option_Bool(true));
|
||||
oc.addDescription("geometry.max-grade.fix", "Processing", "Smooth edge edge geometries with a grade in above the warning threshold.");
|
||||
|
||||
oc.doRegister("offset.disable-normalization", new Option_Bool(false));
|
||||
oc.addSynonyme("offset.disable-normalization", "disable-normalize-node-positions", true);
|
||||
oc.addDescription("offset.disable-normalization", "Processing", "Turn off normalizing node positions");
|
||||
|
||||
oc.doRegister("offset.x", new Option_Float(0));
|
||||
oc.addSynonyme("offset.x", "x-offset-to-apply", true);
|
||||
oc.addDescription("offset.x", "Processing", "Adds FLOAT to net x-positions");
|
||||
|
||||
oc.doRegister("offset.y", new Option_Float(0));
|
||||
oc.addSynonyme("offset.y", "y-offset-to-apply", true);
|
||||
oc.addDescription("offset.y", "Processing", "Adds FLOAT to net y-positions");
|
||||
|
||||
oc.doRegister("offset.z", new Option_Float(0));
|
||||
oc.addDescription("offset.z", "Processing", "Adds FLOAT to net z-positions");
|
||||
|
||||
oc.doRegister("flip-y-axis", new Option_Bool(false));
|
||||
oc.addSynonyme("flip-y-axis", "flip-y");
|
||||
oc.addDescription("flip-y-axis", "Processing", "Flips the y-coordinate along zero");
|
||||
|
||||
oc.doRegister("roundabouts.guess", new Option_Bool(true));
|
||||
oc.addSynonyme("roundabouts.guess", "guess-roundabouts", true);
|
||||
oc.addDescription("roundabouts.guess", "Processing", "Enable roundabout-guessing");
|
||||
|
||||
oc.doRegister("opposites.guess", new Option_Bool(false));
|
||||
oc.addDescription("opposites.guess", "Processing", "Enable guessing of opposite direction lanes usable for overtaking");
|
||||
|
||||
oc.doRegister("opposites.guess.fix-lengths", new Option_Bool(false));
|
||||
oc.addDescription("opposites.guess.fix-lengths", "Processing", "Ensure that opposite edges have the same length");
|
||||
|
||||
oc.doRegister("fringe.guess", new Option_Bool(false));
|
||||
oc.addDescription("fringe.guess", "Processing", "Enable guessing of network fringe nodes");
|
||||
|
||||
oc.doRegister("lefthand", new Option_Bool(false));
|
||||
oc.addDescription("lefthand", "Processing", "Assumes left-hand traffic on the network");
|
||||
|
||||
oc.doRegister("edges.join", new Option_Bool(false));
|
||||
oc.addDescription("edges.join", "Processing",
|
||||
"Merges edges which connect the same nodes and are close to each other (recommended for VISSIM import)");
|
||||
|
||||
oc.doRegister("junctions.join", new Option_Bool(false));
|
||||
oc.addDescription("junctions.join", "Junctions",
|
||||
"Joins junctions that are close to each other (recommended for OSM import)");
|
||||
|
||||
oc.doRegister("junctions.join-dist", new Option_Float(10));
|
||||
oc.addDescription("junctions.join-dist", "Junctions",
|
||||
"Determines the maximal distance for joining junctions (defaults to 10)");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("junctions.join-exclude", new Option_StringVector());
|
||||
oc.addDescription("junctions.join-exclude", "Junctions", "Interprets STR[] as list of junctions to exclude from joining");
|
||||
|
||||
oc.doRegister("speed.offset", new Option_Float(0));
|
||||
oc.addDescription("speed.offset", "Processing", "Modifies all edge speeds by adding FLOAT");
|
||||
|
||||
oc.doRegister("speed.factor", new Option_Float(1));
|
||||
oc.addDescription("speed.factor", "Processing", "Modifies all edge speeds by multiplying by FLOAT");
|
||||
|
||||
oc.doRegister("speed.minimum", new Option_Float(0));
|
||||
oc.addDescription("speed.minimum", "Processing", "Modifies all edge speeds to at least FLOAT");
|
||||
|
||||
oc.doRegister("edges.join-tram-dist", new Option_Float(-1));
|
||||
oc.addDescription("edges.join-tram-dist", "Processing",
|
||||
"Joins tram edges into road lanes with similar geometry (within FLOAT distance)");
|
||||
}
|
||||
|
||||
oc.doRegister("junctions.corner-detail", new Option_Integer(5));
|
||||
oc.addDescription("junctions.corner-detail", "Junctions", "Generate INT intermediate points to smooth out intersection corners");
|
||||
|
||||
oc.doRegister("junctions.internal-link-detail", new Option_Integer(5));
|
||||
oc.addDescription("junctions.internal-link-detail", "Junctions", "Generate INT intermediate points to smooth out lanes within the intersection");
|
||||
|
||||
oc.doRegister("junctions.scurve-stretch", new Option_Float(0));
|
||||
oc.addDescription("junctions.scurve-stretch", "Junctions", "Generate longer intersections to allow for smooth s-curves when the number of lanes changes");
|
||||
|
||||
oc.doRegister("junctions.join-turns", new Option_Bool(false));
|
||||
oc.addDescription("junctions.join-turns", "Junctions",
|
||||
"Builds common edges for turning connections with common from- and to-edge. This causes discrepancies between geometrical length and assigned length due to averaging but enables lane-changing while turning");
|
||||
|
||||
oc.doRegister("junctions.limit-turn-speed", new Option_Float(5.5));
|
||||
oc.addDescription("junctions.limit-turn-speed", "Junctions",
|
||||
"Limits speed on junctions to an average lateral acceleration of at most FLOAT m/s^2)");
|
||||
|
||||
oc.doRegister("junctions.limit-turn-speed.min-angle", new Option_Float(15));
|
||||
oc.addDescription("junctions.limit-turn-speed.min-angle", "Junctions",
|
||||
"Do not limit turn speed for angular changes below FLOAT (degrees). The value is subtracted from the geometric angle before computing the turning radius.");
|
||||
|
||||
oc.doRegister("junctions.limit-turn-speed.min-angle.railway", new Option_Float(35));
|
||||
oc.addDescription("junctions.limit-turn-speed.min-angle.railway", "Junctions",
|
||||
"Do not limit turn speed for angular changes below FLOAT (degrees) on railway edges. The value is subtracted from the geometric angle before computing the turning radius.");
|
||||
|
||||
oc.doRegister("junctions.limit-turn-speed.warn.straight", new Option_Float(5));
|
||||
oc.addDescription("junctions.limit-turn-speed.warn.straight", "Junctions",
|
||||
"Warn about turn speed limits that reduce the speed of straight connections by more than FLOAT");
|
||||
|
||||
oc.doRegister("junctions.limit-turn-speed.warn.turn", new Option_Float(22));
|
||||
oc.addDescription("junctions.limit-turn-speed.warn.turn", "Junctions",
|
||||
"Warn about turn speed limits that reduce the speed of turning connections (no u-turns) by more than FLOAT");
|
||||
|
||||
|
||||
oc.doRegister("junctions.small-radius", new Option_Float(1.5));
|
||||
oc.addDescription("junctions.small-radius", "Junctions",
|
||||
"Default radius for junctions that do not require wide vehicle turns");
|
||||
|
||||
oc.doRegister("rectangular-lane-cut", new Option_Bool(false));
|
||||
oc.addDescription("rectangular-lane-cut", "Junctions", "Forces rectangular cuts between lanes and intersections");
|
||||
|
||||
oc.doRegister("check-lane-foes.roundabout", new Option_Bool(true));
|
||||
oc.addDescription("check-lane-foes.roundabout", "Junctions",
|
||||
"Allow driving onto a multi-lane road if there are foes on other lanes (at roundabouts)");
|
||||
|
||||
oc.doRegister("check-lane-foes.all", new Option_Bool(false));
|
||||
oc.addDescription("check-lane-foes.all", "Junctions",
|
||||
"Allow driving onto a multi-lane road if there are foes on other lanes (everywhere)");
|
||||
|
||||
oc.doRegister("sidewalks.guess", new Option_Bool(false));
|
||||
oc.addDescription("sidewalks.guess", "Pedestrian",
|
||||
"Guess pedestrian sidewalks based on edge speed");
|
||||
|
||||
oc.doRegister("sidewalks.guess.max-speed", new Option_Float((double) 13.89));
|
||||
oc.addDescription("sidewalks.guess.max-speed", "Pedestrian",
|
||||
"Add sidewalks for edges with a speed equal or below the given limit");
|
||||
|
||||
oc.doRegister("sidewalks.guess.min-speed", new Option_Float((double) 5.8));
|
||||
oc.addDescription("sidewalks.guess.min-speed", "Pedestrian",
|
||||
"Add sidewalks for edges with a speed above the given limit");
|
||||
|
||||
oc.doRegister("sidewalks.guess.from-permissions", new Option_Bool(false));
|
||||
oc.addDescription("sidewalks.guess.from-permissions", "Pedestrian",
|
||||
"Add sidewalks for edges that allow pedestrians on any of their lanes regardless of speed");
|
||||
|
||||
oc.doRegister("sidewalks.guess.exclude", new Option_StringVector());
|
||||
oc.addDescription("sidewalks.guess.exclude", "Pedestrian",
|
||||
"Do not guess sidewalks for the given list of edges");
|
||||
|
||||
oc.doRegister("bikelanes.guess", new Option_Bool(false));
|
||||
oc.addDescription("bikelanes.guess", "Bicycle",
|
||||
"Guess bike lanes based on edge speed");
|
||||
|
||||
oc.doRegister("bikelanes.guess.max-speed", new Option_Float((double) 22.22));
|
||||
oc.addDescription("bikelanes.guess.max-speed", "Bicycle",
|
||||
"Add bike lanes for edges with a speed equal or below the given limit");
|
||||
|
||||
oc.doRegister("bikelanes.guess.min-speed", new Option_Float((double) 5.8));
|
||||
oc.addDescription("bikelanes.guess.min-speed", "Bicycle",
|
||||
"Add bike lanes for edges with a speed above the given limit");
|
||||
|
||||
oc.doRegister("bikelanes.guess.from-permissions", new Option_Bool(false));
|
||||
oc.addDescription("bikelanes.guess.from-permissions", "Bicycle",
|
||||
"Add bike lanes for edges that allow bicycles on any of their lanes regardless of speed");
|
||||
|
||||
oc.doRegister("bikelanes.guess.exclude", new Option_StringVector());
|
||||
oc.addDescription("bikelanes.guess.exclude", "Bicycle",
|
||||
"Do not guess bikelanes for the given list of edges");
|
||||
|
||||
oc.doRegister("crossings.guess", new Option_Bool(false));
|
||||
oc.addDescription("crossings.guess", "Pedestrian",
|
||||
"Guess pedestrian crossings based on the presence of sidewalks");
|
||||
|
||||
oc.doRegister("crossings.guess.speed-threshold", new Option_Float(13.89));
|
||||
oc.addDescription("crossings.guess.speed-threshold", "Pedestrian",
|
||||
"At uncontrolled nodes, do not build crossings across edges with a speed above the threshold");
|
||||
|
||||
oc.doRegister("walkingareas", new Option_Bool(false));
|
||||
oc.addDescription("walkingareas", "Pedestrian", "Always build walking areas even if there are no crossings");
|
||||
|
||||
// tls setting options
|
||||
// explicit tls
|
||||
oc.doRegister("tls.set", new Option_StringVector());
|
||||
oc.addSynonyme("tls.set", "explicite-tls", true);
|
||||
oc.addDescription("tls.set", "TLS Building", "Interprets STR[] as list of junctions to be controlled by TLS");
|
||||
|
||||
oc.doRegister("tls.unset", new Option_StringVector());
|
||||
oc.addSynonyme("tls.unset", "explicite-no-tls", true);
|
||||
oc.addDescription("tls.unset", "TLS Building", "Interprets STR[] as list of junctions to be not controlled by TLS");
|
||||
|
||||
// tls-guessing
|
||||
oc.doRegister("tls.guess", new Option_Bool(false));
|
||||
oc.addSynonyme("tls.guess", "guess-tls", true);
|
||||
oc.addDescription("tls.guess", "TLS Building", "Turns on TLS guessing");
|
||||
|
||||
oc.doRegister("tls.guess.threshold", new Option_Float(250 / 3.6));
|
||||
oc.addDescription("tls.guess.threshold", "TLS Building", "Sets minimum value for the sum of all incoming lane speeds when guessing TLS");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("tls.taz-nodes", new Option_Bool(false));
|
||||
oc.addSynonyme("tls.taz-nodes", "tls-guess.district-nodes", true);
|
||||
oc.addDescription("tls.taz-nodes", "TLS Building", "Sets district nodes as tls-controlled"); // !!! describe
|
||||
}
|
||||
|
||||
oc.doRegister("tls.guess.joining", new Option_Bool(false));
|
||||
oc.addSynonyme("tls.guess.joining", "tls-guess.joining", true);
|
||||
oc.addDescription("tls.guess.joining", "TLS Building", "Includes node clusters into guess"); // !!! describe
|
||||
|
||||
oc.doRegister("tls.join", new Option_Bool(false));
|
||||
oc.addSynonyme("tls.join", "try-join-tls", true);
|
||||
oc.addDescription("tls.join", "TLS Building", "Tries to cluster tls-controlled nodes"); // !!! describe
|
||||
|
||||
oc.doRegister("tls.join-dist", new Option_Float(20));
|
||||
oc.addDescription("tls.join-dist", "TLS Building",
|
||||
"Determines the maximal distance for joining traffic lights (defaults to 20)");
|
||||
|
||||
oc.doRegister("tls.uncontrolled-within", new Option_Bool(false));
|
||||
oc.addDescription("tls.uncontrolled-within", "TLS Building",
|
||||
"Do not control edges that lie fully within a joined traffic light. This may cause collisions but allows old traffic light plans to be used");
|
||||
|
||||
oc.doRegister("tls.ignore-internal-junction-jam", new Option_Bool(false));
|
||||
oc.addDescription("tls.ignore-internal-junction-jam", "TLS Building",
|
||||
"Do not build mutually conflicting response matrix, potentially ignoring vehicles that are stuck at an internal junction when their phase has ended");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("tls.guess-signals", new Option_Bool(false));
|
||||
oc.addDescription("tls.guess-signals", "TLS Building", "Interprets tls nodes surrounding an intersection as signal positions for a larger TLS. This is typical pattern for OSM-derived networks");
|
||||
|
||||
oc.doRegister("tls.guess-signals.dist", new Option_Float(25));
|
||||
oc.addDescription("tls.guess-signals.dist", "TLS Building", "Distance for interpreting nodes as signal locations");
|
||||
}
|
||||
|
||||
|
||||
// computational
|
||||
oc.doRegister("tls.cycle.time", new Option_Integer(90));
|
||||
oc.addDescription("tls.cycle.time", "TLS Building", "Use INT as cycle duration");
|
||||
|
||||
oc.doRegister("tls.green.time", new Option_Integer(31));
|
||||
oc.addSynonyme("tls.green.time", "traffic-light-green", true);
|
||||
oc.addDescription("tls.green.time", "TLS Building", "Use INT as green phase duration");
|
||||
|
||||
oc.doRegister("tls.yellow.min-decel", 'D', new Option_Float(3.0));
|
||||
oc.addSynonyme("tls.yellow.min-decel", "min-decel", true);
|
||||
oc.addDescription("tls.yellow.min-decel", "TLS Building", "Defines smallest vehicle deceleration");
|
||||
|
||||
oc.doRegister("tls.yellow.patch-small", new Option_Bool(false));
|
||||
oc.addSynonyme("tls.yellow.patch-small", "patch-small-tyellow", true);
|
||||
oc.addDescription("tls.yellow.patch-small", "TLS Building", "Given yellow times are patched even if being too short");
|
||||
|
||||
oc.doRegister("tls.yellow.time", new Option_Integer(-1));
|
||||
oc.addSynonyme("tls.yellow.time", "traffic-light-yellow", true);
|
||||
oc.addDescription("tls.yellow.time", "TLS Building", "Set INT as fixed time for yellow phase durations");
|
||||
|
||||
oc.doRegister("tls.red.time", new Option_Integer(5));
|
||||
oc.addDescription("tls.red.time", "TLS Building", "Set INT as fixed time for red phase duration at traffic lights that do not have a conflicting flow");
|
||||
|
||||
oc.doRegister("tls.allred.time", new Option_Integer(0));
|
||||
oc.addDescription("tls.allred.time", "TLS Building", "Set INT as fixed time for intermediate red phase after every switch");
|
||||
|
||||
oc.doRegister("tls.minor-left.max-speed", new Option_Float(19.44)); // 70km/h
|
||||
oc.addDescription("tls.minor-left.max-speed", "TLS Building", "Use FLOAT as threshold for allowing left-turning vehicles to move in the same phase as oncoming straight-going vehicles");
|
||||
|
||||
oc.doRegister("tls.left-green.time", new Option_Integer(6));
|
||||
oc.addDescription("tls.left-green.time", "TLS Building", "Use INT as green phase duration for left turns (s). Setting this value to 0 disables additional left-turning phases");
|
||||
|
||||
oc.doRegister("tls.crossing-min.time", new Option_Integer(4));
|
||||
oc.addDescription("tls.crossing-min.time", "TLS Building", "Use INT as minimum green duration for pedestrian crossings (s).");
|
||||
|
||||
oc.doRegister("tls.crossing-clearance.time", new Option_Integer(5));
|
||||
oc.addDescription("tls.crossing-clearance.time", "TLS Building", "Use INT as clearance time for pedestrian crossings (s).");
|
||||
|
||||
oc.doRegister("tls.scramble.time", new Option_Integer(5));
|
||||
oc.addDescription("tls.scramble.time", "TLS Building", "Use INT as green phase duration for pedestrian scramble phase (s).");
|
||||
|
||||
// tls-shifts
|
||||
oc.doRegister("tls.half-offset", new Option_StringVector());
|
||||
oc.addSynonyme("tls.half-offset", "tl-logics.half-offset", true);
|
||||
oc.addDescription("tls.half-offset", "TLS Building", "TLSs in STR[] will be shifted by half-phase");
|
||||
|
||||
oc.doRegister("tls.quarter-offset", new Option_StringVector());
|
||||
oc.addSynonyme("tls.quarter-offset", "tl-logics.quarter-offset", true);
|
||||
oc.addDescription("tls.quarter-offset", "TLS Building", "TLSs in STR[] will be shifted by quarter-phase");
|
||||
|
||||
// tls type
|
||||
oc.doRegister("tls.default-type", new Option_String("static"));
|
||||
oc.addDescription("tls.default-type", "TLS Building", "TLSs with unspecified type will use STR as their algorithm");
|
||||
|
||||
oc.doRegister("tls.layout", new Option_String("opposites"));
|
||||
oc.addDescription("tls.layout", "TLS Building", "Set phase layout four grouping opposite directions or grouping all movements for one incoming edge ['opposites', 'incoming']");
|
||||
|
||||
oc.doRegister("tls.min-dur", new Option_Integer(5));
|
||||
oc.addDescription("tls.min-dur", "TLS Building", "Default minimum phase duration for traffic lights with variable phase length");
|
||||
|
||||
oc.doRegister("tls.max-dur", new Option_Integer(50));
|
||||
oc.addDescription("tls.max-dur", "TLS Building", "Default maximum phase duration for traffic lights with variable phase length");
|
||||
|
||||
oc.doRegister("tls.group-signals", new Option_Bool(false));
|
||||
oc.addDescription("tls.group-signals", "TLS Building", "Assign the same tls link index to connections that share the same states");
|
||||
|
||||
oc.doRegister("tls.ungroup-signals", new Option_Bool(false));
|
||||
oc.addDescription("tls.ungroup-signals", "TLS Building", "Assign a distinct tls link index to every connection");
|
||||
|
||||
// edge pruning
|
||||
oc.doRegister("keep-edges.min-speed", new Option_Float(-1));
|
||||
oc.addSynonyme("keep-edges.min-speed", "edges-min-speed", true);
|
||||
oc.addDescription("keep-edges.min-speed", "Edge Removal", "Only keep edges with speed in meters/second > FLOAT");
|
||||
|
||||
oc.doRegister("remove-edges.explicit", new Option_StringVector());
|
||||
oc.addSynonyme("remove-edges.explicit", "remove-edges");
|
||||
oc.addDescription("remove-edges.explicit", "Edge Removal", "Remove edges in STR[]");
|
||||
|
||||
oc.doRegister("keep-edges.explicit", new Option_StringVector());
|
||||
oc.addSynonyme("keep-edges.explicit", "keep-edges");
|
||||
oc.addDescription("keep-edges.explicit", "Edge Removal", "Only keep edges in STR[] or those which are kept due to other keep-edges or remove-edges options");
|
||||
|
||||
oc.doRegister("keep-edges.input-file", new Option_FileName());
|
||||
oc.addDescription("keep-edges.input-file", "Edge Removal", "Only keep edges in FILE (Each id on a single line. Selection files from SUMO-GUI are also supported) or those which are kept due to other keep-edges or remove-edges options");
|
||||
|
||||
oc.doRegister("remove-edges.input-file", new Option_FileName());
|
||||
oc.addDescription("remove-edges.input-file", "Edge Removal", "Remove edges in FILE. (Each id on a single line. Selection files from SUMO-GUI are also supported)");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("keep-edges.postload", new Option_Bool(false));
|
||||
oc.addDescription("keep-edges.postload", "Edge Removal", "Remove edges after joining");
|
||||
}
|
||||
|
||||
oc.doRegister("keep-edges.in-boundary", new Option_StringVector());
|
||||
oc.addDescription("keep-edges.in-boundary", "Edge Removal", "Only keep edges which are located within the given boundary (given either as CARTESIAN corner coordinates <xmin,ymin,xmax,ymax> or as polygon <x0,y0,x1,y1,...>)");
|
||||
|
||||
oc.doRegister("keep-edges.in-geo-boundary", new Option_StringVector());
|
||||
oc.addDescription("keep-edges.in-geo-boundary", "Edge Removal", "Only keep edges which are located within the given boundary (given either as GEODETIC corner coordinates <lon-min,lat-min,lon-max,lat-max> or as polygon <lon0,lat0,lon1,lat1,...>)");
|
||||
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("keep-edges.by-vclass", new Option_StringVector());
|
||||
oc.addDescription("keep-edges.by-vclass", "Edge Removal", "Only keep edges which allow one of the vclasss in STR[]");
|
||||
|
||||
oc.doRegister("remove-edges.by-vclass", new Option_StringVector());
|
||||
oc.addDescription("remove-edges.by-vclass", "Edge Removal", "Remove edges which allow only vclasses from STR[]");
|
||||
|
||||
oc.doRegister("keep-edges.by-type", new Option_StringVector());
|
||||
oc.addDescription("keep-edges.by-type", "Edge Removal", "Only keep edges where type is in STR[]");
|
||||
|
||||
oc.doRegister("keep-edges.components", new Option_Integer(0));
|
||||
oc.addDescription("keep-edges.components", "Edge Removal", "Only keep the INT largest weakly connected components");
|
||||
|
||||
oc.doRegister("remove-edges.by-type", new Option_StringVector());
|
||||
oc.addDescription("remove-edges.by-type", "Edge Removal", "Remove edges where type is in STR[]");
|
||||
|
||||
oc.doRegister("remove-edges.isolated", new Option_Bool(false));
|
||||
oc.addSynonyme("remove-edges.isolated", "remove-isolated", true);
|
||||
oc.addDescription("remove-edges.isolated", "Edge Removal", "Removes isolated edges");
|
||||
}
|
||||
|
||||
|
||||
// unregulated nodes options
|
||||
oc.doRegister("keep-nodes-unregulated", new Option_Bool(false));
|
||||
oc.addSynonyme("keep-nodes-unregulated", "keep-unregulated");
|
||||
oc.addDescription("keep-nodes-unregulated", "Unregulated Nodes", "All nodes will be unregulated");
|
||||
|
||||
oc.doRegister("keep-nodes-unregulated.explicit", new Option_StringVector());
|
||||
oc.addSynonyme("keep-nodes-unregulated.explicit", "keep-unregulated.explicit");
|
||||
oc.addSynonyme("keep-nodes-unregulated.explicit", "keep-unregulated.nodes", true);
|
||||
oc.addDescription("keep-nodes-unregulated.explicit", "Unregulated Nodes", "Do not regulate nodes in STR[]");
|
||||
|
||||
oc.doRegister("keep-nodes-unregulated.district-nodes", new Option_Bool(false));
|
||||
oc.addSynonyme("keep-nodes-unregulated.district-nodes", "keep-unregulated.district-nodes");
|
||||
oc.addDescription("keep-nodes-unregulated.district-nodes", "Unregulated Nodes", "Do not regulate district nodes");
|
||||
|
||||
// ramp guessing options
|
||||
if (!forNetgen) {
|
||||
oc.doRegister("ramps.guess", new Option_Bool(false));
|
||||
oc.addSynonyme("ramps.guess", "guess-ramps", true);
|
||||
oc.addDescription("ramps.guess", "Ramp Guessing", "Enable ramp-guessing");
|
||||
|
||||
oc.doRegister("ramps.guess-acceleration-lanes", new Option_Bool(true));
|
||||
oc.addDescription("ramps.guess-acceleration-lanes", "Ramp Guessing", "Guess on-ramps and mark acceleration lanes if they exist but do not add new lanes");
|
||||
|
||||
oc.doRegister("ramps.max-ramp-speed", new Option_Float(-1));
|
||||
oc.addSynonyme("ramps.max-ramp-speed", "ramp-guess.max-ramp-speed", true);
|
||||
oc.addDescription("ramps.max-ramp-speed", "Ramp Guessing", "Treat edges with speed > FLOAT as no ramps");
|
||||
|
||||
oc.doRegister("ramps.min-highway-speed", new Option_Float((double)(79 / 3.6)));
|
||||
oc.addSynonyme("ramps.min-highway-speed", "ramp-guess.min-highway-speed", true);
|
||||
oc.addDescription("ramps.min-highway-speed", "Ramp Guessing", "Treat edges with speed < FLOAT as no highways");
|
||||
|
||||
oc.doRegister("ramps.ramp-length", new Option_Float(100));
|
||||
oc.addSynonyme("ramps.ramp-length", "ramp-guess.ramp-length", true);
|
||||
oc.addDescription("ramps.ramp-length", "Ramp Guessing", "Use FLOAT as ramp-length");
|
||||
|
||||
//The Weaving Length Limit for Short Free Onramps, Chiu Liu, Zhongren WangPhD even suggest 70m
|
||||
oc.doRegister("ramps.min-weave-length", new Option_Float(50));
|
||||
oc.addDescription("ramps.min-weave-length", "Ramp Guessing", "Use FLOAT as minimum ramp-length");
|
||||
|
||||
oc.doRegister("ramps.set", new Option_StringVector());
|
||||
oc.addSynonyme("ramps.set", "ramp-guess.explicite", true);
|
||||
oc.addDescription("ramps.set", "Ramp Guessing", "Tries to handle the given edges as ramps");
|
||||
|
||||
oc.doRegister("ramps.unset", new Option_StringVector());
|
||||
oc.addDescription("ramps.unset", "Ramp Guessing", "Do not consider the given edges as ramps");
|
||||
|
||||
oc.doRegister("ramps.no-split", new Option_Bool(false));
|
||||
oc.addSynonyme("ramps.no-split", "ramp-guess.no-split", true);
|
||||
oc.addDescription("ramps.no-split", "Ramp Guessing", "Avoids edge splitting");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBFrame::checkOptions() {
|
||||
OptionsCont& oc = OptionsCont::getOptions();
|
||||
bool ok = true;
|
||||
//
|
||||
if (!SUMOXMLDefinitions::TrafficLightTypes.hasString(oc.getString("tls.default-type"))) {
|
||||
WRITE_ERROR("unsupported value '" + oc.getString("tls.default-type") + "' for option '--tls.default-type'");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.isSet("keep-edges.in-boundary") && oc.isSet("keep-edges.in-geo-boundary")) {
|
||||
WRITE_ERROR("only one of the options 'keep-edges.in-boundary' or 'keep-edges.in-geo-boundary' may be given");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.getBool("no-internal-links") && oc.getBool("crossings.guess")) {
|
||||
WRITE_ERROR("only one of the options 'no-internal-links' or 'crossings.guess' may be given");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.getBool("no-internal-links") && oc.getBool("walkingareas")) {
|
||||
WRITE_ERROR("only one of the options 'no-internal-links' or 'walkareas' may be given");
|
||||
ok = false;
|
||||
}
|
||||
if (!oc.isDefault("tls.green.time") && !oc.isDefault("tls.cycle.time")) {
|
||||
WRITE_ERROR("only one of the options 'tls.green.time' or 'tls.cycle.time' may be given");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.getInt("junctions.internal-link-detail") < 2) {
|
||||
WRITE_ERROR("junctions.internal-link-detail must >= 2");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.getFloat("junctions.scurve-stretch") > 0) {
|
||||
if (oc.getBool("no-internal-links")) {
|
||||
WRITE_WARNING("option 'junctions.scurve-stretch' requires internal lanes to work. Option '--no-internal-links' was disabled.");
|
||||
}
|
||||
// make sure the option is set so heuristics cannot ignore it
|
||||
oc.set("no-internal-links", "false");
|
||||
}
|
||||
if (oc.getFloat("junctions.small-radius") > oc.getFloat("default.junctions.radius") && oc.getFloat("default.junctions.radius") >= 0) {
|
||||
if (!oc.isDefault("junctions.small-radius")) {
|
||||
WRITE_ERROR("option 'default.junctions.radius' cannot be smaller than option 'junctions.small-radius'");
|
||||
ok = false;
|
||||
} else {
|
||||
oc.set("junctions.small-radius", oc.getValueString("default.junctions.radius"));
|
||||
}
|
||||
}
|
||||
if (oc.getString("tls.layout") != "opposites" && oc.getString("tls.layout") != "incoming") {
|
||||
WRITE_ERROR("tls.layout must be 'opposites' or 'incoming'");
|
||||
ok = false;
|
||||
}
|
||||
if (!oc.isDefault("default.right-of-way") &&
|
||||
!SUMOXMLDefinitions::RightOfWayValues.hasString(oc.getString("default.right-of-way"))) {
|
||||
WRITE_ERROR("default.right-of-way must be one of '" + toString(SUMOXMLDefinitions::RightOfWayValues.getStrings()) + "'");
|
||||
ok = false;
|
||||
}
|
||||
if (oc.isDefault("railway.topology.repair") && oc.getBool("railway.topology.repair.connect-straight")) {
|
||||
oc.set("railway.topology.repair", "true");
|
||||
}
|
||||
if (oc.isDefault("railway.topology.all-bidi") && !oc.isDefault("railway.topology.all-bidi.input-file")) {
|
||||
oc.set("railway.topology.all-bidi", "true");
|
||||
}
|
||||
if (oc.isDefault("railway.topology.repair.stop-turn") && !oc.isDefault("railway.topology.repair")) {
|
||||
oc.set("railway.topology.repair.stop-turn", "true");
|
||||
}
|
||||
if (!SUMOXMLDefinitions::LaneSpreadFunctions.hasString(oc.getString("default.spreadtype"))) {
|
||||
WRITE_ERROR("Unknown value for default.spreadtype '" + oc.getString("default.spreadtype") + "'.");
|
||||
ok = false;
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,58 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBFrame.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Michael Behrisch
|
||||
/// @date 09.05.2011
|
||||
///
|
||||
// Sets and checks options for netbuild
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBTypeCont.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBNode.h"
|
||||
#include "NBTrafficLightLogicCont.h"
|
||||
#include "NBDistrictCont.h"
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBFrame
|
||||
* @brief Sets and checks options for netbuild
|
||||
*/
|
||||
class NBFrame {
|
||||
public:
|
||||
/** @brief Inserts options used by the network converter
|
||||
* @param[in] forNetgen Whether netconvert options shall be omitted
|
||||
*/
|
||||
static void fillOptions(bool forNetgen);
|
||||
|
||||
|
||||
/** @brief Checks set options from the OptionsCont-singleton for being valid
|
||||
* @return Whether needed (netbuild) options are set and have proper values
|
||||
*/
|
||||
static bool checkOptions();
|
||||
|
||||
|
||||
};
|
|
@ -1,386 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2011-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBHeightMapper.cpp
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Laura Bieker
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2011
|
||||
///
|
||||
// Set z-values for all network positions based on data from a height map
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/geom/GeomHelper.h>
|
||||
#include "NBHeightMapper.h"
|
||||
#include <utils/geom/GeoConvHelper.h>
|
||||
#include <utils/common/RGBColor.h>
|
||||
|
||||
#ifdef HAVE_GDAL
|
||||
#if __GNUC__ > 3
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wpedantic"
|
||||
#endif
|
||||
#include <ogrsf_frmts.h>
|
||||
#include <ogr_api.h>
|
||||
#include <gdal_priv.h>
|
||||
#if __GNUC__ > 3
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// ===========================================================================
|
||||
// static members
|
||||
// ===========================================================================
|
||||
NBHeightMapper NBHeightMapper::myInstance;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBHeightMapper::NBHeightMapper():
|
||||
myRTree(&Triangle::addSelf) {
|
||||
}
|
||||
|
||||
|
||||
NBHeightMapper::~NBHeightMapper() {
|
||||
clearData();
|
||||
}
|
||||
|
||||
|
||||
const NBHeightMapper&
|
||||
NBHeightMapper::get() {
|
||||
return myInstance;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBHeightMapper::ready() const {
|
||||
return myRasters.size() > 0 || myTriangles.size() > 0;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBHeightMapper::getZ(const Position& geo) const {
|
||||
if (!ready()) {
|
||||
WRITE_WARNING("Cannot supply height since no height data was loaded");
|
||||
return 0;
|
||||
}
|
||||
for (auto& item : myRasters) {
|
||||
const Boundary& boundary = item.first;
|
||||
int16_t* raster = item.second;
|
||||
double result = -1e6;
|
||||
if (boundary.around(geo)) {
|
||||
const int xSize = int((boundary.xmax() - boundary.xmin()) / mySizeOfPixel.x() + .5);
|
||||
const double normX = (geo.x() - boundary.xmin()) / mySizeOfPixel.x();
|
||||
const double normY = (geo.y() - boundary.ymax()) / mySizeOfPixel.y();
|
||||
PositionVector corners;
|
||||
corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 0.5, raster[(int)normY * xSize + (int)normX]));
|
||||
if (normX - floor(normX) > 0.5) {
|
||||
corners.push_back(Position(floor(normX) + 1.5, floor(normY) + 0.5, raster[(int)normY * xSize + (int)normX + 1]));
|
||||
} else {
|
||||
corners.push_back(Position(floor(normX) - 0.5, floor(normY) + 0.5, raster[(int)normY * xSize + (int)normX - 1]));
|
||||
}
|
||||
if (normY - floor(normY) > 0.5) {
|
||||
corners.push_back(Position(floor(normX) + 0.5, floor(normY) + 1.5, raster[((int)normY + 1) * xSize + (int)normX]));
|
||||
} else {
|
||||
corners.push_back(Position(floor(normX) + 0.5, floor(normY) - 0.5, raster[((int)normY - 1) * xSize + (int)normX]));
|
||||
}
|
||||
result = Triangle(corners).getZ(Position(normX, normY));
|
||||
}
|
||||
if (result > -1e5 && result < 1e5) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
// coordinates in degrees hence a small search window
|
||||
float minB[2];
|
||||
float maxB[2];
|
||||
minB[0] = (float)geo.x() - 0.00001f;
|
||||
minB[1] = (float)geo.y() - 0.00001f;
|
||||
maxB[0] = (float)geo.x() + 0.00001f;
|
||||
maxB[1] = (float)geo.y() + 0.00001f;
|
||||
QueryResult queryResult;
|
||||
int hits = myRTree.Search(minB, maxB, queryResult);
|
||||
Triangles result = queryResult.triangles;
|
||||
assert(hits == (int)result.size());
|
||||
UNUSED_PARAMETER(hits); // only used for assertion
|
||||
|
||||
for (Triangles::iterator it = result.begin(); it != result.end(); it++) {
|
||||
const Triangle* triangle = *it;
|
||||
if (triangle->contains(geo)) {
|
||||
return triangle->getZ(geo);
|
||||
}
|
||||
}
|
||||
WRITE_WARNING("Could not get height data for coordinate " + toString(geo));
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHeightMapper::addTriangle(PositionVector corners) {
|
||||
Triangle* triangle = new Triangle(corners);
|
||||
myTriangles.push_back(triangle);
|
||||
Boundary b = corners.getBoxBoundary();
|
||||
const float cmin[2] = {(float) b.xmin(), (float) b.ymin()};
|
||||
const float cmax[2] = {(float) b.xmax(), (float) b.ymax()};
|
||||
myRTree.Insert(cmin, cmax, triangle);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHeightMapper::loadIfSet(OptionsCont& oc) {
|
||||
if (oc.isSet("heightmap.geotiff")) {
|
||||
// parse file(s)
|
||||
std::vector<std::string> files = oc.getStringVector("heightmap.geotiff");
|
||||
for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
|
||||
PROGRESS_BEGIN_MESSAGE("Parsing from GeoTIFF '" + *file + "'");
|
||||
int numFeatures = myInstance.loadTiff(*file);
|
||||
MsgHandler::getMessageInstance()->endProcessMsg(
|
||||
" done (parsed " + toString(numFeatures) +
|
||||
" features, Boundary: " + toString(myInstance.getBoundary()) + ").");
|
||||
}
|
||||
}
|
||||
if (oc.isSet("heightmap.shapefiles")) {
|
||||
// parse file(s)
|
||||
std::vector<std::string> files = oc.getStringVector("heightmap.shapefiles");
|
||||
for (std::vector<std::string>::const_iterator file = files.begin(); file != files.end(); ++file) {
|
||||
PROGRESS_BEGIN_MESSAGE("Parsing from shape-file '" + *file + "'");
|
||||
int numFeatures = myInstance.loadShapeFile(*file);
|
||||
MsgHandler::getMessageInstance()->endProcessMsg(
|
||||
" done (parsed " + toString(numFeatures) +
|
||||
" features, Boundary: " + toString(myInstance.getBoundary()) + ").");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBHeightMapper::loadShapeFile(const std::string& file) {
|
||||
#ifdef HAVE_GDAL
|
||||
#if GDAL_VERSION_MAJOR < 2
|
||||
OGRRegisterAll();
|
||||
OGRDataSource* ds = OGRSFDriverRegistrar::Open(file.c_str(), FALSE);
|
||||
#else
|
||||
GDALAllRegister();
|
||||
GDALDataset* ds = (GDALDataset*)GDALOpenEx(file.c_str(), GDAL_OF_VECTOR | GA_ReadOnly, nullptr, nullptr, nullptr);
|
||||
#endif
|
||||
if (ds == nullptr) {
|
||||
throw ProcessError("Could not open shape file '" + file + "'.");
|
||||
}
|
||||
|
||||
// begin file parsing
|
||||
OGRLayer* layer = ds->GetLayer(0);
|
||||
layer->ResetReading();
|
||||
|
||||
// triangle coordinates are stored in WGS84 and later matched with network coordinates in WGS84
|
||||
// build coordinate transformation
|
||||
OGRSpatialReference* sr_src = layer->GetSpatialRef();
|
||||
OGRSpatialReference sr_dest;
|
||||
sr_dest.SetWellKnownGeogCS("WGS84");
|
||||
OGRCoordinateTransformation* toWGS84 = OGRCreateCoordinateTransformation(sr_src, &sr_dest);
|
||||
if (toWGS84 == nullptr) {
|
||||
WRITE_WARNING("Could not create geocoordinates converter; check whether proj.4 is installed.");
|
||||
}
|
||||
|
||||
int numFeatures = 0;
|
||||
OGRFeature* feature;
|
||||
layer->ResetReading();
|
||||
while ((feature = layer->GetNextFeature()) != nullptr) {
|
||||
OGRGeometry* geom = feature->GetGeometryRef();
|
||||
assert(geom != 0);
|
||||
|
||||
// @todo gracefull handling of shapefiles with unexpected contents or any error handling for that matter
|
||||
assert(std::string(geom->getGeometryName()) == std::string("POLYGON"));
|
||||
// try transform to wgs84
|
||||
geom->transform(toWGS84);
|
||||
OGRLinearRing* cgeom = ((OGRPolygon*) geom)->getExteriorRing();
|
||||
// assume TIN with with 4 points and point0 == point3
|
||||
assert(cgeom->getNumPoints() == 4);
|
||||
PositionVector corners;
|
||||
for (int j = 0; j < 3; j++) {
|
||||
Position pos((double) cgeom->getX(j), (double) cgeom->getY(j), (double) cgeom->getZ(j));
|
||||
corners.push_back(pos);
|
||||
myBoundary.add(pos);
|
||||
}
|
||||
addTriangle(corners);
|
||||
numFeatures++;
|
||||
|
||||
/*
|
||||
OGRwkbGeometryType gtype = geom->getGeometryType();
|
||||
switch (gtype) {
|
||||
case wkbPolygon: {
|
||||
break;
|
||||
}
|
||||
case wkbPoint: {
|
||||
WRITE_WARNING("got wkbPoint");
|
||||
break;
|
||||
}
|
||||
case wkbLineString: {
|
||||
WRITE_WARNING("got wkbLineString");
|
||||
break;
|
||||
}
|
||||
case wkbMultiPoint: {
|
||||
WRITE_WARNING("got wkbMultiPoint");
|
||||
break;
|
||||
}
|
||||
case wkbMultiLineString: {
|
||||
WRITE_WARNING("got wkbMultiLineString");
|
||||
break;
|
||||
}
|
||||
case wkbMultiPolygon: {
|
||||
WRITE_WARNING("got wkbMultiPolygon");
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WRITE_WARNING("Unsupported shape type occurred");
|
||||
break;
|
||||
}
|
||||
*/
|
||||
OGRFeature::DestroyFeature(feature);
|
||||
}
|
||||
#if GDAL_VERSION_MAJOR < 2
|
||||
OGRDataSource::DestroyDataSource(ds);
|
||||
#else
|
||||
GDALClose(ds);
|
||||
#endif
|
||||
OCTDestroyCoordinateTransformation(reinterpret_cast<OGRCoordinateTransformationH>(toWGS84));
|
||||
OGRCleanupAll();
|
||||
return numFeatures;
|
||||
#else
|
||||
UNUSED_PARAMETER(file);
|
||||
WRITE_ERROR("Cannot load shape file since SUMO was compiled without GDAL support.");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBHeightMapper::loadTiff(const std::string& file) {
|
||||
#ifdef HAVE_GDAL
|
||||
GDALAllRegister();
|
||||
GDALDataset* poDataset = (GDALDataset*)GDALOpen(file.c_str(), GA_ReadOnly);
|
||||
if (poDataset == 0) {
|
||||
WRITE_ERROR("Cannot load GeoTIFF file.");
|
||||
return 0;
|
||||
}
|
||||
Boundary boundary;
|
||||
const int xSize = poDataset->GetRasterXSize();
|
||||
const int ySize = poDataset->GetRasterYSize();
|
||||
double adfGeoTransform[6];
|
||||
if (poDataset->GetGeoTransform(adfGeoTransform) == CE_None) {
|
||||
Position topLeft(adfGeoTransform[0], adfGeoTransform[3]);
|
||||
mySizeOfPixel.set(adfGeoTransform[1], adfGeoTransform[5]);
|
||||
const double horizontalSize = xSize * mySizeOfPixel.x();
|
||||
const double verticalSize = ySize * mySizeOfPixel.y();
|
||||
boundary.add(topLeft);
|
||||
boundary.add(topLeft.x() + horizontalSize, topLeft.y() + verticalSize);
|
||||
} else {
|
||||
WRITE_ERROR("Could not parse geo information from " + file + ".");
|
||||
return 0;
|
||||
}
|
||||
const int picSize = xSize * ySize;
|
||||
int16_t* raster = (int16_t*)CPLMalloc(sizeof(int16_t) * picSize);
|
||||
for (int i = 1; i <= poDataset->GetRasterCount(); i++) {
|
||||
GDALRasterBand* poBand = poDataset->GetRasterBand(i);
|
||||
if (poBand->GetColorInterpretation() != GCI_GrayIndex) {
|
||||
WRITE_ERROR("Unknown color band in " + file + ".");
|
||||
clearData();
|
||||
break;
|
||||
}
|
||||
if (poBand->GetRasterDataType() != GDT_Int16) {
|
||||
WRITE_ERROR("Unknown data type in " + file + ".");
|
||||
clearData();
|
||||
break;
|
||||
}
|
||||
assert(xSize == poBand->GetXSize() && ySize == poBand->GetYSize());
|
||||
if (poBand->RasterIO(GF_Read, 0, 0, xSize, ySize, raster, xSize, ySize, GDT_Int16, 0, 0) == CE_Failure) {
|
||||
WRITE_ERROR("Failure in reading " + file + ".");
|
||||
clearData();
|
||||
break;
|
||||
}
|
||||
}
|
||||
GDALClose(poDataset);
|
||||
myRasters.push_back(std::make_pair(boundary, raster));
|
||||
return picSize;
|
||||
#else
|
||||
UNUSED_PARAMETER(file);
|
||||
WRITE_ERROR("Cannot load GeoTIFF file since SUMO was compiled without GDAL support.");
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHeightMapper::clearData() {
|
||||
for (Triangles::iterator it = myTriangles.begin(); it != myTriangles.end(); it++) {
|
||||
delete *it;
|
||||
}
|
||||
myTriangles.clear();
|
||||
#ifdef HAVE_GDAL
|
||||
for (auto& item : myRasters) {
|
||||
CPLFree(item.second);
|
||||
}
|
||||
myRasters.clear();
|
||||
#endif
|
||||
myBoundary.reset();
|
||||
}
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// Triangle member methods
|
||||
// ===========================================================================
|
||||
NBHeightMapper::Triangle::Triangle(const PositionVector& corners):
|
||||
myCorners(corners) {
|
||||
assert(myCorners.size() == 3);
|
||||
// @todo assert non-colinearity
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHeightMapper::Triangle::addSelf(const QueryResult& queryResult) const {
|
||||
queryResult.triangles.push_back(this);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBHeightMapper::Triangle::contains(const Position& pos) const {
|
||||
return myCorners.around(pos);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBHeightMapper::Triangle::getZ(const Position& geo) const {
|
||||
// en.wikipedia.org/wiki/Line-plane_intersection
|
||||
Position p0 = myCorners.front();
|
||||
Position line(0, 0, 1);
|
||||
p0.sub(geo); // p0 - l0
|
||||
Position normal = normalVector();
|
||||
return p0.dotProduct(normal) / line.dotProduct(normal);
|
||||
}
|
||||
|
||||
|
||||
Position
|
||||
NBHeightMapper::Triangle::normalVector() const {
|
||||
// @todo maybe cache result to avoid multiple computations?
|
||||
Position side1 = myCorners[1] - myCorners[0];
|
||||
Position side2 = myCorners[2] - myCorners[0];
|
||||
return side1.crossProduct(side2);
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,194 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2011-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBHeightMapper.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Laura Bieker
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2011
|
||||
///
|
||||
// Set z-values for all network positions based on data from a height map
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#ifdef WIN32
|
||||
typedef __int16 int16_t;
|
||||
#else
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include <string>
|
||||
#include <foreign/rtree/RTree.h>
|
||||
#include <utils/geom/PositionVector.h>
|
||||
#include <utils/geom/Boundary.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
|
||||
#define TRIANGLE_RTREE_QUAL RTree<NBHeightMapper::Triangle*, NBHeightMapper::Triangle, float, 2, NBHeightMapper::QueryResult>
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OptionsCont;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBHeightMapper
|
||||
* @brief Set z-values for all network positions based on data from a height map
|
||||
*
|
||||
* Importing data from '.shp'-files works only if SUMO was compiled with GDAL-support.
|
||||
* If not, an error message is generated.
|
||||
*/
|
||||
class NBHeightMapper {
|
||||
|
||||
friend class NBHeightMapperTest;
|
||||
|
||||
public:
|
||||
/** @brief loads height map data if any loading options are set
|
||||
*
|
||||
* @param[in] oc The options container to get further options from
|
||||
* @exception ProcessError if something fails
|
||||
*/
|
||||
static void loadIfSet(OptionsCont& oc);
|
||||
|
||||
/// @brief return the singleton instance (maybe 0)
|
||||
static const NBHeightMapper& get();
|
||||
|
||||
/// @brief returns whether the NBHeightMapper has data
|
||||
bool ready() const;
|
||||
|
||||
/// @brief returns the convex boundary of all known triangles
|
||||
const Boundary& getBoundary() {
|
||||
return myInstance.myBoundary;
|
||||
}
|
||||
|
||||
/// @brief returns height for the given geo coordinate (WGS84)
|
||||
double getZ(const Position& geo) const;
|
||||
|
||||
class QueryResult;
|
||||
/* @brief content class for the rtree. Since we wish to be able to use the
|
||||
* rtree for spatial querying we have to jump through some minor hoops:
|
||||
* We let each found triangle callback the NBHeightMapper and add itself the
|
||||
* the query result
|
||||
* */
|
||||
class Triangle {
|
||||
|
||||
public:
|
||||
Triangle(const PositionVector& corners);
|
||||
~Triangle() {};
|
||||
|
||||
/// @brief callback for RTree search
|
||||
void addSelf(const QueryResult& queryResult) const;
|
||||
|
||||
/// @brief checks whether pos lies within triangle (only checks x,y)
|
||||
bool contains(const Position& pos) const;
|
||||
|
||||
/// @brief returns the projection of the give geoCoordinate (WGS84) onto triangle plane
|
||||
double getZ(const Position& geo) const;
|
||||
|
||||
/// @brief returns the normal vector for this triangles plane
|
||||
Position normalVector() const;
|
||||
|
||||
/// @brief the corners of the triangle
|
||||
PositionVector myCorners;
|
||||
|
||||
};
|
||||
|
||||
typedef std::vector<const Triangle*> Triangles;
|
||||
|
||||
/// @brief class for cirumventing the const-restriction of RTree::Search-context
|
||||
class QueryResult {
|
||||
public:
|
||||
QueryResult() {};
|
||||
~QueryResult() {};
|
||||
// @brief method not realy const
|
||||
void add(Triangle* triangle) const {
|
||||
triangles.push_back(triangle);
|
||||
};
|
||||
mutable Triangles triangles;
|
||||
};
|
||||
|
||||
private:
|
||||
/// @brief the singleton instance
|
||||
static NBHeightMapper myInstance;
|
||||
|
||||
Triangles myTriangles;
|
||||
|
||||
/// @brief The RTree for spatial queries
|
||||
TRIANGLE_RTREE_QUAL myRTree;
|
||||
|
||||
/// @brief raster height information in m for all loaded files
|
||||
std::vector<std::pair<Boundary, int16_t*> > myRasters;
|
||||
|
||||
/// @brief dimensions of one pixel in raster data
|
||||
Position mySizeOfPixel;
|
||||
|
||||
/// @brief convex boundary of all known triangles;
|
||||
Boundary myBoundary;
|
||||
|
||||
private:
|
||||
/// @brief private constructor and destructor (Singleton)
|
||||
NBHeightMapper();
|
||||
~NBHeightMapper();
|
||||
|
||||
/// @brief adds one triangles worth of height data
|
||||
void addTriangle(PositionVector corners);
|
||||
|
||||
/** @brief load height data from Arcgis-shape file and returns the number of parsed features
|
||||
* @return The number of parsed features
|
||||
* @throws ProcessError
|
||||
*/
|
||||
int loadShapeFile(const std::string& file);
|
||||
|
||||
/** @brief load height data from GeoTIFF file and returns the number of non void pixels
|
||||
* @return The number of valid pixels
|
||||
* @throws ProcessError
|
||||
*/
|
||||
int loadTiff(const std::string& file);
|
||||
|
||||
/// @brief clears loaded data
|
||||
void clearData();
|
||||
|
||||
/// @brief Invalidated copy constructor.
|
||||
NBHeightMapper(const NBHeightMapper&);
|
||||
|
||||
/// @brief Invalidated assignment operator.
|
||||
NBHeightMapper& operator=(const NBHeightMapper&);
|
||||
|
||||
};
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// RTree specialization for speedup and avoiding warnings (ripped from SUMORTree.h)
|
||||
// ===========================================================================
|
||||
template<>
|
||||
inline float TRIANGLE_RTREE_QUAL::RectSphericalVolume(Rect* a_rect) {
|
||||
ASSERT(a_rect);
|
||||
const float extent0 = a_rect->m_max[0] - a_rect->m_min[0];
|
||||
const float extent1 = a_rect->m_max[1] - a_rect->m_min[1];
|
||||
return .78539816f * (extent0 * extent0 + extent1 * extent1);
|
||||
}
|
||||
|
||||
template<>
|
||||
inline TRIANGLE_RTREE_QUAL::Rect TRIANGLE_RTREE_QUAL::CombineRect(Rect* a_rectA, Rect* a_rectB) {
|
||||
ASSERT(a_rectA && a_rectB);
|
||||
Rect newRect;
|
||||
newRect.m_min[0] = rtree_min(a_rectA->m_min[0], a_rectB->m_min[0]);
|
||||
newRect.m_max[0] = rtree_max(a_rectA->m_max[0], a_rectB->m_max[0]);
|
||||
newRect.m_min[1] = rtree_min(a_rectA->m_min[1], a_rectB->m_min[1]);
|
||||
newRect.m_max[1] = rtree_max(a_rectA->m_max[1], a_rectB->m_max[1]);
|
||||
return newRect;
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBHelpers.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// Some mathematical helper methods
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
#include <sstream>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
//#include <iomanip>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include <utils/common/StringTokenizer.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include <utils/geom/Position.h>
|
||||
#include <utils/geom/GeomHelper.h>
|
||||
#include "NBNode.h"
|
||||
#include "NBHelpers.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
double
|
||||
NBHelpers::relAngle(double angle1, double angle2) {
|
||||
angle2 -= angle1;
|
||||
while (angle2 > 180.) {
|
||||
angle2 -= 360.;
|
||||
}
|
||||
while (angle2 < -180.) {
|
||||
angle2 += 360.;
|
||||
}
|
||||
return angle2;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBHelpers::normRelAngle(double angle1, double angle2) {
|
||||
double rel = relAngle(angle1, angle2);
|
||||
if (rel + NUMERICAL_EPS >= 180) {
|
||||
return -180;
|
||||
} else {
|
||||
return rel;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
NBHelpers::normalIDRepresentation(const std::string& id) {
|
||||
std::stringstream strm1(id);
|
||||
long numid;
|
||||
strm1 >> numid;
|
||||
std::stringstream strm2;
|
||||
strm2 << numid;
|
||||
return strm2.str();
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBHelpers::distance(NBNode* node1, NBNode* node2) {
|
||||
return node1->getPosition().distanceTo(node2->getPosition());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHelpers::loadEdgesFromFile(const std::string& file, std::set<std::string>& into) {
|
||||
std::ifstream strm(file.c_str());
|
||||
if (!strm.good()) {
|
||||
throw ProcessError("Could not load names of edges too keep from '" + file + "'.");
|
||||
}
|
||||
while (strm.good()) {
|
||||
std::string name;
|
||||
strm >> name;
|
||||
into.insert(name);
|
||||
// maybe we're loading an edge-selection
|
||||
if (StringUtils::startsWith(name, "edge:")) {
|
||||
into.insert(name.substr(5));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBHelpers::loadPrefixedIDsFomFile(const std::string& file, const std::string prefix, std::set<std::string>& into) {
|
||||
std::ifstream strm(file.c_str());
|
||||
if (!strm.good()) {
|
||||
throw ProcessError("Could not load IDs from '" + file + "'.");
|
||||
}
|
||||
while (strm.good()) {
|
||||
std::string prefixedID;
|
||||
strm >> prefixedID;
|
||||
if (StringUtils::startsWith(prefixedID, prefix)) {
|
||||
into.insert(prefixedID.substr(prefix.size()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NBHelpers::interpretLaneID(const std::string& lane_id, std::string& edge_id, int& index) {
|
||||
// assume lane_id = edge_id + '_' + index
|
||||
const std::string::size_type sep_index = lane_id.rfind('_');
|
||||
if (sep_index == std::string::npos) {
|
||||
WRITE_ERROR("Invalid lane id '" + lane_id + "' (missing '_').");
|
||||
}
|
||||
edge_id = lane_id.substr(0, sep_index);
|
||||
std::string index_string = lane_id.substr(sep_index + 1);
|
||||
try {
|
||||
index = StringUtils::toInt(index_string);
|
||||
} catch (NumberFormatException&) {
|
||||
WRITE_ERROR("Invalid lane index '" + index_string + "' for lane '" + lane_id + "'.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,70 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBHelpers.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// Some mathematical helper methods
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <set>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBNode;
|
||||
class Position;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBHelpers
|
||||
* Some mathmatical methods for the computation of angles
|
||||
*/
|
||||
class NBHelpers {
|
||||
public:
|
||||
/// @brief computes the relative angle between the two angles
|
||||
static double relAngle(double angle1, double angle2);
|
||||
|
||||
/// @brief ensure that reverse relAngles (>=179.999) always count as turnarounds (-180)
|
||||
static double normRelAngle(double angle1, double angle2);
|
||||
|
||||
/// @brief converts the numerical id to its "normal" string representation
|
||||
static std::string normalIDRepresentation(const std::string& id);
|
||||
|
||||
/// @brief returns the distance between both nodes
|
||||
static double distance(NBNode* node1, NBNode* node2);
|
||||
|
||||
/// @brief Add edge ids defined in file (either ID or edge:ID per line) into the given set
|
||||
static void loadEdgesFromFile(const std::string& file, std::set<std::string>& into);
|
||||
|
||||
/// @brief Add prefixed ids defined in file
|
||||
static void loadPrefixedIDsFomFile(const std::string& file, const std::string prefix, std::set<std::string>& into);
|
||||
|
||||
/** @brief parses edge-id and index from lane-id
|
||||
* @param[in] lane_id The lane-id
|
||||
* @param[out] edge_id ID of this lane's edge
|
||||
* @param[out] index Index of this lane
|
||||
*/
|
||||
static void interpretLaneID(const std::string& lane_id, std::string& edge_id, int& index);
|
||||
};
|
|
@ -1,37 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBLinkPossibilityMatrix.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @date Sept 2002
|
||||
///
|
||||
// A matric to describe whether two links are foes to each other
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <bitset>
|
||||
#include <vector>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBLinkPossibilityMatrix
|
||||
* Storing the information which links may be used simultanously, this matrix
|
||||
* is simply made by a vector of bitsets
|
||||
*/
|
||||
typedef std::vector<std::bitset<SUMO_MAX_CONNECTIONS> > NBLinkPossibilityMatrix;
|
|
@ -1,861 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2011-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBLoadedSUMOTLDef.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Michael Behrisch
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Mar 2011
|
||||
///
|
||||
// A complete traffic light logic loaded from a sumo-net. (opted to reimplement
|
||||
// since NBLoadedTLDef is quite vissim specific)
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include "NBTrafficLightLogic.h"
|
||||
#include "NBOwnTLDef.h"
|
||||
#include "NBTrafficLightDefinition.h"
|
||||
#include "NBLoadedSUMOTLDef.h"
|
||||
#include "NBNetBuilder.h"
|
||||
#include "NBOwnTLDef.h"
|
||||
#include "NBNode.h"
|
||||
|
||||
//#define DEBUG_RECONSTRUCTION
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
|
||||
NBLoadedSUMOTLDef::NBLoadedSUMOTLDef(const std::string& id, const std::string& programID,
|
||||
SUMOTime offset, TrafficLightType type) :
|
||||
NBTrafficLightDefinition(id, programID, offset, type),
|
||||
myTLLogic(nullptr),
|
||||
myReconstructAddedConnections(false),
|
||||
myReconstructRemovedConnections(false),
|
||||
myPhasesLoaded(false) {
|
||||
myTLLogic = new NBTrafficLightLogic(id, programID, 0, offset, type);
|
||||
}
|
||||
|
||||
|
||||
NBLoadedSUMOTLDef::NBLoadedSUMOTLDef(const NBTrafficLightDefinition& def, const NBTrafficLightLogic& logic) :
|
||||
// allow for adding a new program for the same def: take the offset and programID from the new logic
|
||||
NBTrafficLightDefinition(def.getID(), logic.getProgramID(), logic.getOffset(), def.getType()),
|
||||
myTLLogic(new NBTrafficLightLogic(logic)),
|
||||
myReconstructAddedConnections(false),
|
||||
myReconstructRemovedConnections(false),
|
||||
myPhasesLoaded(false) {
|
||||
assert(def.getType() == logic.getType());
|
||||
myControlledLinks = def.getControlledLinks();
|
||||
myControlledNodes = def.getNodes();
|
||||
const NBLoadedSUMOTLDef* sumoDef = dynamic_cast<const NBLoadedSUMOTLDef*>(&def);
|
||||
updateParameters(def.getParametersMap());
|
||||
if (sumoDef != nullptr) {
|
||||
myReconstructAddedConnections = sumoDef->myReconstructAddedConnections;
|
||||
myReconstructRemovedConnections = sumoDef->myReconstructRemovedConnections;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NBLoadedSUMOTLDef::~NBLoadedSUMOTLDef() {
|
||||
delete myTLLogic;
|
||||
}
|
||||
|
||||
|
||||
NBTrafficLightLogic*
|
||||
NBLoadedSUMOTLDef::myCompute(int brakingTimeSeconds) {
|
||||
// @todo what to do with those parameters?
|
||||
UNUSED_PARAMETER(brakingTimeSeconds);
|
||||
reconstructLogic();
|
||||
myTLLogic->closeBuilding(false);
|
||||
patchIfCrossingsAdded();
|
||||
myTLLogic->closeBuilding();
|
||||
return new NBTrafficLightLogic(myTLLogic);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex, int linkIndex2, bool reconstruct) {
|
||||
assert(myTLLogic->getNumLinks() > 0); // logic should be loaded by now
|
||||
if (linkIndex >= (int)myTLLogic->getNumLinks()) {
|
||||
throw ProcessError("Invalid linkIndex " + toString(linkIndex) + " for traffic light '" + getID() +
|
||||
"' with " + toString(myTLLogic->getNumLinks()) + " links.");
|
||||
}
|
||||
if (linkIndex2 >= (int)myTLLogic->getNumLinks()) {
|
||||
throw ProcessError("Invalid linkIndex2 " + toString(linkIndex2) + " for traffic light '" + getID() +
|
||||
"' with " + toString(myTLLogic->getNumLinks()) + " links.");
|
||||
}
|
||||
NBConnection conn(from, fromLane, to, toLane, linkIndex, linkIndex2);
|
||||
// avoid duplicates
|
||||
auto newEnd = remove_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(conn));
|
||||
// remove_if does not remove, only re-order
|
||||
myControlledLinks.erase(newEnd, myControlledLinks.end());
|
||||
myControlledLinks.push_back(conn);
|
||||
addNode(from->getToNode());
|
||||
addNode(to->getFromNode());
|
||||
// added connections are definitely controlled. make sure none are removed because they lie within the tl
|
||||
// myControlledInnerEdges.insert(from->getID()); // @todo recheck: this appears to be obsolete
|
||||
// set this information now so that it can be used while loading diffs
|
||||
from->setControllingTLInformation(conn, getID());
|
||||
myReconstructAddedConnections |= reconstruct;
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::setProgramID(const std::string& programID) {
|
||||
NBTrafficLightDefinition::setProgramID(programID);
|
||||
myTLLogic->setProgramID(programID);
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::setTLControllingInformation() const {
|
||||
if (myReconstructAddedConnections) {
|
||||
NBOwnTLDef dummy(DummyID, myControlledNodes, 0, getType());
|
||||
dummy.setParticipantsInformation();
|
||||
dummy.setTLControllingInformation();
|
||||
for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
|
||||
(*i)->removeTrafficLight(&dummy);
|
||||
}
|
||||
}
|
||||
if (myReconstructRemovedConnections) {
|
||||
return; // will be called again in reconstructLogic()
|
||||
}
|
||||
// if nodes have been removed our links may have been invalidated as well
|
||||
// since no logic will be built anyway there is no reason to inform any edges
|
||||
if (amInvalid()) {
|
||||
return;
|
||||
}
|
||||
// set the information about the link's positions within the tl into the
|
||||
// edges the links are starting at, respectively
|
||||
for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
const NBConnection& c = *it;
|
||||
if (c.getTLIndex() >= (int)myTLLogic->getNumLinks()) {
|
||||
throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
|
||||
"' with " + toString(myTLLogic->getNumLinks()) + " links.");
|
||||
}
|
||||
NBEdge* edge = c.getFrom();
|
||||
if (edge != nullptr && edge->getNumLanes() > c.getFromLane()) {
|
||||
// logic may have yet to be reconstructed
|
||||
edge->setControllingTLInformation(c, getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::remapRemoved(NBEdge*, const EdgeVector&, const EdgeVector&) {}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::replaceRemoved(NBEdge* removed, int removedLane, NBEdge* by, int byLane, bool incoming) {
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
|
||||
if (incoming) {
|
||||
(*it).replaceFrom(removed, removedLane, by, byLane);
|
||||
} else {
|
||||
(*it).replaceTo(removed, removedLane, by, byLane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::addPhase(SUMOTime duration, const std::string& state, SUMOTime minDur, SUMOTime maxDur, const std::vector<int>& next, const std::string& name) {
|
||||
myTLLogic->addStep(duration, state, minDur, maxDur, next, name);
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::amInvalid() const {
|
||||
if (myControlledLinks.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
if (myIncomingEdges.size() == 0) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::removeConnection(const NBConnection& conn, bool reconstruct) {
|
||||
for (auto it = myControlledLinks.begin(); it != myControlledLinks.end();) {
|
||||
if ((it->getFrom() == conn.getFrom() &&
|
||||
it->getTo() == conn.getTo() &&
|
||||
it->getFromLane() == conn.getFromLane() &&
|
||||
it->getToLane() == conn.getToLane())
|
||||
|| (it->getTLIndex() == conn.getTLIndex() &&
|
||||
conn.getTLIndex() != conn.InvalidTlIndex &&
|
||||
(it->getFrom() == nullptr || it->getTo() == nullptr))) {
|
||||
if (reconstruct) {
|
||||
myReconstructRemovedConnections = true;
|
||||
it++;
|
||||
} else {
|
||||
it = myControlledLinks.erase(it);
|
||||
}
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::setOffset(SUMOTime offset) {
|
||||
myOffset = offset;
|
||||
myTLLogic->setOffset(offset);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::setType(TrafficLightType type) {
|
||||
myType = type;
|
||||
myTLLogic->setType(type);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::collectEdges() {
|
||||
if (myControlledLinks.size() == 0) {
|
||||
NBTrafficLightDefinition::collectEdges();
|
||||
}
|
||||
myIncomingEdges.clear();
|
||||
EdgeVector myOutgoing;
|
||||
// collect the edges from the participating nodes
|
||||
for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
|
||||
const EdgeVector& incoming = (*i)->getIncomingEdges();
|
||||
copy(incoming.begin(), incoming.end(), back_inserter(myIncomingEdges));
|
||||
const EdgeVector& outgoing = (*i)->getOutgoingEdges();
|
||||
copy(outgoing.begin(), outgoing.end(), back_inserter(myOutgoing));
|
||||
}
|
||||
// check which of the edges are completely within the junction
|
||||
// and which are uncontrolled as well (we already know myControlledLinks)
|
||||
for (EdgeVector::iterator j = myIncomingEdges.begin(); j != myIncomingEdges.end();) {
|
||||
NBEdge* edge = *j;
|
||||
edge->setInsideTLS(false); // reset
|
||||
// an edge lies within the logic if it is outgoing as well as incoming
|
||||
EdgeVector::iterator k = std::find(myOutgoing.begin(), myOutgoing.end(), edge);
|
||||
if (k != myOutgoing.end()) {
|
||||
if (myControlledInnerEdges.count(edge->getID()) == 0) {
|
||||
bool controlled = false;
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
if ((*it).getFrom() == edge) {
|
||||
controlled = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (controlled) {
|
||||
myControlledInnerEdges.insert(edge->getID());
|
||||
} else {
|
||||
myEdgesWithin.push_back(edge);
|
||||
edge->setInsideTLS(true);
|
||||
++j; //j = myIncomingEdges.erase(j);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::collectLinks() {
|
||||
if (myControlledLinks.size() == 0) {
|
||||
// maybe we only loaded a different program for a default traffic light.
|
||||
// Try to build links now.
|
||||
collectAllLinks(myControlledLinks);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @brief patches signal plans by modifying lane indices
|
||||
void
|
||||
NBLoadedSUMOTLDef::shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold) {
|
||||
// avoid shifting twice if the edge is incoming and outgoing to a joined TLS
|
||||
if (myShifted.count(edge) == 0) {
|
||||
/// XXX what if an edge should really be shifted twice?
|
||||
myShifted.insert(edge);
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
(*it).shiftLaneIndex(edge, offset, threshold);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::patchIfCrossingsAdded() {
|
||||
const int size = myTLLogic->getNumLinks();
|
||||
int noLinksAll = 0;
|
||||
for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
const NBConnection& c = *it;
|
||||
if (c.getTLIndex() != NBConnection::InvalidTlIndex) {
|
||||
noLinksAll = MAX2(noLinksAll, (int)c.getTLIndex() + 1);
|
||||
}
|
||||
}
|
||||
const int numNormalLinks = noLinksAll;
|
||||
int oldCrossings = 0;
|
||||
// collect crossings
|
||||
bool customIndex = false;
|
||||
std::vector<NBNode::Crossing*> crossings;
|
||||
for (std::vector<NBNode*>::iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
|
||||
const std::vector<NBNode::Crossing*>& c = (*i)->getCrossings();
|
||||
// set tl indices for crossings
|
||||
customIndex |= (*i)->setCrossingTLIndices(getID(), noLinksAll);
|
||||
copy(c.begin(), c.end(), std::back_inserter(crossings));
|
||||
noLinksAll += (int)c.size();
|
||||
oldCrossings += (*i)->numCrossingsFromSumoNet();
|
||||
}
|
||||
if ((int)crossings.size() != oldCrossings) {
|
||||
std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
|
||||
// do not rebuilt crossing states there are custom indices and the state string is long enough
|
||||
if (phases.size() > 0 && (
|
||||
(int)(phases.front().state.size()) < noLinksAll ||
|
||||
((int)(phases.front().state.size()) > noLinksAll && !customIndex))) {
|
||||
// collect edges
|
||||
EdgeVector fromEdges(size, (NBEdge*)nullptr);
|
||||
EdgeVector toEdges(size, (NBEdge*)nullptr);
|
||||
std::vector<int> fromLanes(size, 0);
|
||||
collectEdgeVectors(fromEdges, toEdges, fromLanes);
|
||||
const std::string crossingDefaultState(crossings.size(), 'r');
|
||||
|
||||
// rebuild the logic (see NBOwnTLDef.cpp::myCompute)
|
||||
NBTrafficLightLogic* newLogic = new NBTrafficLightLogic(getID(), getProgramID(), 0, myOffset, myType);
|
||||
SUMOTime brakingTime = TIME2STEPS(computeBrakingTime(OptionsCont::getOptions().getFloat("tls.yellow.min-decel")));
|
||||
//std::cout << "patchIfCrossingsAdded for " << getID() << " numPhases=" << phases.size() << "\n";
|
||||
for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
|
||||
const std::string state = it->state.substr(0, numNormalLinks) + crossingDefaultState;
|
||||
NBOwnTLDef::addPedestrianPhases(newLogic, it->duration, it->minDur, it->maxDur, state, crossings, fromEdges, toEdges);
|
||||
}
|
||||
NBOwnTLDef::addPedestrianScramble(newLogic, noLinksAll, TIME2STEPS(10), brakingTime, crossings, fromEdges, toEdges);
|
||||
|
||||
delete myTLLogic;
|
||||
myTLLogic = newLogic;
|
||||
} else if (phases.size() == 0) {
|
||||
WRITE_WARNING("Could not patch tlLogic '" + getID() + "' for changed crossings");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::collectEdgeVectors(EdgeVector& fromEdges, EdgeVector& toEdges, std::vector<int>& fromLanes) const {
|
||||
assert(fromEdges.size() > 0);
|
||||
assert(fromEdges.size() == toEdges.size());
|
||||
const int size = (int)fromEdges.size();
|
||||
|
||||
for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
const NBConnection& c = *it;
|
||||
if (c.getTLIndex() != NBConnection::InvalidTlIndex) {
|
||||
if (c.getTLIndex() >= size) {
|
||||
throw ProcessError("Invalid linkIndex " + toString(c.getTLIndex()) + " for traffic light '" + getID() +
|
||||
"' with " + toString(size) + " links.");
|
||||
}
|
||||
fromEdges[c.getTLIndex()] = c.getFrom();
|
||||
toEdges[c.getTLIndex()] = c.getTo();
|
||||
fromLanes[c.getTLIndex()] = c.getFromLane();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::initNeedsContRelation() const {
|
||||
if (!amInvalid() && !myNeedsContRelationReady) {
|
||||
myNeedsContRelation.clear();
|
||||
myRightOnRedConflicts.clear();
|
||||
const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
|
||||
const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = myTLLogic->getPhases();
|
||||
for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
|
||||
const std::string state = (*it).state;
|
||||
for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
|
||||
const NBConnection& c1 = *it1;
|
||||
const int i1 = c1.getTLIndex();
|
||||
if (i1 == NBConnection::InvalidTlIndex || (state[i1] != 'g' && state[i1] != 's') || c1.getFrom() == nullptr || c1.getTo() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
|
||||
const NBConnection& c2 = *it2;
|
||||
const int i2 = c2.getTLIndex();
|
||||
if (i2 != NBConnection::InvalidTlIndex
|
||||
&& i2 != i1
|
||||
&& (state[i2] == 'G' || state[i2] == 'g')
|
||||
&& c2.getFrom() != nullptr && c2.getTo() != nullptr) {
|
||||
const bool rightTurnConflict = NBNode::rightTurnConflict(
|
||||
c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
|
||||
const bool forbidden = forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin);
|
||||
const bool isFoes = foes(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo()) && !c2.getFrom()->isTurningDirectionAt(c2.getTo());
|
||||
if (forbidden || rightTurnConflict) {
|
||||
myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
|
||||
}
|
||||
if (isFoes && state[i1] == 's') {
|
||||
myRightOnRedConflicts.insert(std::make_pair(i1, i2));
|
||||
//std::cout << getID() << " prog=" << getProgramID() << " phase=" << (it - phases.begin()) << " rightOnRedConflict i1=" << i1 << " i2=" << i2 << "\n";
|
||||
}
|
||||
//std::cout << getID() << " i1=" << i1 << " i2=" << i2 << " rightTurnConflict=" << rightTurnConflict << " forbidden=" << forbidden << " isFoes=" << isFoes << "\n";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myNeedsContRelationReady = true;
|
||||
myRightOnRedConflictsReady = true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::rightOnRedConflict(int index, int foeIndex) const {
|
||||
if (amInvalid()) {
|
||||
return false;
|
||||
}
|
||||
if (!myRightOnRedConflictsReady) {
|
||||
initNeedsContRelation();
|
||||
assert(myRightOnRedConflictsReady);
|
||||
}
|
||||
return std::find(myRightOnRedConflicts.begin(), myRightOnRedConflicts.end(), std::make_pair(index, foeIndex)) != myRightOnRedConflicts.end();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::registerModifications(bool addedConnections, bool removedConnections) {
|
||||
myReconstructAddedConnections |= addedConnections;
|
||||
myReconstructRemovedConnections |= removedConnections;
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::reconstructLogic() {
|
||||
const bool netedit = NBNetBuilder::runningNetedit();
|
||||
#ifdef DEBUG_RECONSTRUCTION
|
||||
bool debugPrintModified = myReconstructAddedConnections || myReconstructRemovedConnections;
|
||||
std::cout << getID() << " reconstructLogic added=" << myReconstructAddedConnections
|
||||
<< " removed=" << myReconstructRemovedConnections
|
||||
<< " valid=" << hasValidIndices()
|
||||
<< " phasesLoaded=" << myPhasesLoaded
|
||||
<< " oldLinks:\n";
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
|
||||
std::cout << " " << *it << "\n";
|
||||
}
|
||||
#endif
|
||||
if (myReconstructAddedConnections) {
|
||||
myReconstructAddedConnections = false;
|
||||
// do not rebuild the logic when running netedit and all links are already covered by the program
|
||||
if (!myPhasesLoaded && !(netedit && hasValidIndices())) {
|
||||
// rebuild the logic from scratch
|
||||
// XXX if a connection with the same from- and to-edge already exisits, its states could be copied instead
|
||||
NBOwnTLDef dummy(DummyID, myControlledNodes, 0, getType());
|
||||
dummy.setParticipantsInformation();
|
||||
dummy.setProgramID(getProgramID());
|
||||
dummy.setTLControllingInformation();
|
||||
NBTrafficLightLogic* newLogic = dummy.compute(OptionsCont::getOptions());
|
||||
myIncomingEdges = dummy.getIncomingEdges();
|
||||
myControlledLinks = dummy.getControlledLinks();
|
||||
for (std::vector<NBNode*>::const_iterator i = myControlledNodes.begin(); i != myControlledNodes.end(); i++) {
|
||||
(*i)->removeTrafficLight(&dummy);
|
||||
}
|
||||
delete myTLLogic;
|
||||
myTLLogic = newLogic;
|
||||
if (newLogic != nullptr) {
|
||||
newLogic->setID(getID());
|
||||
newLogic->setType(getType());
|
||||
newLogic->setOffset(getOffset());
|
||||
setTLControllingInformation();
|
||||
// reset crossing custom indices
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
c->customTLIndex = NBConnection::InvalidTlIndex;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else {
|
||||
setTLControllingInformation();
|
||||
}
|
||||
}
|
||||
if (myReconstructRemovedConnections) {
|
||||
myReconstructRemovedConnections = false;
|
||||
// for each connection, check whether it is still valid
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end();) {
|
||||
const NBConnection con = (*it);
|
||||
if (// edge still exists
|
||||
std::find(myIncomingEdges.begin(), myIncomingEdges.end(), con.getFrom()) != myIncomingEdges.end()
|
||||
// connection still exists
|
||||
&& con.getFrom()->hasConnectionTo(con.getTo(), con.getToLane(), con.getFromLane())
|
||||
// connection is still set to be controlled
|
||||
&& con.getFrom()->mayBeTLSControlled(con.getFromLane(), con.getTo(), con.getToLane())) {
|
||||
it++;
|
||||
} else {
|
||||
// remove connection
|
||||
const int removed = con.getTLIndex();
|
||||
it = myControlledLinks.erase(it);
|
||||
// no automatic modificaions when running netedit
|
||||
if (!myPhasesLoaded && !(netedit && hasValidIndices())) {
|
||||
// shift index off successive connections and remove entry from all phases if the tlIndex was only used by this connection
|
||||
bool exclusive = true;
|
||||
for (NBConnection& other : myControlledLinks) {
|
||||
if (other != con && other.getTLIndex() == removed) {
|
||||
exclusive = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (exclusive) {
|
||||
// shift indices above the removed index downward
|
||||
for (NBConnection& other : myControlledLinks) {
|
||||
if (other.getTLIndex() > removed) {
|
||||
other.setTLIndex(other.getTLIndex() - 1);
|
||||
}
|
||||
}
|
||||
// shift crossing custom indices above the removed index downward
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
if (c->customTLIndex > removed) {
|
||||
c->customTLIndex--;
|
||||
}
|
||||
}
|
||||
}
|
||||
// rebuild the logic
|
||||
NBTrafficLightLogic* newLogic = new NBTrafficLightLogic(getID(), getProgramID(), 0, myOffset, myType);
|
||||
for (const NBTrafficLightLogic::PhaseDefinition& phase : myTLLogic->getPhases()) {
|
||||
std::string newState = phase.state;
|
||||
newState.erase(newState.begin() + removed);
|
||||
newLogic->addStep(phase.duration, newState);
|
||||
}
|
||||
delete myTLLogic;
|
||||
myTLLogic = newLogic;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
setTLControllingInformation();
|
||||
}
|
||||
#ifdef DEBUG_RECONSTRUCTION
|
||||
if (debugPrintModified) {
|
||||
std::cout << " newLinks:\n";
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); ++it) {
|
||||
std::cout << " " << *it << "\n";
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBLoadedSUMOTLDef::getMaxIndex() {
|
||||
int maxIndex = -1;
|
||||
for (const NBConnection& c : myControlledLinks) {
|
||||
maxIndex = MAX2(maxIndex, c.getTLIndex());
|
||||
maxIndex = MAX2(maxIndex, c.getTLIndex2());
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
maxIndex = MAX2(maxIndex, c->tlLinkIndex);
|
||||
maxIndex = MAX2(maxIndex, c->tlLinkIndex2);
|
||||
}
|
||||
}
|
||||
return maxIndex;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBLoadedSUMOTLDef::getMaxValidIndex() {
|
||||
return myTLLogic->getNumLinks() - 1;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::hasValidIndices() const {
|
||||
for (const NBConnection& c : myControlledLinks) {
|
||||
if (c.getTLIndex() == NBConnection::InvalidTlIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
if (c->tlLinkIndex == NBConnection::InvalidTlIndex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
// method getMaxIndex() is const but cannot be declare as such due to inheritance
|
||||
return const_cast<NBLoadedSUMOTLDef*>(this)->getMaxIndex() < myTLLogic->getNumLinks();
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
NBLoadedSUMOTLDef::getStates(int index) {
|
||||
assert(index >= 0);
|
||||
assert(index <= getMaxIndex());
|
||||
std::string result;
|
||||
for (auto& pd : myTLLogic->getPhases()) {
|
||||
result += pd.state[index];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::isUsed(int index) {
|
||||
for (const NBConnection& c : myControlledLinks) {
|
||||
if (c.getTLIndex() == index || c.getTLIndex2() == index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
if (c->tlLinkIndex == index || c->tlLinkIndex2 == index) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
std::set<const NBEdge*>
|
||||
NBLoadedSUMOTLDef::getEdgesUsingIndex(int index) const {
|
||||
std::set<const NBEdge*> result;
|
||||
for (const NBConnection& c : myControlledLinks) {
|
||||
if (c.getTLIndex() == index || c.getTLIndex2() == index) {
|
||||
result.insert(c.getFrom());
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::replaceIndex(int oldIndex, int newIndex) {
|
||||
if (oldIndex == newIndex) {
|
||||
return;
|
||||
}
|
||||
for (NBConnection& c : myControlledLinks) {
|
||||
if (c.getTLIndex() == oldIndex) {
|
||||
c.setTLIndex(newIndex);
|
||||
}
|
||||
if (c.getTLIndex2() == oldIndex) {
|
||||
c.setTLIndex2(newIndex);
|
||||
}
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
if (c->tlLinkIndex == oldIndex) {
|
||||
c->tlLinkIndex = newIndex;
|
||||
}
|
||||
if (c->tlLinkIndex2 == oldIndex) {
|
||||
c->tlLinkIndex2 = newIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::groupSignals() {
|
||||
const int maxIndex = getMaxIndex();
|
||||
std::vector<int> unusedIndices;
|
||||
for (int i = 0; i <= maxIndex; i++) {
|
||||
if (isUsed(i)) {
|
||||
std::set<const NBEdge*> edges = getEdgesUsingIndex(i);
|
||||
// compactify
|
||||
replaceIndex(i, i - (int)unusedIndices.size());
|
||||
if (edges.size() == 0) {
|
||||
// do not group pedestrian crossing signals
|
||||
continue;
|
||||
}
|
||||
std::string states = getStates(i);
|
||||
for (int j = i + 1; j <= maxIndex; j++) {
|
||||
// only group signals from the same edges as is commonly done by
|
||||
// traffic engineers
|
||||
if (states == getStates(j) && edges == getEdgesUsingIndex(j)) {
|
||||
replaceIndex(j, i - (int)unusedIndices.size());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
unusedIndices.push_back(i);
|
||||
}
|
||||
}
|
||||
for (int i = (int)unusedIndices.size() - 1; i >= 0; i--) {
|
||||
myTLLogic->deleteStateIndex(unusedIndices[i]);
|
||||
}
|
||||
cleanupStates();
|
||||
//std::cout << "oldMaxIndex=" << maxIndex << " newMaxIndex=" << getMaxIndex() << " unused=" << toString(unusedIndices) << "\n";
|
||||
setTLControllingInformation();
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::ungroupSignals() {
|
||||
NBConnectionVector defaultOrdering;
|
||||
collectAllLinks(defaultOrdering);
|
||||
myTLLogic->setStateLength((int)myControlledLinks.size());
|
||||
std::vector<std::string> states; // organized per link rather than phase
|
||||
int index = 0;
|
||||
for (NBConnection& c : defaultOrdering) {
|
||||
NBConnection& c2 = *find_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(c));
|
||||
states.push_back(getStates(c2.getTLIndex()));
|
||||
c2.setTLIndex(index++);
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
states.push_back(getStates(c->tlLinkIndex));
|
||||
c->tlLinkIndex = index++;
|
||||
if (c->tlLinkIndex2 != NBConnection::InvalidTlIndex) {
|
||||
states.push_back(getStates(c->tlLinkIndex2));
|
||||
c->tlLinkIndex2 = index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < (int)states.size(); i++) {
|
||||
for (int p = 0; p < (int)states[i].size(); p++) {
|
||||
myTLLogic->setPhaseState(p, i, (LinkState)states[i][p]);
|
||||
}
|
||||
}
|
||||
setTLControllingInformation();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::copyIndices(NBTrafficLightDefinition* def) {
|
||||
std::map<int, std::string> oldStates; // organized per link index rather than phase
|
||||
std::map<int, std::string> newStates; // organized per link index rather than phase
|
||||
for (NBConnection& c : def->getControlledLinks()) {
|
||||
NBConnection& c2 = *find_if(myControlledLinks.begin(), myControlledLinks.end(), connection_equal(c));
|
||||
const int oldIndex = c2.getTLIndex();
|
||||
const int newIndex = c.getTLIndex();
|
||||
std::string states = getStates(oldIndex);
|
||||
oldStates[oldIndex] = states;
|
||||
if (newStates.count(newIndex) != 0 && newStates[newIndex] != states) {
|
||||
WRITE_WARNING("Signal groups from program '" + def->getProgramID() + "' are incompatible with the states of program '" + getProgramID() + "' at tlLogic '" + getID()
|
||||
+ "'. Possibly unsafe program.");
|
||||
} else {
|
||||
newStates[newIndex] = states;
|
||||
}
|
||||
c2.setTLIndex(newIndex);
|
||||
}
|
||||
const int maxIndex = getMaxIndex();
|
||||
myTLLogic->setStateLength(maxIndex + 1);
|
||||
for (int i = 0; i < (int)newStates.size(); i++) {
|
||||
for (int p = 0; p < (int)newStates[i].size(); p++) {
|
||||
myTLLogic->setPhaseState(p, i, (LinkState)newStates[i][p]);
|
||||
}
|
||||
}
|
||||
setTLControllingInformation();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::cleanupStates() {
|
||||
const int maxIndex = getMaxIndex();
|
||||
std::vector<int> unusedIndices;
|
||||
for (int i = 0; i <= maxIndex; i++) {
|
||||
if (isUsed(i)) {
|
||||
if (unusedIndices.size() > 0) {
|
||||
replaceIndex(i, i - (int)unusedIndices.size());
|
||||
}
|
||||
} else {
|
||||
unusedIndices.push_back(i);
|
||||
}
|
||||
}
|
||||
for (int i = (int)unusedIndices.size() - 1; i >= 0; i--) {
|
||||
myTLLogic->deleteStateIndex(unusedIndices[i]);
|
||||
}
|
||||
if (unusedIndices.size() > 0) {
|
||||
myTLLogic->setStateLength(maxIndex + 1 - (int)unusedIndices.size());
|
||||
setTLControllingInformation();
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::joinLogic(NBTrafficLightDefinition* def) {
|
||||
def->setParticipantsInformation();
|
||||
def->compute(OptionsCont::getOptions());
|
||||
const int maxIndex = MAX2(getMaxIndex(), def->getMaxIndex());
|
||||
myTLLogic->setStateLength(maxIndex + 1);
|
||||
myControlledLinks.insert(myControlledLinks.end(), def->getControlledLinks().begin(), def->getControlledLinks().end());
|
||||
}
|
||||
|
||||
bool
|
||||
NBLoadedSUMOTLDef::usingSignalGroups() const {
|
||||
// count how often each index is used
|
||||
std::map<int, int> indexUsage;
|
||||
for (const NBConnection& c : myControlledLinks) {
|
||||
indexUsage[c.getTLIndex()]++;
|
||||
}
|
||||
for (NBNode* n : myControlledNodes) {
|
||||
for (NBNode::Crossing* c : n->getCrossings()) {
|
||||
indexUsage[c->tlLinkIndex]++;
|
||||
indexUsage[c->tlLinkIndex2]++;
|
||||
}
|
||||
}
|
||||
for (auto it : indexUsage) {
|
||||
if (it.first >= 0 && it.second > 1) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedSUMOTLDef::guessMinMaxDuration() {
|
||||
bool hasMinMaxDur = false;
|
||||
for (auto phase : myTLLogic->getPhases()) {
|
||||
if (phase.maxDur != UNSPECIFIED_DURATION) {
|
||||
//std::cout << " phase=" << phase.state << " maxDur=" << phase.maxDur << "\n";
|
||||
hasMinMaxDur = true;
|
||||
}
|
||||
}
|
||||
if (!hasMinMaxDur) {
|
||||
const SUMOTime minMinDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.min-dur"));
|
||||
const SUMOTime maxDur = TIME2STEPS(OptionsCont::getOptions().getInt("tls.max-dur"));
|
||||
std::set<int> yellowIndices;
|
||||
for (auto phase : myTLLogic->getPhases()) {
|
||||
for (int i = 0; i < (int)phase.state.size(); i++) {
|
||||
if (phase.state[i] == 'y' || phase.state[i] == 'Y') {
|
||||
yellowIndices.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int ip = 0; ip < (int)myTLLogic->getPhases().size(); ip++) {
|
||||
bool needMinMaxDur = false;
|
||||
auto phase = myTLLogic->getPhases()[ip];
|
||||
std::set<int> greenIndices;
|
||||
if (phase.state.find_first_of("yY") != std::string::npos) {
|
||||
continue;
|
||||
}
|
||||
for (int i = 0; i < (int)phase.state.size(); i++) {
|
||||
if (yellowIndices.count(i) != 0 && phase.state[i] == 'G') {
|
||||
needMinMaxDur = true;
|
||||
greenIndices.insert(i);
|
||||
}
|
||||
}
|
||||
if (needMinMaxDur) {
|
||||
double maxSpeed = 0;
|
||||
for (NBConnection& c : myControlledLinks) {
|
||||
if (greenIndices.count(c.getTLIndex()) != 0) {
|
||||
maxSpeed = MAX2(maxSpeed, c.getFrom()->getLaneSpeed(c.getFromLane()));
|
||||
}
|
||||
}
|
||||
// 5s at 50km/h, 10s at 80km/h, rounded to full seconds
|
||||
const double minDurBySpeed = maxSpeed * 3.6 / 6 - 3.3;
|
||||
SUMOTime minDur = MAX2(minMinDur, TIME2STEPS(floor(minDurBySpeed + 0.5)));
|
||||
myTLLogic->setPhaseMinDuration(ip, minDur);
|
||||
myTLLogic->setPhaseMaxDuration(ip, maxDur);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,253 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2011-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBLoadedSUMOTLDef.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date Mar 2011
|
||||
///
|
||||
// A complete traffic light logic loaded from a sumo-net. (opted to reimplement
|
||||
// since NBLoadedTLDef is quite vissim specific)
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "NBNode.h"
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBTrafficLightDefinition.h"
|
||||
#include "NBTrafficLightLogic.h"
|
||||
#include <utils/common/SUMOTime.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBLoadedSUMOTLDef
|
||||
* @brief A loaded (complete) traffic light logic
|
||||
*/
|
||||
class NBLoadedSUMOTLDef : public NBTrafficLightDefinition {
|
||||
public:
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] programID The programID for the computed logic
|
||||
* @param[in] offset The offset for the computed logic
|
||||
* @param[in] type The algorithm type for the computed logic
|
||||
*/
|
||||
NBLoadedSUMOTLDef(const std::string& id, const std::string& programID, SUMOTime offset, TrafficLightType type);
|
||||
|
||||
/** @brief Constructor that copies from an existing definition and its computed logic (used by NETEDIT)
|
||||
* @param[in] def The definition to copy
|
||||
* @param[in] logic The computed logic of the given def
|
||||
*/
|
||||
NBLoadedSUMOTLDef(const NBTrafficLightDefinition& def, const NBTrafficLightLogic& logic);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBLoadedSUMOTLDef();
|
||||
|
||||
/** @brief Sets the programID
|
||||
* @param[in] programID The new ID of the program (subID)
|
||||
*/
|
||||
void setProgramID(const std::string& programID);
|
||||
|
||||
/** @brief Informs edges about being controlled by a tls
|
||||
*/
|
||||
void setTLControllingInformation() const;
|
||||
|
||||
/** @brief Replaces occurences of the removed edge in incoming/outgoing edges of all definitions
|
||||
* @param[in] removed The removed edge
|
||||
* @param[in] incoming The edges to use instead if an incoming edge was removed
|
||||
* @param[in] outgoing The edges to use instead if an outgoing edge was removed
|
||||
*/
|
||||
void remapRemoved(NBEdge* removed,
|
||||
const EdgeVector& incoming, const EdgeVector& outgoing);
|
||||
|
||||
|
||||
/** @brief Replaces a removed edge/lane
|
||||
* @param[in] removed The edge to replace
|
||||
* @param[in] removedLane The lane of this edge to replace
|
||||
* @param[in] by The edge to insert instead
|
||||
* @param[in] byLane This edge's lane to insert instead
|
||||
*/
|
||||
void replaceRemoved(NBEdge* removed, int removedLane,
|
||||
NBEdge* by, int byLane, bool incoming);
|
||||
|
||||
/** @brief patches signal plans by modifying lane indices
|
||||
* with the given offset, only indices with a value above threshold are modified
|
||||
*/
|
||||
void shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold = -1);
|
||||
|
||||
/** @brief Adds a phase to the logic
|
||||
* the new phase is inserted at the end of the list of already added phases
|
||||
* @param[in] duration The duration of the phase to add
|
||||
* @param[in] state The state definition of a tls phase
|
||||
* @param[in] minDur The minimum duration of the phase to add
|
||||
* @param[in] maxDur The maximum duration of the phase to add
|
||||
*/
|
||||
void addPhase(SUMOTime duration, const std::string& state, SUMOTime minDur, SUMOTime maxDur, const std::vector<int>& next, const std::string& name);
|
||||
|
||||
/// @brief mark phases as load
|
||||
void phasesLoaded() {
|
||||
myPhasesLoaded = true;
|
||||
}
|
||||
|
||||
/** @brief Adds a connection and immediately informs the edges
|
||||
*/
|
||||
void addConnection(NBEdge* from, NBEdge* to, int fromLane, int toLane, int linkIndex, int linkIndex2, bool reconstruct = true);
|
||||
|
||||
|
||||
/** @brief removes the given connection from the traffic light
|
||||
* if recontruct=true, reconstructs the logic and informs the edges for immediate use in NETEDIT
|
||||
* @note: tlIndex is not necessarily unique. we need the whole connection data here
|
||||
*/
|
||||
void removeConnection(const NBConnection& conn, bool reconstruct = true);
|
||||
|
||||
/// @brief register changes that necessitate recomputation
|
||||
void registerModifications(bool addedConnections, bool removedConnections);
|
||||
|
||||
/** @brief Returns the internal logic
|
||||
*/
|
||||
NBTrafficLightLogic* getLogic() {
|
||||
return myTLLogic;
|
||||
}
|
||||
|
||||
/** @brief Sets the offset of this tls
|
||||
* @param[in] offset The offset of this cycle
|
||||
*/
|
||||
void setOffset(SUMOTime offset);
|
||||
|
||||
/** @brief Sets the algorithm type of this tls
|
||||
* @param[in] offset The algorithm type of this tls
|
||||
*/
|
||||
void setType(TrafficLightType type);
|
||||
|
||||
/// @brief whether the given index must yield to the foeIndex while turing right on a red light
|
||||
bool rightOnRedConflict(int index, int foeIndex) const;
|
||||
|
||||
/* @brief shortens phase states to remove states that are not referenced by
|
||||
* any controlled link and returns whether states were shortened
|
||||
*/
|
||||
bool cleanupStates();
|
||||
|
||||
/// @brief whether this definition uses signal group (multiple connections with the same link index)
|
||||
bool usingSignalGroups() const;
|
||||
|
||||
/// @brief join nodes and states from the given logic (append red state)
|
||||
void joinLogic(NBTrafficLightDefinition* def);
|
||||
|
||||
/// @brief heuristically add minDur and maxDur when switching from tlType fixed to actuated
|
||||
void guessMinMaxDuration();
|
||||
|
||||
/// @brief let connections with the same state use the same link index
|
||||
void groupSignals();
|
||||
|
||||
/// @brief let all connections use a distinct link index
|
||||
void ungroupSignals();
|
||||
|
||||
/// @brief copy the assignment of link indices to connections from the given definition and rebuilt the states to match
|
||||
// Note: Issues a warning when the grouping of def is incompatible with the current states
|
||||
void copyIndices(NBTrafficLightDefinition* def);
|
||||
|
||||
protected:
|
||||
/** @brief Collects the links participating in this traffic light
|
||||
* (only if not previously loaded)
|
||||
*/
|
||||
void collectLinks();
|
||||
|
||||
/** @brief Build the list of participating edges
|
||||
*/
|
||||
void collectEdges();
|
||||
|
||||
/** @brief Computes the traffic light logic finally in dependence to the type
|
||||
* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls in seconds
|
||||
* @return The computed logic
|
||||
*/
|
||||
NBTrafficLightLogic* myCompute(int brakingTimeSeconds);
|
||||
|
||||
bool amInvalid() const;
|
||||
|
||||
/* initialize myNeedsContRelation and set myNeedsContRelationReady to true */
|
||||
void initNeedsContRelation() const;
|
||||
|
||||
/// @brief return the highest known tls link index used by any controlled connection or crossing
|
||||
int getMaxIndex();
|
||||
|
||||
///@brief Returns the maximum index controlled by this traffic light
|
||||
int getMaxValidIndex();
|
||||
|
||||
/// @brief get all states for the given link index
|
||||
std::string getStates(int index);
|
||||
|
||||
/// @brief return whether the given link index is used by any connectons
|
||||
bool isUsed(int index);
|
||||
|
||||
/// @brief replace the given link index in all connections
|
||||
void replaceIndex(int oldIndex, int newIndex);
|
||||
|
||||
/// brief retrieve all edges with connections that use the given traffic light index
|
||||
std::set<const NBEdge*> getEdgesUsingIndex(int index) const;
|
||||
|
||||
private:
|
||||
|
||||
/** @brief phases are added directly to myTLLogic which is then returned in myCompute() */
|
||||
NBTrafficLightLogic* myTLLogic;
|
||||
|
||||
/// @brief repair the plan if controlled nodes received pedestrian crossings
|
||||
void patchIfCrossingsAdded();
|
||||
|
||||
/// @brief set of edges with shifted lane indices (to avoid shifting twice)
|
||||
std::set<NBEdge*> myShifted;
|
||||
|
||||
/// @brief whether the logic must be reconstructed
|
||||
bool myReconstructAddedConnections;
|
||||
bool myReconstructRemovedConnections;
|
||||
bool myPhasesLoaded;
|
||||
|
||||
/** @brief Collects the edges for each tlIndex
|
||||
* @param[out] fromEdges The from-edge for each controlled tlIndex
|
||||
* @param[out] toEdges The to-edge for each controlled tlIndex
|
||||
* @param[out] fromLanes The from-lanes for each controlled tlIndex
|
||||
*/
|
||||
void collectEdgeVectors(EdgeVector& fromEdges, EdgeVector& toEdges, std::vector<int>& fromLanes) const;
|
||||
|
||||
/// @brief adapt to removal or addition of connections
|
||||
void reconstructLogic();
|
||||
|
||||
/// @brief return whether all tls link indices are valid
|
||||
bool hasValidIndices() const;
|
||||
|
||||
private:
|
||||
/// @brief class for identifying connections
|
||||
class connection_equal {
|
||||
public:
|
||||
/// constructor
|
||||
connection_equal(const NBConnection& c) : myC(c) {}
|
||||
|
||||
bool operator()(const NBConnection& c) const {
|
||||
return c.getFrom() == myC.getFrom() && c.getTo() == myC.getTo() &&
|
||||
c.getFromLane() == myC.getFromLane() && c.getToLane() == myC.getToLane();
|
||||
}
|
||||
private:
|
||||
const NBConnection& myC;
|
||||
private:
|
||||
/// @brief invalidated assignment operator
|
||||
connection_equal& operator=(const connection_equal& s);
|
||||
|
||||
};
|
||||
|
||||
};
|
|
@ -1,669 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBLoadedTLDef.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 29.05.2005
|
||||
///
|
||||
// A loaded (complete) traffic light logic
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <cassert>
|
||||
#include <iterator>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include "NBTrafficLightLogic.h"
|
||||
#include "NBTrafficLightDefinition.h"
|
||||
#include "NBLoadedTLDef.h"
|
||||
#include "NBNode.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
/* -------------------------------------------------------------------------
|
||||
* NBLoadedTLDef::SignalGroup-methods
|
||||
* ----------------------------------------------------------------------- */
|
||||
NBLoadedTLDef::SignalGroup::SignalGroup(const std::string& id)
|
||||
: Named(id) {}
|
||||
|
||||
NBLoadedTLDef::SignalGroup::~SignalGroup() {}
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::addConnection(const NBConnection& c) {
|
||||
assert(c.getFromLane() < 0 || c.getFrom()->getNumLanes() > c.getFromLane());
|
||||
myConnections.push_back(c);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::addPhaseBegin(SUMOTime time, TLColor color) {
|
||||
myPhases.push_back(PhaseDef(time, color));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::setYellowTimes(SUMOTime tRedYellow, SUMOTime tYellow) {
|
||||
myTRedYellow = tRedYellow;
|
||||
myTYellow = tYellow;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::sortPhases() {
|
||||
sort(myPhases.begin(), myPhases.end(), phase_by_time_sorter());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::patchTYellow(int tyellow, bool forced) {
|
||||
if (myTYellow < 0) {
|
||||
// was not set before (was not loaded)
|
||||
myTYellow = tyellow;
|
||||
} else if (forced && myTYellow < tyellow) {
|
||||
WRITE_WARNING("TYellow of signal group '" + getID() + "' was less than the computed one; patched (was:" + toString(myTYellow) + ", is:" + toString(tyellow) + ")");
|
||||
myTYellow = tyellow;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::vector<double>
|
||||
NBLoadedTLDef::SignalGroup::getTimes(SUMOTime cycleDuration) const {
|
||||
// within the phase container, we should have the green and red phases add their times
|
||||
std::vector<double> ret; // !!! time vector
|
||||
for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
|
||||
ret.push_back((double)(*i).myTime);
|
||||
}
|
||||
// further, we possibly should set the yellow phases
|
||||
if (myTYellow > 0) {
|
||||
for (std::vector<PhaseDef>::const_iterator i = myPhases.begin(); i != myPhases.end(); i++) {
|
||||
if ((*i).myColor == TLCOLOR_RED) {
|
||||
SUMOTime time = (SUMOTime)(*i).myTime + myTYellow;
|
||||
if (time > cycleDuration) {
|
||||
time = time - cycleDuration;
|
||||
}
|
||||
ret.push_back((double) time);
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBLoadedTLDef::SignalGroup::getLinkNo() const {
|
||||
return (int) myConnections.size();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::SignalGroup::mayDrive(SUMOTime time) const {
|
||||
assert(myPhases.size() != 0);
|
||||
for (std::vector<PhaseDef>::const_reverse_iterator i = myPhases.rbegin(); i != myPhases.rend(); i++) {
|
||||
SUMOTime nextTime = (*i).myTime;
|
||||
if (time >= nextTime) {
|
||||
return (*i).myColor == TLCOLOR_GREEN;
|
||||
}
|
||||
}
|
||||
return (*(myPhases.end() - 1)).myColor == TLCOLOR_GREEN;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::SignalGroup::hasYellow(SUMOTime time) const {
|
||||
bool has_red_now = !mayDrive(time);
|
||||
bool had_green = mayDrive(time - myTYellow);
|
||||
return has_red_now && had_green;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::SignalGroup::containsConnection(NBEdge* from, NBEdge* to) const {
|
||||
for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
|
||||
if ((*i).getFrom() == from && (*i).getTo() == to) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
const NBConnection&
|
||||
NBLoadedTLDef::SignalGroup::getConnection(int pos) const {
|
||||
assert(pos < (int)myConnections.size());
|
||||
return myConnections[pos];
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::SignalGroup::containsIncoming(NBEdge* from) const {
|
||||
for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
|
||||
if ((*i).getFrom() == from) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::remapIncoming(NBEdge* which, const EdgeVector& by) {
|
||||
NBConnectionVector newConns;
|
||||
for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
|
||||
if ((*i).getFrom() == which) {
|
||||
NBConnection conn((*i).getFrom(), (*i).getTo());
|
||||
i = myConnections.erase(i);
|
||||
for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
|
||||
NBConnection curr(conn);
|
||||
if (!curr.replaceFrom(which, *j)) {
|
||||
throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
|
||||
}
|
||||
newConns.push_back(curr);
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
copy(newConns.begin(), newConns.end(),
|
||||
back_inserter(myConnections));
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::SignalGroup::containsOutgoing(NBEdge* to) const {
|
||||
for (NBConnectionVector::const_iterator i = myConnections.begin(); i != myConnections.end(); i++) {
|
||||
if ((*i).getTo() == to) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::remapOutgoing(NBEdge* which, const EdgeVector& by) {
|
||||
NBConnectionVector newConns;
|
||||
for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end();) {
|
||||
if ((*i).getTo() == which) {
|
||||
NBConnection conn((*i).getFrom(), (*i).getTo());
|
||||
i = myConnections.erase(i);
|
||||
for (EdgeVector::const_iterator j = by.begin(); j != by.end(); j++) {
|
||||
NBConnection curr(conn);
|
||||
if (!curr.replaceTo(which, *j)) {
|
||||
throw ProcessError("Could not replace edge '" + which->getID() + "' by '" + (*j)->getID() + "'.\nUndefined...");
|
||||
}
|
||||
newConns.push_back(curr);
|
||||
}
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
copy(newConns.begin(), newConns.end(),
|
||||
back_inserter(myConnections));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::SignalGroup::remap(NBEdge* removed, int removedLane,
|
||||
NBEdge* by, int byLane) {
|
||||
for (NBConnectionVector::iterator i = myConnections.begin(); i != myConnections.end(); i++) {
|
||||
if ((*i).getTo() == removed
|
||||
&&
|
||||
((*i).getToLane() == removedLane
|
||||
||
|
||||
(*i).getToLane() == -1)) {
|
||||
(*i).replaceTo(removed, removedLane, by, byLane);
|
||||
|
||||
} else if ((*i).getTo() == removed && removedLane == -1) {
|
||||
(*i).replaceTo(removed, by);
|
||||
}
|
||||
|
||||
if ((*i).getFrom() == removed
|
||||
&&
|
||||
((*i).getFromLane() == removedLane
|
||||
||
|
||||
(*i).getFromLane() == -1)) {
|
||||
(*i).replaceFrom(removed, removedLane, by, byLane);
|
||||
|
||||
} else if ((*i).getFrom() == removed && removedLane == -1) {
|
||||
(*i).replaceFrom(removed, by);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* -------------------------------------------------------------------------
|
||||
* NBLoadedTLDef::Phase-methods
|
||||
* ----------------------------------------------------------------------- */
|
||||
NBLoadedTLDef::NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id,
|
||||
const std::vector<NBNode*>& junctions, SUMOTime offset, TrafficLightType type) :
|
||||
NBTrafficLightDefinition(id, junctions, DefaultProgramID, offset, type),
|
||||
myEdgeCont(&ec) {
|
||||
}
|
||||
|
||||
|
||||
NBLoadedTLDef::NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id, NBNode* junction, SUMOTime offset, TrafficLightType type) :
|
||||
NBTrafficLightDefinition(id, junction, DefaultProgramID, offset, type),
|
||||
myEdgeCont(&ec) {
|
||||
}
|
||||
|
||||
|
||||
NBLoadedTLDef::NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id, SUMOTime offset, TrafficLightType type) :
|
||||
NBTrafficLightDefinition(id, DefaultProgramID, offset, type),
|
||||
myEdgeCont(&ec) {
|
||||
}
|
||||
|
||||
|
||||
NBLoadedTLDef::~NBLoadedTLDef() {
|
||||
for (SignalGroupCont::iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); ++i) {
|
||||
delete (*i).second;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NBTrafficLightLogic*
|
||||
NBLoadedTLDef::myCompute(int brakingTimeSeconds) {
|
||||
MsgHandler::getWarningInstance()->clear(); // !!!
|
||||
NBLoadedTLDef::SignalGroupCont::const_iterator i;
|
||||
// compute the switching times
|
||||
std::set<double> tmpSwitchTimes;
|
||||
for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
NBLoadedTLDef::SignalGroup* group = (*i).second;
|
||||
// needed later
|
||||
group->sortPhases();
|
||||
// patch the yellow time for this group
|
||||
group->patchTYellow(brakingTimeSeconds, OptionsCont::getOptions().getBool("tls.yellow.patch-small"));
|
||||
// copy the now valid times into the container
|
||||
// both the given red and green phases are added and also the
|
||||
// yellow times
|
||||
std::vector<double> gtimes = group->getTimes(myCycleDuration);
|
||||
for (std::vector<double>::const_iterator k = gtimes.begin(); k != gtimes.end(); k++) {
|
||||
tmpSwitchTimes.insert(*k);
|
||||
}
|
||||
}
|
||||
std::vector<double> switchTimes;
|
||||
copy(tmpSwitchTimes.begin(), tmpSwitchTimes.end(), back_inserter(switchTimes));
|
||||
sort(switchTimes.begin(), switchTimes.end());
|
||||
|
||||
// count the signals
|
||||
int noSignals = 0;
|
||||
for (i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
noSignals += (*i).second->getLinkNo();
|
||||
}
|
||||
// build the phases
|
||||
NBTrafficLightLogic* logic = new NBTrafficLightLogic(getID(), getProgramID(), noSignals, myOffset, myType);
|
||||
for (std::vector<double>::iterator l = switchTimes.begin(); l != switchTimes.end(); l++) {
|
||||
// compute the duration of the current phase
|
||||
int duration;
|
||||
if (l != switchTimes.end() - 1) {
|
||||
// get from the difference to the next switching time
|
||||
duration = (int)((*(l + 1)) - (*l));
|
||||
} else {
|
||||
// get from the differenc to the first switching time
|
||||
duration = (int)(myCycleDuration - (*l) + * (switchTimes.begin()));
|
||||
}
|
||||
// no information about yellow times will be generated
|
||||
assert((*l) >= 0);
|
||||
logic->addStep(TIME2STEPS(duration), buildPhaseState((int)(*l)));
|
||||
}
|
||||
// check whether any warnings were printed
|
||||
if (MsgHandler::getWarningInstance()->wasInformed()) {
|
||||
WRITE_WARNING("During computation of traffic light '" + getID() + "'.");
|
||||
}
|
||||
logic->closeBuilding();
|
||||
|
||||
// initialize myNeedsContRelation
|
||||
myNeedsContRelation.clear();
|
||||
const bool controlledWithin = !OptionsCont::getOptions().getBool("tls.uncontrolled-within");
|
||||
const std::vector<NBTrafficLightLogic::PhaseDefinition> phases = logic->getPhases();
|
||||
for (std::vector<NBTrafficLightLogic::PhaseDefinition>::const_iterator it = phases.begin(); it != phases.end(); it++) {
|
||||
const std::string state = (*it).state;
|
||||
for (NBConnectionVector::const_iterator it1 = myControlledLinks.begin(); it1 != myControlledLinks.end(); it1++) {
|
||||
const NBConnection& c1 = *it1;
|
||||
const int i1 = c1.getTLIndex();
|
||||
if (i1 == NBConnection::InvalidTlIndex || state[i1] != 'g' || c1.getFrom() == nullptr || c1.getTo() == nullptr) {
|
||||
continue;
|
||||
}
|
||||
for (NBConnectionVector::const_iterator it2 = myControlledLinks.begin(); it2 != myControlledLinks.end(); it2++) {
|
||||
const NBConnection& c2 = *it2;
|
||||
const int i2 = c2.getTLIndex();
|
||||
if (i2 != NBConnection::InvalidTlIndex
|
||||
&& i2 != i1
|
||||
&& (state[i2] == 'G' || state[i2] == 'g')
|
||||
&& c2.getFrom() != nullptr && c2.getTo() != nullptr) {
|
||||
const bool rightTurnConflict = NBNode::rightTurnConflict(
|
||||
c1.getFrom(), c1.getTo(), c1.getFromLane(), c2.getFrom(), c2.getTo(), c2.getFromLane());
|
||||
if (forbids(c2.getFrom(), c2.getTo(), c1.getFrom(), c1.getTo(), true, controlledWithin) || rightTurnConflict) {
|
||||
myNeedsContRelation.insert(StreamPair(c1.getFrom(), c1.getTo(), c2.getFrom(), c2.getTo()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
myNeedsContRelationReady = true;
|
||||
|
||||
return logic;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::setTLControllingInformation() const {
|
||||
// assign the tl-indices to the edge connections
|
||||
for (NBConnectionVector::const_iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
const NBConnection& c = *it;
|
||||
if (c.getTLIndex() != NBConnection::InvalidTlIndex) {
|
||||
c.getFrom()->setControllingTLInformation(c, getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
NBLoadedTLDef::buildPhaseState(int time) const {
|
||||
int pos = 0;
|
||||
std::string state;
|
||||
// set the green and yellow information first;
|
||||
// the information whether other have to break needs those masks
|
||||
// completely filled
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
SignalGroup* group = (*i).second;
|
||||
int linkNo = group->getLinkNo();
|
||||
bool mayDrive = group->mayDrive(time);
|
||||
bool hasYellow = group->hasYellow(time);
|
||||
char c = 'r';
|
||||
if (mayDrive) {
|
||||
c = 'g';
|
||||
}
|
||||
if (hasYellow) {
|
||||
c = 'y';
|
||||
}
|
||||
for (int j = 0; j < linkNo; j++) {
|
||||
const NBConnection& conn = group->getConnection(j);
|
||||
NBConnection assConn(conn);
|
||||
// assert that the connection really exists
|
||||
if (assConn.check(*myEdgeCont)) {
|
||||
state = state + c;
|
||||
++pos;
|
||||
}
|
||||
}
|
||||
}
|
||||
// set the braking mask
|
||||
pos = 0;
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
SignalGroup* group = (*i).second;
|
||||
int linkNo = group->getLinkNo();
|
||||
for (int j = 0; j < linkNo; j++) {
|
||||
const NBConnection& conn = group->getConnection(j);
|
||||
NBConnection assConn(conn);
|
||||
if (assConn.check(*myEdgeCont)) {
|
||||
if (!mustBrake(assConn, state, pos)) {
|
||||
if (state[pos] == 'g') {
|
||||
state[pos] = 'G';
|
||||
}
|
||||
if (state[pos] == 'y') {
|
||||
state[pos] = 'Y';
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::mustBrake(const NBConnection& possProhibited,
|
||||
const std::string& state,
|
||||
int strmpos) const {
|
||||
// check whether the stream has red
|
||||
if (state[strmpos] != 'g' && state[strmpos] != 'G') {
|
||||
return true;
|
||||
}
|
||||
|
||||
// check whether another stream which has green is a higher
|
||||
// priorised foe to the given
|
||||
int pos = 0;
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
SignalGroup* group = (*i).second;
|
||||
// get otherlinks that have green
|
||||
int linkNo = group->getLinkNo();
|
||||
for (int j = 0; j < linkNo; j++) {
|
||||
// get the current connection (possible foe)
|
||||
const NBConnection& other = group->getConnection(j);
|
||||
NBConnection possProhibitor(other);
|
||||
// if the connction ist still valid ...
|
||||
if (possProhibitor.check(*myEdgeCont)) {
|
||||
// ... do nothing if it starts at the same edge
|
||||
if (possProhibited.getFrom() == possProhibitor.getFrom()) {
|
||||
pos++;
|
||||
continue;
|
||||
}
|
||||
if (state[pos] == 'g' || state[pos] == 'G') {
|
||||
if (NBTrafficLightDefinition::mustBrake(possProhibited, possProhibitor, true)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
pos++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::setParticipantsInformation() {
|
||||
// assign participating nodes to the request
|
||||
collectNodes();
|
||||
// collect the information about participating edges and links
|
||||
collectEdges();
|
||||
collectLinks();
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedTLDef::collectNodes() {
|
||||
myControlledNodes.clear();
|
||||
SignalGroupCont::const_iterator m;
|
||||
for (m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
|
||||
SignalGroup* group = (*m).second;
|
||||
int linkNo = group->getLinkNo();
|
||||
for (int j = 0; j < linkNo; j++) {
|
||||
const NBConnection& conn = group->getConnection(j);
|
||||
NBEdge* edge = conn.getFrom();
|
||||
NBNode* node = edge->getToNode();
|
||||
myControlledNodes.push_back(node);
|
||||
}
|
||||
}
|
||||
std::sort(myControlledNodes.begin(), myControlledNodes.end(), NBNode::nodes_by_id_sorter());
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::collectLinks() {
|
||||
myControlledLinks.clear();
|
||||
// build the list of links which are controled by the traffic light
|
||||
for (EdgeVector::iterator i = myIncomingEdges.begin(); i != myIncomingEdges.end(); i++) {
|
||||
NBEdge* incoming = *i;
|
||||
int noLanes = incoming->getNumLanes();
|
||||
for (int j = 0; j < noLanes; j++) {
|
||||
std::vector<NBEdge::Connection> elv = incoming->getConnectionsFromLane(j);
|
||||
for (std::vector<NBEdge::Connection>::iterator k = elv.begin(); k != elv.end(); k++) {
|
||||
NBEdge::Connection el = *k;
|
||||
if (el.toEdge != nullptr) {
|
||||
myControlledLinks.push_back(NBConnection(incoming, j, el.toEdge, el.toLane));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// assign tl-indices to myControlledLinks
|
||||
int pos = 0;
|
||||
for (SignalGroupCont::const_iterator m = mySignalGroups.begin(); m != mySignalGroups.end(); m++) {
|
||||
SignalGroup* group = (*m).second;
|
||||
int linkNo = group->getLinkNo();
|
||||
for (int j = 0; j < linkNo; j++) {
|
||||
const NBConnection& conn = group->getConnection(j);
|
||||
assert(conn.getFromLane() < 0 || (int) conn.getFrom()->getNumLanes() > conn.getFromLane());
|
||||
NBConnection tst(conn);
|
||||
tst.setTLIndex(pos);
|
||||
if (tst.check(*myEdgeCont)) {
|
||||
if (tst.getFrom()->mayBeTLSControlled(tst.getFromLane(), tst.getTo(), tst.getToLane())) {
|
||||
for (NBConnectionVector::iterator it = myControlledLinks.begin(); it != myControlledLinks.end(); it++) {
|
||||
NBConnection& c = *it;
|
||||
if (c.getTLIndex() == NBConnection::InvalidTlIndex
|
||||
&& tst.getFrom() == c.getFrom() && tst.getTo() == c.getTo()
|
||||
&& (tst.getFromLane() < 0 || tst.getFromLane() == c.getFromLane())
|
||||
&& (tst.getToLane() < 0 || tst.getToLane() == c.getToLane())) {
|
||||
c.setTLIndex(pos);
|
||||
}
|
||||
}
|
||||
//std::cout << getID() << " group=" << (*m).first << " tst=" << tst << "\n";
|
||||
pos++;
|
||||
}
|
||||
} else {
|
||||
WRITE_WARNING("Could not set signal on connection (signal: " + getID() + ", group: " + group->getID() + ")");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NBLoadedTLDef::SignalGroup*
|
||||
NBLoadedTLDef::findGroup(NBEdge* from, NBEdge* to) const {
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
if ((*i).second->containsConnection(from, to)) {
|
||||
return (*i).second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
|
||||
const NBConnection& connection) {
|
||||
if (mySignalGroups.find(groupid) == mySignalGroups.end()) {
|
||||
return false;
|
||||
}
|
||||
mySignalGroups[groupid]->addConnection(connection);
|
||||
NBNode* n1 = connection.getFrom()->getToNode();
|
||||
if (n1 != nullptr) {
|
||||
addNode(n1);
|
||||
n1->addTrafficLight(this);
|
||||
}
|
||||
NBNode* n2 = connection.getTo()->getFromNode();
|
||||
if (n2 != nullptr) {
|
||||
addNode(n2);
|
||||
n2->addTrafficLight(this);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBLoadedTLDef::addToSignalGroup(const std::string& groupid,
|
||||
const NBConnectionVector& connections) {
|
||||
bool ok = true;
|
||||
for (NBConnectionVector::const_iterator i = connections.begin(); i != connections.end(); i++) {
|
||||
ok &= addToSignalGroup(groupid, *i);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::addSignalGroup(const std::string& id) {
|
||||
assert(mySignalGroups.find(id) == mySignalGroups.end());
|
||||
mySignalGroups[id] = new SignalGroup(id);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::addSignalGroupPhaseBegin(const std::string& groupid, SUMOTime time,
|
||||
TLColor color) {
|
||||
assert(mySignalGroups.find(groupid) != mySignalGroups.end());
|
||||
mySignalGroups[groupid]->addPhaseBegin(time, color);
|
||||
}
|
||||
|
||||
void
|
||||
NBLoadedTLDef::setSignalYellowTimes(const std::string& groupid,
|
||||
SUMOTime myTRedYellow, SUMOTime myTYellow) {
|
||||
assert(mySignalGroups.find(groupid) != mySignalGroups.end());
|
||||
mySignalGroups[groupid]->setYellowTimes(myTRedYellow, myTYellow);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::setCycleDuration(int cycleDur) {
|
||||
myCycleDuration = cycleDur;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::remapRemoved(NBEdge* removed,
|
||||
const EdgeVector& incoming,
|
||||
const EdgeVector& outgoing) {
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
SignalGroup* group = (*i).second;
|
||||
if (group->containsIncoming(removed)) {
|
||||
group->remapIncoming(removed, incoming);
|
||||
}
|
||||
if (group->containsOutgoing(removed)) {
|
||||
group->remapOutgoing(removed, outgoing);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::replaceRemoved(NBEdge* removed, int removedLane,
|
||||
NBEdge* by, int byLane, bool incoming) {
|
||||
for (SignalGroupCont::const_iterator i = mySignalGroups.begin(); i != mySignalGroups.end(); i++) {
|
||||
SignalGroup* group = (*i).second;
|
||||
if ((incoming && group->containsIncoming(removed)) || (!incoming && group->containsOutgoing(removed))) {
|
||||
group->remap(removed, removedLane, by, byLane);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBLoadedTLDef::initNeedsContRelation() const {
|
||||
if (!myNeedsContRelationReady) {
|
||||
throw ProcessError("myNeedsContRelation was not propperly initialized\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBLoadedTLDef::getMaxIndex() {
|
||||
setParticipantsInformation();
|
||||
NBTrafficLightLogic* logic = compute(OptionsCont::getOptions());
|
||||
if (logic != nullptr) {
|
||||
return logic->getNumLinks() - 1;
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,386 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBLoadedTLDef.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Sascha Krieg
|
||||
/// @date Fri, 29.04.2005
|
||||
///
|
||||
// A loaded (complete) traffic light logic
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include "NBTrafficLightDefinition.h"
|
||||
#include "NBNode.h"
|
||||
#include <utils/common/SUMOTime.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBLoadedTLDef
|
||||
* @brief A loaded (complete) traffic light logic
|
||||
*/
|
||||
class NBLoadedTLDef : public NBTrafficLightDefinition {
|
||||
public:
|
||||
/** @class SignalGroup
|
||||
* @brief A single signal group, may control several connections
|
||||
*/
|
||||
class SignalGroup : public Named {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the signal group
|
||||
*/
|
||||
SignalGroup(const std::string& id);
|
||||
|
||||
/// @brief Destructor
|
||||
~SignalGroup();
|
||||
|
||||
/** @brief Inserts a controlled connection
|
||||
* @param[in] c The connection to be controlled by this signal group
|
||||
*/
|
||||
void addConnection(const NBConnection& c);
|
||||
|
||||
/** @brief Sets the begin of a phase
|
||||
* @param[in] time The time at which the phase starts
|
||||
* @param[in] color The color of this signal starting at the given time
|
||||
*/
|
||||
void addPhaseBegin(SUMOTime time, TLColor color);
|
||||
|
||||
/** @brief Sets the times for redyellow and yellow
|
||||
* @param[in] tRedYellowe The duration of the redyellow phase
|
||||
* @param[in] tYellow The duration of the yellow phase
|
||||
*/
|
||||
void setYellowTimes(SUMOTime tRedYellowe, SUMOTime tYellow);
|
||||
|
||||
/** @brief Returns the times at which the signal switches
|
||||
* @param[in] cycleDuration The duration of the complete cycle
|
||||
* @return The switch times of this signal
|
||||
*/
|
||||
std::vector<double> getTimes(SUMOTime cycleDuration) const;
|
||||
|
||||
/** @brief Sorts the phases */
|
||||
void sortPhases();
|
||||
|
||||
/** @brief Returns the number of links (connection) controlled by this signal
|
||||
* @return The number of links controlled by this signal
|
||||
*/
|
||||
int getLinkNo() const;
|
||||
|
||||
/** @brief Returns whether vehicles on controlled links may drive at the given time
|
||||
* @param[in] time The regarded time
|
||||
* @return Whether vehicles may drive at this time
|
||||
*/
|
||||
bool mayDrive(SUMOTime time) const;
|
||||
|
||||
/** @brief Returns whether controlled links have yellow at the given time
|
||||
* @param[in] time The regarded time
|
||||
* @return Whether controlled links are yellow at this time
|
||||
*/
|
||||
bool hasYellow(SUMOTime time) const;
|
||||
|
||||
/** @brief Returns whether the given connection is controlled by this signal
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] from The connection's end edge
|
||||
* @return Whether the connection is controlled by this signal
|
||||
*/
|
||||
bool containsConnection(NBEdge* from, NBEdge* to) const;
|
||||
|
||||
/** @brief Returns whether this signal controls the given edge
|
||||
* @param[in] from The incoming edge
|
||||
* @return Whether this edge is controlled by this signal
|
||||
*/
|
||||
bool containsIncoming(NBEdge* from) const;
|
||||
|
||||
/** @brief Replaces the given incoming edge by the others given
|
||||
* @param[in] which The edge to replace
|
||||
* @param[in] by The replacements
|
||||
*/
|
||||
void remapIncoming(NBEdge* which, const EdgeVector& by);
|
||||
|
||||
/** @brief Returns whether this signal controls a connection where the given edge is the destination
|
||||
* @param[in] from The outgoing edge
|
||||
* @return Whether this edge's predecessing edge is controlled by this signal
|
||||
*/
|
||||
bool containsOutgoing(NBEdge* to) const;
|
||||
|
||||
/** @brief Replaces the given outgoing edge by the others given
|
||||
* @param[in] which The edge to replace
|
||||
* @param[in] by The replacements
|
||||
*/
|
||||
void remapOutgoing(NBEdge* which, const EdgeVector& by);
|
||||
|
||||
/** @brief Returns the connection at the given index
|
||||
* @param[in] pos The position within this signal
|
||||
* @return The connection at the given index
|
||||
*/
|
||||
const NBConnection& getConnection(int pos) const;
|
||||
|
||||
/** @brief Sets the yellow time
|
||||
* @param[in] tyellow The yellow time to set in seconds
|
||||
* @param[in] forced Whether resetting tyellow was forced by the user by setting "tls.yellow.patch-small"
|
||||
*/
|
||||
void patchTYellow(int tyellow, bool forced);
|
||||
|
||||
/** @brief Replaces a removed edge/lane
|
||||
* @param[in] removed The edge to replace
|
||||
* @param[in] removedLane The lane of this edge to replace
|
||||
* @param[in] by The edge to insert instead
|
||||
* @param[in] byLane This edge's lane to insert instead
|
||||
*/
|
||||
void remap(NBEdge* removed, int removedLane, NBEdge* by, int byLane);
|
||||
|
||||
/** @class PhaseDef
|
||||
* @brief Definition of a single, loaded phase
|
||||
*/
|
||||
class PhaseDef {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] time The begin time of this phase
|
||||
* @param[in] color A signal's color from this time
|
||||
*/
|
||||
PhaseDef(SUMOTime time, TLColor color)
|
||||
: myTime(time), myColor(color) { }
|
||||
|
||||
/// @brief The begin time of this phase
|
||||
SUMOTime myTime;
|
||||
/// @brief A signal's color from this time
|
||||
TLColor myColor;
|
||||
};
|
||||
|
||||
/** @class phase_by_time_sorter
|
||||
* @brief Sorts phases by their begin time
|
||||
*/
|
||||
class phase_by_time_sorter {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
explicit phase_by_time_sorter() { }
|
||||
|
||||
/** @brief Sorts phases by their begin time
|
||||
* @param[in] p1 a phase definition
|
||||
* @param[in] p2 a phase definition
|
||||
*/
|
||||
int operator()(const PhaseDef& p1, const PhaseDef& p2) {
|
||||
return p1.myTime < p2.myTime;
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
/// @brief Connections controlled by this signal
|
||||
NBConnectionVector myConnections;
|
||||
/// @brief The phases of this signal
|
||||
std::vector<PhaseDef> myPhases;
|
||||
/// @brief The times of redyellow and yellow
|
||||
SUMOTime myTRedYellow, myTYellow;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/// @brief Definition of the container for signal groups
|
||||
typedef std::map<std::string, SignalGroup*> SignalGroupCont;
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] junctions Junctions controlled by this tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id,
|
||||
const std::vector<NBNode*>& junctions, SUMOTime offset,
|
||||
TrafficLightType type);
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] junction The junction controlled by this tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id, NBNode* junction, SUMOTime offset,
|
||||
TrafficLightType type);
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBLoadedTLDef(const NBEdgeCont& ec, const std::string& id, SUMOTime offset,
|
||||
TrafficLightType type);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBLoadedTLDef();
|
||||
|
||||
|
||||
/** @brief Returns the signal group which is responsible for the given connection
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] to The connection's end edge
|
||||
* @return The signal group which controls the given connection
|
||||
*/
|
||||
SignalGroup* findGroup(NBEdge* from, NBEdge* to) const;
|
||||
|
||||
|
||||
/** @brief Sets the duration of a cycle
|
||||
* @param[in] cycleDur The duration of the cycle
|
||||
*/
|
||||
void setCycleDuration(int cycleDur);
|
||||
|
||||
|
||||
/** @brief Adds a signal group
|
||||
* @param[in] id The id of the signal group
|
||||
*/
|
||||
void addSignalGroup(const std::string& id);
|
||||
|
||||
|
||||
/** @brief Adds a connection to a signal group
|
||||
* @param[in] groupid The id of the signal group to add the connection to
|
||||
* @param[in] connection The connection to add
|
||||
*/
|
||||
bool addToSignalGroup(const std::string& groupid,
|
||||
const NBConnection& connection);
|
||||
|
||||
|
||||
/** @brief Adds a list of connections to a signal group
|
||||
* @param[in] groupid The id of the signal group to add the connections to
|
||||
* @param[in] connections The connections to add
|
||||
*/
|
||||
bool addToSignalGroup(const std::string& groupid,
|
||||
const NBConnectionVector& connections);
|
||||
|
||||
|
||||
/** @brief Sets the information about the begin of a phase
|
||||
* @param[in] groupid The id of the signal group to add the phase to
|
||||
* @param[in] time The time the phase starts at
|
||||
* @param[in] color The color of the signal during this phase
|
||||
*/
|
||||
void addSignalGroupPhaseBegin(const std::string& groupid,
|
||||
SUMOTime time, TLColor color);
|
||||
|
||||
|
||||
/** @brief Sets the times the light is yellow or red/yellow
|
||||
* @param[in] groupid The id of the signal group to add the phase to
|
||||
* @param[in] tRedYellow The duration of redyellow
|
||||
* @param[in] tYellow The duration of yellow
|
||||
*/
|
||||
void setSignalYellowTimes(const std::string& groupid,
|
||||
SUMOTime tRedYellow, SUMOTime tYellow);
|
||||
|
||||
|
||||
/// @name Public methods from NBTrafficLightDefinition-interface
|
||||
/// @{
|
||||
|
||||
/** @brief Informs edges about being controlled by a tls
|
||||
* @param[in] ec The container of edges
|
||||
* @see NBTrafficLightDefinition::setTLControllingInformation
|
||||
*/
|
||||
void setTLControllingInformation() const;
|
||||
|
||||
|
||||
/** @brief Replaces occurences of the removed edge in incoming/outgoing edges of all definitions
|
||||
* @param[in] removed The removed edge
|
||||
* @param[in] incoming The edges to use instead if an incoming edge was removed
|
||||
* @param[in] outgoing The edges to use instead if an outgoing edge was removed
|
||||
* @see NBTrafficLightDefinition::remapRemoved
|
||||
*/
|
||||
void remapRemoved(NBEdge* removed,
|
||||
const EdgeVector& incoming, const EdgeVector& outgoing);
|
||||
|
||||
/* initialize myNeedsContRelation and set myNeedsContRelationReady to true */
|
||||
void initNeedsContRelation() const;
|
||||
|
||||
///@brief Returns the maximum index controlled by this traffic light
|
||||
int getMaxIndex();
|
||||
|
||||
/// @}
|
||||
|
||||
|
||||
protected:
|
||||
/// @name Protected methods from NBTrafficLightDefinition-interface
|
||||
/// @{
|
||||
|
||||
/** @brief Computes the traffic light logic finally in dependence to the type
|
||||
* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls in seconds
|
||||
* @return The computed logic
|
||||
* @see NBTrafficLightDefinition::myCompute
|
||||
*/
|
||||
NBTrafficLightLogic* myCompute(int brakingTimeSeconds);
|
||||
|
||||
/** @brief Builds the list of participating nodes/edges/links
|
||||
* @see NBTrafficLightDefinition::setParticipantsInformation
|
||||
*/
|
||||
void setParticipantsInformation();
|
||||
|
||||
|
||||
/** @brief Collects the nodes participating in this traffic light
|
||||
* @see NBTrafficLightDefinition::collectNodes
|
||||
*/
|
||||
void collectNodes();
|
||||
|
||||
|
||||
/** @brief Collects the links participating in this traffic light
|
||||
* @exception ProcessError If a link could not be found
|
||||
* @see NBTrafficLightDefinition::collectLinks
|
||||
*/
|
||||
void collectLinks();
|
||||
|
||||
|
||||
/** @brief Returns the information whether a connection must brake, given a phase
|
||||
* @param[in] possProhibited The connection to investigate
|
||||
* @param[in] state The state
|
||||
* @param[in] strmpos The index of this connection within the masks
|
||||
* @return Whether the given connection must brake
|
||||
*/
|
||||
bool mustBrake(const NBConnection& possProhibited,
|
||||
const std::string& state,
|
||||
int strmpos) const;
|
||||
|
||||
|
||||
/** @brief Replaces a removed edge/lane
|
||||
* @param[in] removed The edge to replace
|
||||
* @param[in] removedLane The lane of this edge to replace
|
||||
* @param[in] by The edge to insert instead
|
||||
* @param[in] byLane This edge's lane to insert instead
|
||||
* @see NBTrafficLightDefinition::replaceRemoved
|
||||
*/
|
||||
void replaceRemoved(NBEdge* removed, int removedLane,
|
||||
NBEdge* by, int byLane, bool incoming);
|
||||
/// @}
|
||||
|
||||
private:
|
||||
/** @brief Builds the phase for a given time
|
||||
* @param[in] ec The edge control to use
|
||||
* @param[in] time The time to build the phase for
|
||||
* @return The phase of this tls for the given time
|
||||
*/
|
||||
std::string buildPhaseState(int time) const;
|
||||
|
||||
// pointer to the NBEdgeCont for checking edges
|
||||
const NBEdgeCont* myEdgeCont;
|
||||
|
||||
|
||||
private:
|
||||
/// @brief Controlled signal groups
|
||||
SignalGroupCont mySignalGroups;
|
||||
|
||||
/// @brief The duration of a single cycle
|
||||
int myCycleDuration;
|
||||
|
||||
|
||||
};
|
|
@ -1,754 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBNetBuilder.cpp
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Thimor Bohn
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @author Walter Bamberger
|
||||
/// @date 20 Nov 2001
|
||||
///
|
||||
// Instance responsible for building networks
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include "NBNetBuilder.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBTrafficLightLogicCont.h"
|
||||
#include "NBDistrictCont.h"
|
||||
#include "NBDistrict.h"
|
||||
#include "NBRequest.h"
|
||||
#include "NBTypeCont.h"
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
#include <utils/common/StringTokenizer.h>
|
||||
#include <utils/common/SUMOVehicleClass.h>
|
||||
#include <utils/common/SysUtils.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/geom/GeoConvHelper.h>
|
||||
#include "NBAlgorithms.h"
|
||||
#include "NBAlgorithms_Ramps.h"
|
||||
#include "NBAlgorithms_Railway.h"
|
||||
#include "NBHeightMapper.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBNetBuilder::NBNetBuilder() :
|
||||
myEdgeCont(myTypeCont),
|
||||
myNetworkHaveCrossings(false) {
|
||||
}
|
||||
|
||||
|
||||
NBNetBuilder::~NBNetBuilder() {}
|
||||
|
||||
|
||||
void
|
||||
NBNetBuilder::applyOptions(OptionsCont& oc) {
|
||||
// apply options to type control
|
||||
myTypeCont.setDefaults(oc.getInt("default.lanenumber"), oc.getFloat("default.lanewidth"), oc.getFloat("default.speed"),
|
||||
oc.getInt("default.priority"), parseVehicleClasses("", oc.getString("default.disallow")));
|
||||
// apply options to edge control
|
||||
myEdgeCont.applyOptions(oc);
|
||||
// apply options to traffic light logics control
|
||||
myTLLCont.applyOptions(oc);
|
||||
NBEdge::setDefaultConnectionLength(oc.getFloat("default.connection-length"));
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBNetBuilder::compute(OptionsCont& oc, const std::set<std::string>& explicitTurnarounds, bool mayAddOrRemove) {
|
||||
GeoConvHelper& geoConvHelper = GeoConvHelper::getProcessing();
|
||||
|
||||
const bool lefthand = oc.getBool("lefthand");
|
||||
if (lefthand) {
|
||||
mirrorX();
|
||||
}
|
||||
|
||||
// MODIFYING THE SETS OF NODES AND EDGES
|
||||
// Removes edges that are connecting the same node
|
||||
long before = PROGRESS_BEGIN_TIME_MESSAGE("Removing self-loops");
|
||||
myNodeCont.removeSelfLoops(myDistrictCont, myEdgeCont, myTLLCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
if (mayAddOrRemove && oc.exists("remove-edges.isolated") && oc.getBool("remove-edges.isolated")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Finding isolated roads");
|
||||
myNodeCont.removeIsolatedRoads(myDistrictCont, myEdgeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
if (mayAddOrRemove && oc.exists("keep-edges.components") && oc.getInt("keep-edges.components") > 0) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Finding largest components");
|
||||
myNodeCont.removeComponents(myDistrictCont, myEdgeCont, oc.getInt("keep-edges.components"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
if (mayAddOrRemove && oc.exists("keep-edges.postload") && oc.getBool("keep-edges.postload")) {
|
||||
if (oc.isSet("keep-edges.explicit") || oc.isSet("keep-edges.input-file")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Removing unwished edges");
|
||||
myEdgeCont.removeUnwishedEdges(myDistrictCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
}
|
||||
// Processing pt stops and lines
|
||||
if (oc.exists("ptstop-output") && oc.isSet("ptstop-output")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Processing public transport stops");
|
||||
if (!(oc.exists("ptline-output") && oc.isSet("ptline-output"))
|
||||
&& !oc.getBool("ptstop-output.no-bidi")) {
|
||||
myPTStopCont.localizePTStops(myEdgeCont);
|
||||
}
|
||||
myPTStopCont.assignLanes(myEdgeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
if (oc.exists("ptline-output") && oc.isSet("ptline-output")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Revising public transport stops based on pt lines");
|
||||
myPTLineCont.process(myEdgeCont, myPTStopCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
if (oc.exists("ptline-output") && oc.isSet("ptline-output")) {
|
||||
if (oc.exists("ptline-clean-up") && oc.getBool("ptline-clean-up")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Cleaning up public transport stops that are not served by any line");
|
||||
myPTStopCont.postprocess(myPTLineCont.getServedPTStops());
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
} else {
|
||||
int numDeletedStops = myPTStopCont.cleanupDeleted(myEdgeCont);
|
||||
if (numDeletedStops > 0) {
|
||||
WRITE_WARNING("Removed " + toString(numDeletedStops) + " pt stops because they could not be assigned to the network");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && !oc.getBool("ptstop-output.no-bidi")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Align pt stop id signs with corresponding edge id signs");
|
||||
myPTStopCont.alignIdSigns();
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
// analyse and fix railway topology
|
||||
if (oc.exists("railway.topology.all-bidi") && oc.getBool("railway.topology.all-bidi")) {
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false);
|
||||
NBRailwayTopologyAnalyzer::makeAllBidi(*this);
|
||||
} else if (oc.exists("railway.topology.repair") && oc.getBool("railway.topology.repair")) {
|
||||
// correct railway angles for angle-based connectivity heuristic
|
||||
myEdgeCont.checkGeometries(0,
|
||||
oc.getFloat("geometry.min-radius"), false,
|
||||
oc.getBool("geometry.min-radius.fix.railways"), true);
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false);
|
||||
NBRailwayTopologyAnalyzer::repairTopology(*this);
|
||||
}
|
||||
if (oc.exists("railway.topology.direction-priority") && oc.getBool("railway.topology.direction-priority")) {
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); // recompute after new edges were added
|
||||
NBRailwayTopologyAnalyzer::assignDirectionPriority(*this);
|
||||
}
|
||||
if (oc.exists("railway.topology.output") && oc.isSet("railway.topology.output")) {
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false); // recompute after new edges were added
|
||||
NBRailwayTopologyAnalyzer::analyzeTopology(*this);
|
||||
}
|
||||
|
||||
|
||||
if (mayAddOrRemove && oc.exists("edges.join-tram-dist") && oc.getFloat("edges.join-tram-dist") >= 0) {
|
||||
// should come before joining junctions
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Joining tram edges");
|
||||
int numJoinedTramEdges = myEdgeCont.joinTramEdges(myDistrictCont, myPTLineCont, oc.getFloat("edges.join-tram-dist"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
if (numJoinedTramEdges > 0) {
|
||||
WRITE_MESSAGE(" Joined " + toString(numJoinedTramEdges) + " tram edges into roads.");
|
||||
}
|
||||
}
|
||||
if (oc.getBool("junctions.join")
|
||||
|| (oc.exists("ramps.guess") && oc.getBool("ramps.guess"))
|
||||
|| oc.getBool("tls.guess.joining")
|
||||
|| (oc.exists("tls.guess-signals") && oc.getBool("tls.guess-signals"))) {
|
||||
// preliminary geometry computations to determine the length of edges
|
||||
// This depends on turning directions and sorting of edge list
|
||||
// in case junctions are joined geometry computations have to be repeated
|
||||
// preliminary roundabout computations to avoid damaging roundabouts via junctions.join or ramps.guess
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false);
|
||||
NBNodesEdgesSorter::sortNodesEdges(myNodeCont);
|
||||
myEdgeCont.computeLaneShapes();
|
||||
myNodeCont.computeNodeShapes();
|
||||
myEdgeCont.computeEdgeShapes();
|
||||
if (oc.getBool("roundabouts.guess")) {
|
||||
myEdgeCont.guessRoundabouts();
|
||||
}
|
||||
const std::set<EdgeSet>& roundabouts = myEdgeCont.getRoundabouts();
|
||||
for (std::set<EdgeSet>::const_iterator it_round = roundabouts.begin();
|
||||
it_round != roundabouts.end(); ++it_round) {
|
||||
std::vector<std::string> nodeIDs;
|
||||
for (EdgeSet::const_iterator it_edge = it_round->begin(); it_edge != it_round->end(); ++it_edge) {
|
||||
nodeIDs.push_back((*it_edge)->getToNode()->getID());
|
||||
}
|
||||
myNodeCont.addJoinExclusion(nodeIDs);
|
||||
}
|
||||
NBNodeTypeComputer::validateRailCrossings(myNodeCont, myTLLCont);
|
||||
}
|
||||
// join junctions (may create new "geometry"-nodes so it needs to come before removing these
|
||||
if (mayAddOrRemove && oc.exists("junctions.join-exclude") && oc.isSet("junctions.join-exclude")) {
|
||||
myNodeCont.addJoinExclusion(oc.getStringVector("junctions.join-exclude"));
|
||||
}
|
||||
int numJoined = myNodeCont.joinLoadedClusters(myDistrictCont, myEdgeCont, myTLLCont);
|
||||
if (mayAddOrRemove && oc.getBool("junctions.join")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Joining junction clusters");
|
||||
numJoined += myNodeCont.joinJunctions(oc.getFloat("junctions.join-dist"), myDistrictCont, myEdgeCont, myTLLCont, myPTStopCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
if (numJoined > 0) {
|
||||
// bit of a misnomer since we're already done
|
||||
WRITE_MESSAGE(" Joined " + toString(numJoined) + " junction cluster(s).");
|
||||
}
|
||||
//
|
||||
if (mayAddOrRemove && oc.exists("join-lanes") && oc.getBool("join-lanes")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Joining lanes");
|
||||
const int num = myEdgeCont.joinLanes(SVC_IGNORING) + myEdgeCont.joinLanes(SVC_PEDESTRIAN);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
WRITE_MESSAGE(" Joined lanes on " + toString(num) + " edges.");
|
||||
}
|
||||
//
|
||||
if (mayAddOrRemove) {
|
||||
int no = 0;
|
||||
const bool removeGeometryNodes = oc.exists("geometry.remove") && oc.getBool("geometry.remove");
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Removing empty nodes" + std::string(removeGeometryNodes ? " and geometry nodes" : ""));
|
||||
// removeUnwishedNodes needs turnDirections. @todo: try to call this less often
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false);
|
||||
no = myNodeCont.removeUnwishedNodes(myDistrictCont, myEdgeCont, myTLLCont, myPTStopCont, myPTLineCont, myParkingCont, removeGeometryNodes);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
WRITE_MESSAGE(" " + toString(no) + " nodes removed.");
|
||||
}
|
||||
|
||||
// MOVE TO ORIGIN
|
||||
// compute new boundary after network modifications have taken place
|
||||
Boundary boundary;
|
||||
for (std::map<std::string, NBNode*>::const_iterator it = myNodeCont.begin(); it != myNodeCont.end(); ++it) {
|
||||
boundary.add(it->second->getPosition());
|
||||
}
|
||||
for (std::map<std::string, NBEdge*>::const_iterator it = myEdgeCont.begin(); it != myEdgeCont.end(); ++it) {
|
||||
boundary.add(it->second->getGeometry().getBoxBoundary());
|
||||
}
|
||||
geoConvHelper.setConvBoundary(boundary);
|
||||
|
||||
if (!oc.getBool("offset.disable-normalization") && oc.isDefault("offset.x") && oc.isDefault("offset.y")) {
|
||||
moveToOrigin(geoConvHelper, lefthand);
|
||||
}
|
||||
geoConvHelper.computeFinal(lefthand); // information needed for location element fixed at this point
|
||||
|
||||
if (oc.exists("geometry.min-dist") && !oc.isDefault("geometry.min-dist")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Reducing geometries");
|
||||
myEdgeCont.reduceGeometries(oc.getFloat("geometry.min-dist"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
// @note: removing geometry can create similar edges so joinSimilarEdges must come afterwards
|
||||
// @note: likewise splitting can destroy similarities so joinSimilarEdges must come before
|
||||
if (mayAddOrRemove && oc.getBool("edges.join")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Joining similar edges");
|
||||
myNodeCont.joinSimilarEdges(myDistrictCont, myEdgeCont, myTLLCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
if (oc.getBool("opposites.guess")) {
|
||||
PROGRESS_BEGIN_MESSAGE("guessing opposite direction edges");
|
||||
myEdgeCont.guessOpposites();
|
||||
PROGRESS_DONE_MESSAGE();
|
||||
}
|
||||
//
|
||||
if (mayAddOrRemove && oc.exists("geometry.split") && oc.getBool("geometry.split")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Splitting geometry edges");
|
||||
myEdgeCont.splitGeometry(myDistrictCont, myNodeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
// turning direction
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing turning directions");
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
// correct edge geometries to avoid overlap
|
||||
if (oc.exists("geometry.avoid-overlap") && oc.getBool("geometry.avoid-overlap")) {
|
||||
myNodeCont.avoidOverlap();
|
||||
}
|
||||
|
||||
// GUESS TLS POSITIONS
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Assigning nodes to traffic lights");
|
||||
if (oc.isSet("tls.set")) {
|
||||
std::vector<std::string> tlControlledNodes = oc.getStringVector("tls.set");
|
||||
TrafficLightType type = SUMOXMLDefinitions::TrafficLightTypes.get(oc.getString("tls.default-type"));
|
||||
for (std::vector<std::string>::const_iterator i = tlControlledNodes.begin(); i != tlControlledNodes.end(); ++i) {
|
||||
NBNode* node = myNodeCont.retrieve(*i);
|
||||
if (node == nullptr) {
|
||||
WRITE_WARNING("Building a tl-logic for junction '" + *i + "' is not possible." + "\n The junction '" + *i + "' is not known.");
|
||||
} else {
|
||||
myNodeCont.setAsTLControlled(node, myTLLCont, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
myNodeCont.guessTLs(oc, myTLLCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
|
||||
// guess ramps (after guessing tls because ramps should not be build at traffic lights)
|
||||
const bool modifyRamps = mayAddOrRemove && (
|
||||
(oc.exists("ramps.guess") && oc.getBool("ramps.guess"))
|
||||
|| (oc.exists("ramps.set") && oc.isSet("ramps.set")));
|
||||
if (modifyRamps || (oc.exists("ramps.guess-acceleration-lanes") && oc.getBool("ramps.guess-acceleration-lanes"))) {
|
||||
before = SysUtils::getCurrentMillis();
|
||||
if (modifyRamps) {
|
||||
PROGRESS_BEGIN_MESSAGE("Guessing and setting on-/off-ramps");
|
||||
}
|
||||
NBNodesEdgesSorter::sortNodesEdges(myNodeCont);
|
||||
NBRampsComputer::computeRamps(*this, oc);
|
||||
if (modifyRamps) {
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
}
|
||||
// guess bike lanes
|
||||
int addedLanes = 0;
|
||||
if (mayAddOrRemove && ((oc.getBool("bikelanes.guess") || oc.getBool("bikelanes.guess.from-permissions")))) {
|
||||
const int bikelanes = myEdgeCont.guessSpecialLanes(SVC_BICYCLE, oc.getFloat("default.bikelane-width"),
|
||||
oc.getFloat("bikelanes.guess.min-speed"),
|
||||
oc.getFloat("bikelanes.guess.max-speed"),
|
||||
oc.getBool("bikelanes.guess.from-permissions"),
|
||||
"bikelanes.guess.exclude");
|
||||
WRITE_MESSAGE("Guessed " + toString(bikelanes) + " bike lanes.");
|
||||
addedLanes += bikelanes;
|
||||
}
|
||||
|
||||
// guess sidewalks
|
||||
if (mayAddOrRemove && ((oc.getBool("sidewalks.guess") || oc.getBool("sidewalks.guess.from-permissions")))) {
|
||||
const int sidewalks = myEdgeCont.guessSpecialLanes(SVC_PEDESTRIAN, oc.getFloat("default.sidewalk-width"),
|
||||
oc.getFloat("sidewalks.guess.min-speed"),
|
||||
oc.getFloat("sidewalks.guess.max-speed"),
|
||||
oc.getBool("sidewalks.guess.from-permissions"),
|
||||
"sidewalks.guess.exclude");
|
||||
WRITE_MESSAGE("Guessed " + toString(sidewalks) + " sidewalks.");
|
||||
addedLanes += sidewalks;
|
||||
}
|
||||
// re-adapt stop lanes after adding special lanes
|
||||
if (oc.exists("ptstop-output") && oc.isSet("ptstop-output") && addedLanes > 0) {
|
||||
myPTStopCont.assignLanes(myEdgeCont);
|
||||
}
|
||||
|
||||
// check whether any not previously setable connections may be set now
|
||||
myEdgeCont.recheckPostProcessConnections();
|
||||
|
||||
// remap ids if wished
|
||||
int numChangedEdges = myEdgeCont.remapIDs(oc.getBool("numerical-ids"), oc.isSet("reserved-ids"), oc.getString("prefix"), myPTStopCont);
|
||||
int numChangedNodes = myNodeCont.remapIDs(oc.getBool("numerical-ids"), oc.isSet("reserved-ids"), oc.getString("prefix"));
|
||||
if (numChangedEdges + numChangedNodes > 0) {
|
||||
WRITE_MESSAGE("Remapped " + toString(numChangedEdges) + " edge IDs and " + toString(numChangedNodes) + " node IDs.");
|
||||
}
|
||||
|
||||
//
|
||||
if (oc.exists("geometry.max-angle")) {
|
||||
myEdgeCont.checkGeometries(
|
||||
DEG2RAD(oc.getFloat("geometry.max-angle")),
|
||||
oc.getFloat("geometry.min-radius"),
|
||||
oc.getBool("geometry.min-radius.fix"),
|
||||
oc.getBool("geometry.min-radius.fix.railways"));
|
||||
}
|
||||
|
||||
// GEOMETRY COMPUTATION
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Sorting nodes' edges");
|
||||
NBNodesEdgesSorter::sortNodesEdges(myNodeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
myEdgeCont.computeLaneShapes();
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing node shapes");
|
||||
if (oc.exists("geometry.junction-mismatch-threshold")) {
|
||||
myNodeCont.computeNodeShapes(oc.getFloat("geometry.junction-mismatch-threshold"));
|
||||
} else {
|
||||
myNodeCont.computeNodeShapes();
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing edge shapes");
|
||||
myEdgeCont.computeEdgeShapes(oc.getBool("geometry.max-grade.fix") ? oc.getFloat("geometry.max-grade") / 100 : -1);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
// resort edges based on the node and edge shapes
|
||||
NBNodesEdgesSorter::sortNodesEdges(myNodeCont, true);
|
||||
NBTurningDirectionsComputer::computeTurnDirections(myNodeCont, false);
|
||||
|
||||
// APPLY SPEED MODIFICATIONS
|
||||
if (oc.exists("speed.offset")) {
|
||||
const double speedOffset = oc.getFloat("speed.offset");
|
||||
const double speedFactor = oc.getFloat("speed.factor");
|
||||
const double speedMin = oc.getFloat("speed.minimum");
|
||||
if (speedOffset != 0 || speedFactor != 1 || speedMin > 0) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Applying speed modifications");
|
||||
for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
|
||||
(*i).second->setSpeed(-1, MAX2((*i).second->getSpeed() * speedFactor + speedOffset, speedMin));
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
}
|
||||
|
||||
// CONNECTIONS COMPUTATION
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing node types");
|
||||
NBNodeTypeComputer::computeNodeTypes(myNodeCont, myTLLCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
myNetworkHaveCrossings = oc.getBool("walkingareas");
|
||||
if (mayAddOrRemove && oc.getBool("crossings.guess")) {
|
||||
myNetworkHaveCrossings = true;
|
||||
int crossings = 0;
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
crossings += (*i).second->guessCrossings();
|
||||
}
|
||||
WRITE_MESSAGE("Guessed " + toString(crossings) + " pedestrian crossings.");
|
||||
}
|
||||
if (!myNetworkHaveCrossings) {
|
||||
// recheck whether we had crossings in the input
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
if (i->second->getCrossingsIncludingInvalid().size() > 0) {
|
||||
myNetworkHaveCrossings = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!mayAddOrRemove && myNetworkHaveCrossings) {
|
||||
// crossings added via netedit
|
||||
oc.resetWritable();
|
||||
oc.set("no-internal-links", "false");
|
||||
}
|
||||
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing priorities");
|
||||
NBEdgePriorityComputer::computeEdgePriorities(myNodeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing approached edges");
|
||||
myEdgeCont.computeEdge2Edges(oc.getBool("no-left-connections"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
if (oc.getBool("roundabouts.guess")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Guessing and setting roundabouts");
|
||||
const int numGuessed = myEdgeCont.guessRoundabouts();
|
||||
if (numGuessed > 0) {
|
||||
WRITE_MESSAGE(" Guessed " + toString(numGuessed) + " roundabout(s).");
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
myEdgeCont.markRoundabouts();
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing approaching lanes");
|
||||
myEdgeCont.computeLanes2Edges();
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Dividing of lanes on approached lanes");
|
||||
myNodeCont.computeLanes2Lanes();
|
||||
myEdgeCont.sortOutgoingLanesConnections();
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
if (oc.getBool("fringe.guess")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Guessing Network fringe");
|
||||
const int numGuessed = myNodeCont.guessFringe();
|
||||
if (numGuessed > 0) {
|
||||
WRITE_MESSAGE(" Guessed " + toString(numGuessed) + " fringe nodes.");
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Processing turnarounds");
|
||||
if (!oc.getBool("no-turnarounds")) {
|
||||
myEdgeCont.appendTurnarounds(
|
||||
oc.getBool("no-turnarounds.tls"),
|
||||
oc.getBool("no-turnarounds.fringe"),
|
||||
oc.getBool("no-turnarounds.except-deadend"),
|
||||
oc.getBool("no-turnarounds.except-turnlane"),
|
||||
oc.getBool("no-turnarounds.geometry"));
|
||||
} else {
|
||||
myEdgeCont.appendTurnarounds(explicitTurnarounds, oc.getBool("no-turnarounds.tls"));
|
||||
}
|
||||
if (oc.exists("railway.topology.repair.stop-turn") && oc.getBool("railway.topology.repair.stop-turn")
|
||||
&& myPTStopCont.getStops().size() > 0) {
|
||||
// allow direction reversal at all bidi-edges with stops
|
||||
myEdgeCont.appendRailwayTurnarounds(myPTStopCont);
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Rechecking of lane endings");
|
||||
myEdgeCont.recheckLanes();
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
|
||||
if (myNetworkHaveCrossings && !oc.getBool("no-internal-links")) {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
i->second->buildCrossingsAndWalkingAreas();
|
||||
}
|
||||
} else {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
// needed by netedit if the last crossings was deleted from the network
|
||||
// and walkingareas have been invalidated since the last call to compute()
|
||||
i->second->discardWalkingareas();
|
||||
}
|
||||
if (oc.getBool("no-internal-links")) {
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
i->second->discardAllCrossings(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
// join traffic lights (after building connections)
|
||||
if (oc.getBool("tls.join")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Joining traffic light nodes");
|
||||
myNodeCont.joinTLS(myTLLCont, oc.getFloat("tls.join-dist"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
// COMPUTING RIGHT-OF-WAY AND TRAFFIC LIGHT PROGRAMS
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing traffic light control information");
|
||||
myTLLCont.setTLControllingInformation(myEdgeCont, myNodeCont);
|
||||
if (oc.exists("opendrive-files") && oc.isSet("opendrive-files")) {
|
||||
myTLLCont.setOpenDriveSignalParameters();
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing node logics");
|
||||
myNodeCont.computeLogics(myEdgeCont);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
|
||||
//
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Computing traffic light logics");
|
||||
std::pair<int, int> numbers = myTLLCont.computeLogics(oc);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
std::string progCount = "";
|
||||
if (numbers.first != numbers.second) {
|
||||
progCount = "(" + toString(numbers.second) + " programs) ";
|
||||
}
|
||||
WRITE_MESSAGE(" " + toString(numbers.first) + " traffic light(s) " + progCount + "computed.");
|
||||
|
||||
for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
|
||||
(*i).second->sortOutgoingConnectionsByIndex();
|
||||
}
|
||||
// FINISHING INNER EDGES
|
||||
if (!oc.getBool("no-internal-links")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Building inner edges");
|
||||
// walking areas shall only be built if crossings are wished as well
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
(*i).second->buildInnerEdges();
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
// PATCH NODE SHAPES
|
||||
if (oc.getFloat("junctions.scurve-stretch") > 0) {
|
||||
// @note: nodes have collected correction hints in buildInnerEdges()
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("stretching junctions to smooth geometries");
|
||||
myEdgeCont.computeLaneShapes();
|
||||
myNodeCont.computeNodeShapes();
|
||||
myEdgeCont.computeEdgeShapes(oc.getBool("geometry.max-grade.fix") ? oc.getFloat("geometry.max-grade") / 100 : -1);
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
(*i).second->buildInnerEdges();
|
||||
}
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
// compute lane-to-lane node logics (require traffic lights and inner edges to be done)
|
||||
myNodeCont.computeLogics2(myEdgeCont, oc);
|
||||
|
||||
// remove guessed traffic lights at junctions without conflicts (requires computeLogics2)
|
||||
myNodeCont.recheckGuessedTLS(myTLLCont);
|
||||
|
||||
//
|
||||
if (oc.isSet("street-sign-output")) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Generating street signs");
|
||||
myEdgeCont.generateStreetSigns();
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
|
||||
if (lefthand != oc.getBool("flip-y-axis")) {
|
||||
mirrorX();
|
||||
};
|
||||
|
||||
if (oc.exists("geometry.check-overlap") && oc.getFloat("geometry.check-overlap") > 0) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Checking overlapping edges");
|
||||
myEdgeCont.checkOverlap(oc.getFloat("geometry.check-overlap"), oc.getFloat("geometry.check-overlap.vertical-threshold"));
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
if (geoConvHelper.getConvBoundary().getZRange() > 0 && oc.getFloat("geometry.max-grade") > 0) {
|
||||
before = PROGRESS_BEGIN_TIME_MESSAGE("Checking edge grade");
|
||||
// user input is in %
|
||||
myEdgeCont.checkGrade(oc.getFloat("geometry.max-grade") / 100);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
//find accesses for pt rail stops and add bidi-stops
|
||||
if (oc.exists("ptstop-output") && oc.isSet("ptstop-output")) {
|
||||
before = SysUtils::getCurrentMillis();
|
||||
int numBidiStops = 0;
|
||||
if (!oc.getBool("ptstop-output.no-bidi")) {
|
||||
numBidiStops = myPTStopCont.generateBidiStops(myEdgeCont);
|
||||
}
|
||||
PROGRESS_BEGIN_MESSAGE("Find accesses for pt rail stops");
|
||||
double maxRadius = oc.getFloat("railway.access-distance");
|
||||
double accessFactor = oc.getFloat("railway.access-factor");
|
||||
int maxCount = oc.getInt("railway.max-accesses");
|
||||
myPTStopCont.findAccessEdgesForRailStops(myEdgeCont, maxRadius, maxCount, accessFactor);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
if (numBidiStops > 0) {
|
||||
if (oc.exists("ptline-output") && oc.isSet("ptline-output")) {
|
||||
myPTLineCont.fixBidiStops(myEdgeCont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// report
|
||||
WRITE_MESSAGE("-----------------------------------------------------");
|
||||
WRITE_MESSAGE("Summary:");
|
||||
myNodeCont.printBuiltNodesStatistics();
|
||||
WRITE_MESSAGE(" Network boundaries:");
|
||||
WRITE_MESSAGE(" Original boundary : " + toString(geoConvHelper.getOrigBoundary()));
|
||||
WRITE_MESSAGE(" Applied offset : " + toString(geoConvHelper.getOffsetBase()));
|
||||
WRITE_MESSAGE(" Converted boundary : " + toString(geoConvHelper.getConvBoundary()));
|
||||
WRITE_MESSAGE("-----------------------------------------------------");
|
||||
NBRequest::reportWarnings();
|
||||
// report on very large networks
|
||||
if (MAX2(geoConvHelper.getConvBoundary().xmax(), geoConvHelper.getConvBoundary().ymax()) > 50000 ||
|
||||
MIN2(geoConvHelper.getConvBoundary().xmin(), geoConvHelper.getConvBoundary().ymin()) < -50000) {
|
||||
WRITE_WARNING("Network contains very large coordinates and could cause problems with Unreal Engine coordinates. The recomended maximum value in any axis is 50000");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
void
|
||||
NBNetBuilder::computeSingleNode(NBNode* node, OptionsCont& oc, const std::set<std::string>& explicitTurnarounds, bool mayAddOrRemove) {
|
||||
// for a single node do the following:
|
||||
// sortEdges
|
||||
// computeLaneShapes
|
||||
// computeNodeShapes
|
||||
// computeEdgeShapes
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
void
|
||||
NBNetBuilder::moveToOrigin(GeoConvHelper& geoConvHelper, bool lefthand) {
|
||||
long before = PROGRESS_BEGIN_TIME_MESSAGE("Moving network to origin");
|
||||
Boundary boundary = geoConvHelper.getConvBoundary();
|
||||
// Center the network
|
||||
const double x = -(boundary.xmin() + boundary.xmax())*0.5;
|
||||
const double y = -(boundary.ymin() + boundary.ymax())*0.5;
|
||||
//if (lefthand) {
|
||||
// y = boundary.ymax();
|
||||
//}
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
(*i).second->reshiftPosition(x, y);
|
||||
}
|
||||
for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
|
||||
(*i).second->reshiftPosition(x, y);
|
||||
}
|
||||
for (std::map<std::string, NBDistrict*>::const_iterator i = myDistrictCont.begin(); i != myDistrictCont.end(); ++i) {
|
||||
(*i).second->reshiftPosition(x, y);
|
||||
}
|
||||
for (std::map<std::string, NBPTStop*>::const_iterator i = myPTStopCont.begin(); i != myPTStopCont.end(); ++i) {
|
||||
(*i).second->reshiftPosition(x, y);
|
||||
}
|
||||
geoConvHelper.moveConvertedBy(x, y);
|
||||
PROGRESS_TIME_MESSAGE(before);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBNetBuilder::mirrorX() {
|
||||
// mirror the network along the X-axis
|
||||
for (std::map<std::string, NBNode*>::const_iterator i = myNodeCont.begin(); i != myNodeCont.end(); ++i) {
|
||||
(*i).second->mirrorX();
|
||||
}
|
||||
for (std::map<std::string, NBEdge*>::const_iterator i = myEdgeCont.begin(); i != myEdgeCont.end(); ++i) {
|
||||
(*i).second->mirrorX();
|
||||
}
|
||||
for (std::map<std::string, NBDistrict*>::const_iterator i = myDistrictCont.begin(); i != myDistrictCont.end(); ++i) {
|
||||
(*i).second->mirrorX();
|
||||
}
|
||||
for (std::map<std::string, NBPTStop*>::const_iterator i = myPTStopCont.begin(); i != myPTStopCont.end(); ++i) {
|
||||
(*i).second->mirrorX();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBNetBuilder::transformCoordinate(Position& from, bool includeInBoundary, GeoConvHelper* from_srs) {
|
||||
Position orig(from);
|
||||
bool ok = true;
|
||||
if (GeoConvHelper::getNumLoaded() > 1
|
||||
&& GeoConvHelper::getLoaded().usingGeoProjection()
|
||||
&& from_srs != nullptr
|
||||
&& from_srs->usingGeoProjection()
|
||||
&& *from_srs != GeoConvHelper::getLoaded()) {
|
||||
from_srs->cartesian2geo(from);
|
||||
ok &= GeoConvHelper::getLoaded().x2cartesian(from, false);
|
||||
}
|
||||
ok &= GeoConvHelper::getProcessing().x2cartesian(from, includeInBoundary);
|
||||
if (ok) {
|
||||
const NBHeightMapper& hm = NBHeightMapper::get();
|
||||
if (hm.ready()) {
|
||||
if (from_srs != nullptr && from_srs->usingGeoProjection()) {
|
||||
from_srs->cartesian2geo(orig);
|
||||
}
|
||||
from.setz(hm.getZ(orig));
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBNetBuilder::transformCoordinates(PositionVector& from, bool includeInBoundary, GeoConvHelper* from_srs) {
|
||||
const double maxLength = OptionsCont::getOptions().getFloat("geometry.max-segment-length");
|
||||
if (maxLength > 0 && from.size() > 1) {
|
||||
// transformation to cartesian coordinates must happen before we can check segment length
|
||||
PositionVector copy = from;
|
||||
for (int i = 0; i < (int) from.size(); i++) {
|
||||
transformCoordinate(copy[i], false);
|
||||
}
|
||||
addGeometrySegments(from, copy, maxLength);
|
||||
}
|
||||
bool ok = true;
|
||||
for (int i = 0; i < (int) from.size(); i++) {
|
||||
ok = ok && transformCoordinate(from[i], includeInBoundary, from_srs);
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
int
|
||||
NBNetBuilder::addGeometrySegments(PositionVector& from, const PositionVector& cartesian, const double maxLength) {
|
||||
// check lengths and insert new points where needed (in the original
|
||||
// coordinate system)
|
||||
int inserted = 0;
|
||||
for (int i = 0; i < (int)cartesian.size() - 1; i++) {
|
||||
Position start = from[i + inserted];
|
||||
Position end = from[i + inserted + 1];
|
||||
double length = cartesian[i].distanceTo(cartesian[i + 1]);
|
||||
const Position step = (end - start) * (maxLength / length);
|
||||
int steps = 0;
|
||||
while (length > maxLength) {
|
||||
length -= maxLength;
|
||||
steps++;
|
||||
from.insert(from.begin() + i + inserted + 1, start + (step * steps));
|
||||
inserted++;
|
||||
}
|
||||
}
|
||||
return inserted;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBNetBuilder::runningNetedit() {
|
||||
// see GNELoadThread::fillOptions
|
||||
return OptionsCont::getOptions().exists("new");
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,279 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBNetBuilder.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Fri, 29.04.2005
|
||||
///
|
||||
// Instance responsible for building networks
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utils/shapes/ShapeContainer.h>
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBTypeCont.h"
|
||||
#include "NBNodeCont.h"
|
||||
#include "NBNode.h"
|
||||
#include "NBParking.h"
|
||||
#include "NBTrafficLightLogicCont.h"
|
||||
#include "NBDistrictCont.h"
|
||||
#include "NBPTStopCont.h"
|
||||
#include "NBPTLineCont.h"
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OptionsCont;
|
||||
class OutputDevice;
|
||||
class GeoConvHelper;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBNetBuilder
|
||||
* @brief Instance responsible for building networks
|
||||
*
|
||||
* The class' - and the netbuild module's - functionality is embedded within the
|
||||
* compute() method.
|
||||
*
|
||||
* @addtogroup netbuild
|
||||
* @{
|
||||
*
|
||||
* -# Removing self loops
|
||||
* \n Removes edges which end at the node they start at using NBNodeCont::removeSelfLoops().
|
||||
* -# Joining double connections
|
||||
* \n Joins edges between same nodes using NBNodeCont::recheckEdges().
|
||||
* -# Finding isolated roads (optional)
|
||||
* -# Removing empty nodes and geometry nodes (optional)
|
||||
* \n Removed nodes with no incoming/outgoing edges and nodes which can be transformed into
|
||||
* geometry point using NBNodeCont::removeUnwishedNodes().
|
||||
* -# Removing unwished edges (optional)
|
||||
* \n If "keep-edges.postload" and "keep-edges.explicit" are set, the edges not within "keep-edges.explicit" are
|
||||
* removed from the network using NBEdgeCont::removeUnwishedEdges().
|
||||
* -# Rechecking nodes after edge removal (optional)
|
||||
* \n If any of the edge removing options was set ("keep-edges.explicit", "remove-edges.explicit", "keep-edges.postload",
|
||||
* "keep-edges.by-vclass", "keep-edges.input-file"), the now orphaned nodes are removed using
|
||||
* NBNodeCont::removeUnwishedNodes().
|
||||
* -# Splitting geometry edges (optional)
|
||||
* \n If "geometry.split" is set, edge geometries are converted to nodes using
|
||||
* NBEdgeCont::splitGeometry().
|
||||
* -# Normalising/transposing node positions
|
||||
* \n If "offset.disable-normalization", "offset.x", and "offset.y" are not
|
||||
* set, the road graph's instances are moved to the origin.
|
||||
* -# Guessing and setting on-/off-ramps
|
||||
* -# Guessing and setting TLs
|
||||
* -# Computing turning directions
|
||||
* -# Sorting nodes' edges
|
||||
* -# Guessing and setting roundabouts
|
||||
* -# Computing Approached Edges
|
||||
* -# Computing Approaching Lanes
|
||||
* -# Dividing of Lanes on Approached Lanes
|
||||
* -# Appending Turnarounds (optional)
|
||||
* -# Rechecking of lane endings
|
||||
* -# Computing node shapes
|
||||
* -# Computing edge shapes
|
||||
* -# Computing tls logics
|
||||
* -# Computing node logics
|
||||
* -# Computing traffic light logics
|
||||
*
|
||||
* @todo Removing unwished edges: Recheck whether this can be done during loading - whether this option/step is really needed.
|
||||
* @todo Finding isolated roads: Describe
|
||||
* @bug Removing empty nodes and geometry nodes: Ok, empty nodes should be removed, uh? But this is only done if "geometry.remove" is set.
|
||||
* @}
|
||||
*/
|
||||
class NBNetBuilder {
|
||||
friend class GNENet; // for triggering intermediate build steps
|
||||
|
||||
public:
|
||||
/// @brief Constructor
|
||||
NBNetBuilder();
|
||||
|
||||
/// @brief Destructor
|
||||
~NBNetBuilder();
|
||||
|
||||
/** @brief Initialises the storage by applying given options
|
||||
*
|
||||
* Options, mainly steering the acceptance of edges, are parsed
|
||||
* and the according internal variables are set.
|
||||
*
|
||||
* @param[in] oc The options container to read options from
|
||||
* @exception ProcessError If something fails (message is included)
|
||||
*/
|
||||
void applyOptions(OptionsCont& oc);
|
||||
|
||||
/** @brief Performs the network building steps
|
||||
*
|
||||
* @param[in] oc Container that contains options for building
|
||||
* @param[in] explicitTurnarounds List of edge ids for which turn-arounds should be added (used by NETEDIT)
|
||||
* @param[in] mayAddOrRemove whether processing steps which cause nodes and edges to be added or removed shall be triggered (used by netedit)
|
||||
* @exception ProcessError (recheck)
|
||||
*/
|
||||
void compute(OptionsCont& oc, const std::set<std::string>& explicitTurnarounds = std::set<std::string>(), bool mayAddOrRemove = true);
|
||||
|
||||
/** @brief Updates the shape for a single Node
|
||||
*
|
||||
* @param[in] oc Container that contains options for building
|
||||
* @param[in] explicitTurnarounds List of edge ids for which turn-arounds should be added (used by NETEDIT)
|
||||
* @param[in] mayAddOrRemove whether processing steps which cause nodes and edges to be added or removed shall be triggered (used by netedit)
|
||||
* @exception ProcessError (recheck)
|
||||
*/
|
||||
//void computeSingleNode(NBNode* node, OptionsCont& oc, const std::set<std::string>& explicitTurnarounds = std::set<std::string>(), bool mayAddOrRemove = true);
|
||||
|
||||
/// @name Retrieval of subcontainers
|
||||
/// @{
|
||||
/// @brief Returns a reference to edge container
|
||||
NBEdgeCont& getEdgeCont() {
|
||||
return myEdgeCont;
|
||||
}
|
||||
|
||||
/// @brief Returns a reference to the node container
|
||||
NBNodeCont& getNodeCont() {
|
||||
return myNodeCont;
|
||||
}
|
||||
|
||||
/// @brief Returns a reference to the type container
|
||||
NBTypeCont& getTypeCont() {
|
||||
return myTypeCont;
|
||||
}
|
||||
|
||||
/// @brief Returns a reference to the traffic light logics container
|
||||
NBTrafficLightLogicCont& getTLLogicCont() {
|
||||
return myTLLCont;
|
||||
}
|
||||
|
||||
/// @brief Returns a reference the districts container
|
||||
NBDistrictCont& getDistrictCont() {
|
||||
return myDistrictCont;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Returns a reference to the pt stop container
|
||||
NBPTStopCont& getPTStopCont() {
|
||||
return myPTStopCont;
|
||||
}
|
||||
|
||||
/// @brief Returns a reference to the pt line container
|
||||
NBPTLineCont& getPTLineCont() {
|
||||
return myPTLineCont;
|
||||
}
|
||||
/// @}
|
||||
|
||||
NBParkingCont& getParkingCont() {
|
||||
return myParkingCont;
|
||||
}
|
||||
|
||||
ShapeContainer& getShapeCont() {
|
||||
return myShapeCont;
|
||||
}
|
||||
|
||||
/// @brief notify about style of loaded network (Without Crossings)
|
||||
bool haveNetworkCrossings() {
|
||||
return myNetworkHaveCrossings;
|
||||
}
|
||||
|
||||
/// @brief enable crossing in networks
|
||||
void setHaveNetworkCrossings(bool value) {
|
||||
myNetworkHaveCrossings = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief transforms loaded coordinates
|
||||
* handles projections, offsets (using GeoConvHelper) and import of height data (using NBHeightMapper)
|
||||
* @param[in,out] from The coordinate to be transformed
|
||||
* @param[in] includeInBoundary Whether to patch the convex boundary of the GeoConvHelper default instance
|
||||
* @param[in] from_srs The spatial reference system of the input coordinate
|
||||
* @notde These methods are located outside of GeoConvHelper to avoid linker-dependencies on GDAL for libgeom
|
||||
*/
|
||||
static bool transformCoordinate(Position& from, bool includeInBoundary = true, GeoConvHelper* from_srs = 0);
|
||||
static bool transformCoordinates(PositionVector& from, bool includeInBoundary = true, GeoConvHelper* from_srs = 0);
|
||||
|
||||
/// @brief insertion geometry points to ensure maximum segment length between points
|
||||
static int addGeometrySegments(PositionVector& from, const PositionVector& cartesian, const double maxLength);
|
||||
|
||||
/// @brief whether netbuilding takes place in the context of NETEDIT
|
||||
static bool runningNetedit();
|
||||
|
||||
|
||||
protected:
|
||||
/**
|
||||
* @class by_id_sorter
|
||||
* @brief Sorts nodes by their ids
|
||||
*/
|
||||
class by_id_sorter {
|
||||
public:
|
||||
/// @brief constructor
|
||||
explicit by_id_sorter() {}
|
||||
|
||||
/// @brief selection operator
|
||||
int operator()(const NBNode* n1, const NBNode* n2) const {
|
||||
return n1->getID() < n2->getID();
|
||||
}
|
||||
};
|
||||
|
||||
protected:
|
||||
/// @brief The used container for nodes
|
||||
NBNodeCont myNodeCont;
|
||||
|
||||
/// @brief The used container for street types
|
||||
NBTypeCont myTypeCont;
|
||||
|
||||
/// @brief The used container for edges
|
||||
NBEdgeCont myEdgeCont;
|
||||
|
||||
/// @brief The used container for traffic light logics
|
||||
NBTrafficLightLogicCont myTLLCont;
|
||||
|
||||
/// @brief The used container for districts
|
||||
NBDistrictCont myDistrictCont;
|
||||
|
||||
/// @brief The used container for pt stops
|
||||
NBPTStopCont myPTStopCont;
|
||||
|
||||
/// @brief The used container for pt stops
|
||||
NBPTLineCont myPTLineCont;
|
||||
|
||||
NBParkingCont myParkingCont;
|
||||
|
||||
/// @brief container for loaded polygon data
|
||||
ShapeContainer myShapeCont;
|
||||
|
||||
/// @brief flag to indicate that network has crossings
|
||||
bool myNetworkHaveCrossings;
|
||||
|
||||
private:
|
||||
/// @brief shift network so its lower left corner is at 0,0
|
||||
void moveToOrigin(GeoConvHelper& geoConvHelper, bool lefthand);
|
||||
|
||||
/// @brief mirror the network along the X-axis
|
||||
void mirrorX();
|
||||
|
||||
private:
|
||||
/// @brief invalidated copy constructor
|
||||
NBNetBuilder(const NBNetBuilder& s);
|
||||
|
||||
/// @brief invalidated assignment operator
|
||||
NBNetBuilder& operator=(const NBNetBuilder& s);
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,914 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBNode.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Yun-Pang Floetteroed
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// The representation of a single node
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <utility>
|
||||
#include <string>
|
||||
#include <set>
|
||||
#include <memory>
|
||||
#include <utils/common/StdDefs.h>
|
||||
#include <utils/common/Named.h>
|
||||
#include <utils/geom/Bresenham.h>
|
||||
#include <utils/geom/GeomHelper.h>
|
||||
#include <utils/common/VectorHelper.h>
|
||||
#include <utils/geom/Position.h>
|
||||
#include <utils/geom/PositionVector.h>
|
||||
#include <utils/xml/SUMOXMLDefinitions.h>
|
||||
#include "NBEdge.h"
|
||||
#include "NBConnection.h"
|
||||
#include "NBConnectionDefs.h"
|
||||
#include "NBContHelper.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBRequest;
|
||||
class NBDistrict;
|
||||
class OptionsCont;
|
||||
class NBTrafficLightDefinition;
|
||||
class NBTypeCont;
|
||||
class NBTrafficLightLogicCont;
|
||||
class NBDistrictCont;
|
||||
class OutputDevice;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBNode
|
||||
* @brief Represents a single node (junction) during network building
|
||||
*/
|
||||
class NBNode : public Named, public Parameterised {
|
||||
friend class NBNodeCont;
|
||||
friend class GNEJunction; // < used for visualization (NETEDIT)
|
||||
friend class NBNodesEdgesSorter; // < sorts the edges
|
||||
friend class NBNodeTypeComputer; // < computes type
|
||||
friend class NBEdgePriorityComputer; // < computes priorities of edges per intersection
|
||||
|
||||
public:
|
||||
/**
|
||||
* @class ApproachingDivider
|
||||
* @brief Computes lane-2-lane connections
|
||||
*
|
||||
* Being a bresenham-callback, this class computes which lanes
|
||||
* are approached by the current lane (first callback parameter).
|
||||
* The second callback parameter is the destination lane that is the
|
||||
* middle of the computed lanes.
|
||||
* The lanes are spreaded from this middle position both to left and right
|
||||
* but may also be transposed in full when there is not enough space.
|
||||
*/
|
||||
class ApproachingDivider : public Bresenham::BresenhamCallBack {
|
||||
public:
|
||||
/**@brief Constructor
|
||||
* @param[in] approaching The list of the edges that approach the outgoing edge
|
||||
* @param[in] currentOutgoing The outgoing edge
|
||||
*/
|
||||
ApproachingDivider(const EdgeVector& approaching, NBEdge* currentOutgoing);
|
||||
|
||||
/// @brief Destructor
|
||||
~ApproachingDivider();
|
||||
|
||||
/// @ get number of avaliable lanes
|
||||
int numAvailableLanes() const {
|
||||
return (int)myAvailableLanes.size();
|
||||
}
|
||||
|
||||
/// @brief the bresenham-callback
|
||||
void execute(const int src, const int dest);
|
||||
|
||||
/// @brief the method that spreads the wished number of lanes from the the lane given by the bresenham-call to both left and right
|
||||
std::deque<int>* spread(const std::vector<int>& approachingLanes, int dest) const;
|
||||
|
||||
private:
|
||||
/// @brief The list of edges that approach the current edge
|
||||
const EdgeVector& myApproaching;
|
||||
|
||||
/// @brief The approached current edge
|
||||
NBEdge* myCurrentOutgoing;
|
||||
|
||||
/// @brief The available lanes to which connections shall be built
|
||||
std::vector<int> myAvailableLanes;
|
||||
|
||||
/// @brief whether the outgoing edge is exclusively used by bikes
|
||||
bool myIsBikeEdge;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated assignment operator.
|
||||
ApproachingDivider& operator=(const ApproachingDivider&) = delete;
|
||||
|
||||
};
|
||||
|
||||
/** @struct Crossing
|
||||
* @brief A definition of a pedestrian crossing
|
||||
*/
|
||||
struct Crossing : public Parameterised {
|
||||
/// @brief constructor
|
||||
Crossing(const NBNode* _node, const EdgeVector& _edges, double _width, bool _priority, int _customTLIndex, int _customTLIndex2, const PositionVector& _customShape);
|
||||
/// @brief The parent node of this crossing
|
||||
const NBNode* node;
|
||||
/// @brief The edges being crossed
|
||||
EdgeVector edges;
|
||||
/// @brief The crossing's shape
|
||||
PositionVector shape;
|
||||
/// @brief This crossing's width
|
||||
double customWidth;
|
||||
/// @brief This crossing's width
|
||||
double width;
|
||||
/// @brief the (edge)-id of this crossing
|
||||
std::string id;
|
||||
/// @brief the lane-id of the previous walkingArea
|
||||
std::string prevWalkingArea;
|
||||
/// @brief the lane-id of the next walkingArea
|
||||
std::string nextWalkingArea;
|
||||
/// @brief whether the pedestrians have priority
|
||||
bool priority;
|
||||
/// @brief optional customShape for this crossing
|
||||
PositionVector customShape;
|
||||
/// @brief the traffic light index of this crossing (if controlled)
|
||||
int tlLinkIndex;
|
||||
int tlLinkIndex2;
|
||||
/// @brief the custom traffic light index of this crossing (if controlled)
|
||||
int customTLIndex;
|
||||
int customTLIndex2;
|
||||
/// @brief The id of the traffic light that controls this connection
|
||||
std::string tlID;
|
||||
/// @brief whether this crossing is valid (and can be written to the net.xml). This is needed for netedit because validity can only be checked during junction computation
|
||||
bool valid;
|
||||
};
|
||||
|
||||
|
||||
/** @struct WalkingArea
|
||||
* @brief A definition of a pedestrian walking area
|
||||
*/
|
||||
struct WalkingArea {
|
||||
/// @brief constructor
|
||||
WalkingArea(const std::string& _id, double _width) :
|
||||
id(_id),
|
||||
width(_width) {
|
||||
}
|
||||
/// @brief the (edge)-id of this walkingArea
|
||||
std::string id;
|
||||
/// @brief This lane's width
|
||||
double width;
|
||||
/// @brief This lane's width
|
||||
double length = INVALID_DOUBLE;
|
||||
/// @brief The polygonal shape
|
||||
PositionVector shape;
|
||||
/// @brief the lane-id of the next crossing(s)
|
||||
std::vector<std::string> nextCrossings;
|
||||
/// @brief the lane-id of the next sidewalk lane or ""
|
||||
std::vector<std::string> nextSidewalks;
|
||||
/// @brief the lane-id of the previous sidewalk lane or ""
|
||||
std::vector<std::string> prevSidewalks;
|
||||
/// @brief whether this walkingArea has a custom shape
|
||||
bool hasCustomShape = false;
|
||||
/// @brief minimum number of edges crossed by nextCrossings
|
||||
int minNextCrossingEdges = std::numeric_limits<int>::max();
|
||||
/// @brief minimum number of edges crossed by incoming crossings
|
||||
int minPrevCrossingEdges = std::numeric_limits<int>::max();
|
||||
};
|
||||
|
||||
struct WalkingAreaCustomShape {
|
||||
std::set<const NBEdge*, ComparatorIdLess> edges;
|
||||
PositionVector shape;
|
||||
};
|
||||
|
||||
/// @brief edge directions (for pedestrian related stuff)
|
||||
static const int FORWARD;
|
||||
static const int BACKWARD;
|
||||
|
||||
/// @brief unspecified lane width
|
||||
static const double UNSPECIFIED_RADIUS;
|
||||
|
||||
/// @brief flags for controlling shape generation
|
||||
static const int AVOID_WIDE_RIGHT_TURN;
|
||||
static const int AVOID_WIDE_LEFT_TURN;
|
||||
static const int FOUR_CONTROL_POINTS;
|
||||
static const int AVOID_INTERSECTING_LEFT_TURNS;
|
||||
static const int SCURVE_IGNORE;
|
||||
|
||||
public:
|
||||
/**@brief Constructor
|
||||
* @param[in] id The id of the node
|
||||
* @param[in] position The position of the node
|
||||
* @param[in] type The type of the node
|
||||
*/
|
||||
NBNode(const std::string& id, const Position& position, SumoXMLNodeType type);
|
||||
|
||||
/**@brief Constructor
|
||||
* @param[in] id The id of the node
|
||||
* @param[in] position The position of the node
|
||||
* @param[in] district The district this district node represents, 0 means no district node
|
||||
*/
|
||||
NBNode(const std::string& id, const Position& position, NBDistrict* district = 0);
|
||||
|
||||
/// @brief Destructor
|
||||
~NBNode();
|
||||
|
||||
/**@brief Resets initial values
|
||||
* @param[in] position The position of the node
|
||||
* @param[in] type The type of the node
|
||||
* @param[in] updateEdgeGeometries Whether the geometires of all
|
||||
* connected edges shall be updated
|
||||
*/
|
||||
void reinit(const Position& position, SumoXMLNodeType type,
|
||||
bool updateEdgeGeometries = false);
|
||||
|
||||
/// @name Atomar getter methods
|
||||
/// @{
|
||||
/// @brief Returns the position of this node
|
||||
const Position& getPosition() const {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
/// @brief Returns a position that is guaranteed to lie within the node shape
|
||||
Position getCenter() const;
|
||||
|
||||
/// @brief Returns this node's incoming edges (The edges which yield in this node)
|
||||
const EdgeVector& getIncomingEdges() const {
|
||||
return myIncomingEdges;
|
||||
}
|
||||
|
||||
/// @brief Returns this node's outgoing edges (The edges which start at this node)
|
||||
const EdgeVector& getOutgoingEdges() const {
|
||||
return myOutgoingEdges;
|
||||
}
|
||||
|
||||
/// @brief Returns all edges which participate in this node (Edges that start or end at this node)
|
||||
const EdgeVector& getEdges() const {
|
||||
return myAllEdges;
|
||||
}
|
||||
|
||||
/**@brief Returns the type of this node
|
||||
* @see SumoXMLNodeType
|
||||
*/
|
||||
SumoXMLNodeType getType() const {
|
||||
return myType;
|
||||
}
|
||||
|
||||
/// @brief Returns the turning radius of this node
|
||||
double getRadius() const {
|
||||
return myRadius;
|
||||
}
|
||||
|
||||
/// @brief Returns the keepClear flag
|
||||
bool getKeepClear() const {
|
||||
return myKeepClear;
|
||||
}
|
||||
|
||||
/// @brief Returns hint on how to compute right of way
|
||||
RightOfWay getRightOfWay() const {
|
||||
return myRightOfWay;
|
||||
}
|
||||
|
||||
/// @brief Returns fringe type
|
||||
FringeType getFringeType() const {
|
||||
return myFringeType;
|
||||
}
|
||||
|
||||
/// @brief Returns intersection name
|
||||
const std::string& getName() const {
|
||||
return myName;
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// @name Methods for dealing with assigned traffic lights
|
||||
/// @{
|
||||
/**@brief Adds a traffic light to the list of traffic lights that control this node
|
||||
* @param[in] tld The traffic light that controls this node
|
||||
*/
|
||||
void addTrafficLight(NBTrafficLightDefinition* tlDef);
|
||||
|
||||
/// @brief Removes the given traffic light from this node
|
||||
void removeTrafficLight(NBTrafficLightDefinition* tlDef);
|
||||
|
||||
/// @brief Removes all references to traffic lights that control this tls
|
||||
void removeTrafficLights(bool setAsPriority = false);
|
||||
|
||||
/**@brief Returns whether this node is controlled by any tls
|
||||
* @return Whether a traffic light was assigned to this node
|
||||
*/
|
||||
bool isTLControlled() const {
|
||||
return myTrafficLights.size() != 0;
|
||||
}
|
||||
|
||||
/// @brief Returns the traffic lights that were assigned to this node (The set of tls that control this node)
|
||||
const std::set<NBTrafficLightDefinition*>& getControllingTLS() const {
|
||||
return myTrafficLights;
|
||||
}
|
||||
|
||||
/// @brief causes the traffic light to be computed anew
|
||||
void invalidateTLS(NBTrafficLightLogicCont& tlCont, bool removedConnections, bool addedConnections);
|
||||
|
||||
/// @brief patches loaded signal plans by modifying lane indices above threshold by the given offset
|
||||
void shiftTLConnectionLaneIndex(NBEdge* edge, int offset, int threshold = -1);
|
||||
/// @}
|
||||
|
||||
|
||||
/// @name Prunning the input
|
||||
/// @{
|
||||
|
||||
/**@brief Removes edges which are both incoming and outgoing into this node
|
||||
*
|
||||
* If given, the connections to other edges participating in this node are updated
|
||||
*
|
||||
* @param[in, opt. changed] dc The districts container to update
|
||||
* @param[in, opt. changed] ec The edge container to remove the edges from
|
||||
* @param[in, opt. changed] tc The traffic lights container to update
|
||||
* @return The number of removed edges
|
||||
*/
|
||||
int removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);
|
||||
/// @}
|
||||
|
||||
|
||||
/// @name Applying offset
|
||||
/// @{
|
||||
/**@brief Applies an offset to the node
|
||||
* @param[in] xoff The x-offset to apply
|
||||
* @param[in] yoff The y-offset to apply
|
||||
*/
|
||||
void reshiftPosition(double xoff, double yoff);
|
||||
|
||||
/// @brief mirror coordinates along the x-axis
|
||||
void mirrorX();
|
||||
/// @}
|
||||
|
||||
/// @brief adds an incoming edge
|
||||
void addIncomingEdge(NBEdge* edge);
|
||||
|
||||
/// @brief adds an outgoing edge
|
||||
void addOutgoingEdge(NBEdge* edge);
|
||||
|
||||
/// @brief computes the connections of lanes to edges
|
||||
void computeLanes2Lanes();
|
||||
|
||||
/// @brief computes the node's type, logic and traffic light
|
||||
void computeLogic(const NBEdgeCont& ec);
|
||||
|
||||
/// @brief compute right-of-way logic for all lane-to-lane connections
|
||||
void computeLogic2(bool checkLaneFoes);
|
||||
|
||||
/// @brief writes the XML-representation of the logic as a bitset-logic XML representation
|
||||
bool writeLogic(OutputDevice& into) const;
|
||||
|
||||
/// @brief get the 'foes' string (conflict bit set) of the right-of-way logic
|
||||
const std::string getFoes(int linkIndex) const;
|
||||
|
||||
/// @brief get the 'response' string (right-of-way bit set) of the right-of-way logic
|
||||
const std::string getResponse(int linkIndex) const;
|
||||
|
||||
/// @brief whether there are conflicting streams of traffic at this node
|
||||
bool hasConflict() const;
|
||||
|
||||
/// @brief Returns something like the most unused direction Should only be used to add source or sink nodes
|
||||
Position getEmptyDir() const;
|
||||
|
||||
/**@brief Returns whether the given edge ends at this node
|
||||
* @param[in] e The edge
|
||||
* @return Whether the given edge is one of this node's incoming edges
|
||||
*/
|
||||
bool hasIncoming(const NBEdge* const e) const;
|
||||
|
||||
/**@brief Returns whether the given edge starts at this node
|
||||
* @param[in] e The edge
|
||||
* @return Whether the given edge is one of this node's outgoing edges
|
||||
*/
|
||||
bool hasOutgoing(const NBEdge* const e) const;
|
||||
|
||||
/// @brief returns the opposite incoming edge of certain edge
|
||||
NBEdge* getOppositeIncoming(NBEdge* e) const;
|
||||
|
||||
/// @brief invalidate incoming connections
|
||||
void invalidateIncomingConnections();
|
||||
|
||||
/// @brief invalidate outgoing connections
|
||||
void invalidateOutgoingConnections();
|
||||
|
||||
/// @brief remove duble edges
|
||||
void removeDoubleEdges();
|
||||
|
||||
/// @brief get connection to certain node
|
||||
NBEdge* getConnectionTo(NBNode* n) const;
|
||||
|
||||
/// @brief add shorted link FOES
|
||||
void addSortedLinkFoes(const NBConnection& mayDrive, const NBConnection& mustStop);
|
||||
|
||||
/// @brief get possibly splitted incoming edge
|
||||
NBEdge* getPossiblySplittedIncoming(const std::string& edgeid);
|
||||
|
||||
/// @brief get possibly splitted outgoing edge
|
||||
NBEdge* getPossiblySplittedOutgoing(const std::string& edgeid);
|
||||
|
||||
/// @brief Removes edge from this node and optionally removes connections as well
|
||||
void removeEdge(NBEdge* edge, bool removeFromConnections = true);
|
||||
|
||||
/**@brief Computes whether the given connection is a left mover across the junction
|
||||
*
|
||||
* It is assumed, that it is a left-mover if the clockwise angle is lower
|
||||
* than the counter-clockwise angle.
|
||||
*
|
||||
* @param[in] from The incoming edge (the begin of the connection)
|
||||
* @param[in] from The outgoing edge (the end of the connection)
|
||||
* @return Whether the described connection is a left-mover
|
||||
*/
|
||||
bool isLeftMover(const NBEdge* const from, const NBEdge* const to) const;
|
||||
|
||||
/**@brief Returns the information whether the described flow must let any other flow pass
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] to The connection's end edge
|
||||
* @param[in] fromLane The lane the connection start at
|
||||
* @param[in] toLane The lane the connection ends at
|
||||
* @param[in] includePedCrossings Whether braking due to a pedestrian crossing counts
|
||||
* @return Whether the described connection must brake (has higher priorised foes)
|
||||
*/
|
||||
bool mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const;
|
||||
|
||||
/**@brief Returns the information whether the described flow must brake for the given crossing
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] to The connection's end edge
|
||||
* @param[in] crossing The pedestrian crossing to check
|
||||
* @return Whether the described connection must brake (has higher priorised foes)
|
||||
*/
|
||||
bool mustBrakeForCrossing(const NBEdge* const from, const NBEdge* const to, const Crossing& crossing) const;
|
||||
|
||||
/// @brief return whether the given laneToLane connection is a right turn which must yield to a bicycle crossings
|
||||
static bool rightTurnConflict(const NBEdge* from, const NBEdge* to, int fromLane,
|
||||
const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorFromLane);
|
||||
|
||||
/// @brief return whether the given laneToLane connection originate from the same edge and are in conflict due to turning across each other
|
||||
bool turnFoes(const NBEdge* from, const NBEdge* to, int fromLane,
|
||||
const NBEdge* from2, const NBEdge* to2, int fromLane2,
|
||||
bool lefthand = false) const;
|
||||
|
||||
/**@brief Returns the information whether "prohibited" flow must let "prohibitor" flow pass
|
||||
* @param[in] possProhibitedFrom The maybe prohibited connection's begin
|
||||
* @param[in] possProhibitedTo The maybe prohibited connection's end
|
||||
* @param[in] possProhibitorFrom The maybe prohibiting connection's begin
|
||||
* @param[in] possProhibitorTo The maybe prohibiting connection's end
|
||||
* @param[in] regardNonSignalisedLowerPriority Whether the right of way rules without traffic lights shall be regarded
|
||||
* @return Whether the second flow prohibits the first one
|
||||
*/
|
||||
bool forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
|
||||
const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
|
||||
bool regardNonSignalisedLowerPriority) const;
|
||||
|
||||
/**@brief Returns the information whether the given flows cross
|
||||
* @param[in] from1 The starting edge of the first stream
|
||||
* @param[in] to1 The ending edge of the first stream
|
||||
* @param[in] from2 The starting edge of the second stream
|
||||
* @param[in] to2 The ending edge of the second stream
|
||||
* @return Whether both stream are foes (cross)
|
||||
*/
|
||||
bool foes(const NBEdge* const from1, const NBEdge* const to1,
|
||||
const NBEdge* const from2, const NBEdge* const to2) const;
|
||||
|
||||
/**@brief Returns the representation of the described stream's direction
|
||||
* @param[in] incoming The edge the stream starts at
|
||||
* @param[in] outgoing The edge the stream ends at
|
||||
* @param[in] leftHand Whether a lefthand network is being built. Should only be set at writing time
|
||||
* @return The direction of the stream
|
||||
*/
|
||||
LinkDirection getDirection(const NBEdge* const incoming, const NBEdge* const outgoing, bool leftHand = false) const;
|
||||
|
||||
/// @brief get link state
|
||||
LinkState getLinkState(const NBEdge* incoming, NBEdge* outgoing,
|
||||
int fromLane, int toLane, bool mayDefinitelyPass, const std::string& tlID) const;
|
||||
|
||||
/**@brief Compute the junction shape for this node
|
||||
* @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition
|
||||
*/
|
||||
void computeNodeShape(double mismatchThreshold);
|
||||
|
||||
/// @brief update geometry of node and surrounding edges
|
||||
void updateSurroundingGeometry();
|
||||
|
||||
/// @brief retrieve the junction shape
|
||||
const PositionVector& getShape() const;
|
||||
|
||||
/// @brief set the junction shape
|
||||
void setCustomShape(const PositionVector& shape);
|
||||
|
||||
/// @brief set the turning radius
|
||||
void setRadius(double radius) {
|
||||
myRadius = radius;
|
||||
}
|
||||
|
||||
/// @brief set the keepClear flag
|
||||
void setKeepClear(bool keepClear) {
|
||||
myKeepClear = keepClear;
|
||||
}
|
||||
|
||||
/// @brief set method for computing right-of-way
|
||||
void setRightOfWay(RightOfWay rightOfWay) {
|
||||
myRightOfWay = rightOfWay;
|
||||
}
|
||||
|
||||
/// @brief set method for computing right-of-way
|
||||
void setFringeType(FringeType fringeType) {
|
||||
myFringeType = fringeType;
|
||||
}
|
||||
|
||||
/// @brief set intersection name
|
||||
void setName(const std::string& name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
/// @brief return whether the shape was set by the user
|
||||
bool hasCustomShape() const {
|
||||
return myHaveCustomPoly;
|
||||
}
|
||||
|
||||
/// @brief check if node is removable
|
||||
bool checkIsRemovable() const;
|
||||
|
||||
/// @brief check if node is removable and return reason if not
|
||||
bool checkIsRemovableReporting(std::string& reason) const;
|
||||
|
||||
/// @brief get edges to join
|
||||
std::vector<std::pair<NBEdge*, NBEdge*> > getEdgesToJoin() const;
|
||||
|
||||
/// @chech if node is near district
|
||||
bool isNearDistrict() const;
|
||||
|
||||
/// @brief check if node is a district
|
||||
bool isDistrict() const;
|
||||
|
||||
/// @brief whether an internal junction should be built at from and respect other
|
||||
bool needsCont(const NBEdge* fromE, const NBEdge* otherFromE,
|
||||
const NBEdge::Connection& c, const NBEdge::Connection& otherC) const;
|
||||
|
||||
/// @brief whether the connection must yield if the foe remains on the intersection after its phase ends
|
||||
bool tlsContConflict(const NBEdge* from, const NBEdge::Connection& c,
|
||||
const NBEdge* foeFrom, const NBEdge::Connection& foe) const;
|
||||
|
||||
|
||||
/**@brief Compute the shape for an internal lane
|
||||
* @param[in] fromE The starting edge
|
||||
* @param[in] con The connection for this internal lane
|
||||
* @param[in] numPoints The number of geometry points for the internal lane
|
||||
* @param[in] recordError The node itself if the displacement error during shape computation shall be recorded
|
||||
* @return The shape of the internal lane
|
||||
*/
|
||||
PositionVector computeInternalLaneShape(NBEdge* fromE, const NBEdge::Connection& con, int numPoints, NBNode* recordError = 0, int shapeFlag = 0) const;
|
||||
|
||||
/**@brief Compute a smooth curve between the given geometries
|
||||
* @param[in] begShape The geometry at the start
|
||||
* @param[in] endShape The geometry at the end
|
||||
* @param[in] numPoints The number of geometry points for the internal lane
|
||||
* @param[in] isTurnaround Whether this shall be the shape for a turnaround
|
||||
* @param[in] extrapolateBeg Extrapolation distance at the beginning
|
||||
* @param[in] extrapolateEnd Extrapolation distance at the end
|
||||
* @param[in] recordError The node itself if the displacement error during shape computation shall be recorded
|
||||
* @return The shape of the internal lane
|
||||
*/
|
||||
PositionVector computeSmoothShape(const PositionVector& begShape, const PositionVector& endShape, int numPoints,
|
||||
bool isTurnaround, double extrapolateBeg, double extrapolateEnd,
|
||||
NBNode* recordError = 0, int shapeFlag = 0) const;
|
||||
/// @brief get bezier control points
|
||||
static PositionVector bezierControlPoints(const PositionVector& begShape, const PositionVector& endShape,
|
||||
bool isTurnaround, double extrapolateBeg, double extrapolateEnd,
|
||||
bool& ok, NBNode* recordError = 0, double straightThresh = DEG2RAD(5),
|
||||
int shapeFlag = 0);
|
||||
|
||||
|
||||
/// @brief compute the displacement error during s-curve computation
|
||||
double getDisplacementError() const {
|
||||
return myDisplacementError;
|
||||
}
|
||||
|
||||
/// @brief Replaces occurences of the first edge within the list of incoming by the second Connections are remapped, too
|
||||
void replaceIncoming(NBEdge* which, NBEdge* by, int laneOff);
|
||||
|
||||
/// @brief Replaces occurences of every edge from the given list within the list of incoming by the second Connections are remapped, too
|
||||
void replaceIncoming(const EdgeVector& which, NBEdge* by);
|
||||
|
||||
/// @brief Replaces occurences of the first edge within the list of outgoing by the second Connections are remapped, too
|
||||
void replaceOutgoing(NBEdge* which, NBEdge* by, int laneOff);
|
||||
|
||||
/// @brief Replaces occurences of every edge from the given list within the list of outgoing by the second Connections are remapped, too
|
||||
void replaceOutgoing(const EdgeVector& which, NBEdge* by);
|
||||
|
||||
/// @brief guess pedestrian crossings and return how many were guessed
|
||||
int guessCrossings();
|
||||
|
||||
/* @brief check whether a crossing should be build for the candiate edges and build 0 to n crossings
|
||||
* @param[in] candidates The candidate vector of edges to be crossed
|
||||
* @return The number of crossings built
|
||||
* */
|
||||
int checkCrossing(EdgeVector candidates);
|
||||
|
||||
/// @brief return true if there already exist a crossing with the same edges as the input
|
||||
bool checkCrossingDuplicated(EdgeVector edges);
|
||||
|
||||
/// @brief build internal lanes, pedestrian crossings and walking areas
|
||||
void buildInnerEdges();
|
||||
|
||||
/**@brief build pedestrian crossings
|
||||
* @return The next index for creating internal lanes
|
||||
**/
|
||||
int buildCrossings();
|
||||
|
||||
/**@brief build pedestrian walking areas and set connections from/to walkingAreas
|
||||
* @param[in] cornerDetail The detail level when generating the inner curve
|
||||
*/
|
||||
void buildWalkingAreas(int cornerDetail);
|
||||
|
||||
/// @brief build crossings, and walkingareas. Also removes invalid loaded crossings if wished
|
||||
void buildCrossingsAndWalkingAreas();
|
||||
|
||||
/// @brief return all edges that lie clockwise between the given edges
|
||||
EdgeVector edgesBetween(const NBEdge* e1, const NBEdge* e2) const;
|
||||
|
||||
/// @brief return true if the given edges are connected by a crossing
|
||||
bool crossingBetween(const NBEdge* e1, const NBEdge* e2) const;
|
||||
|
||||
/// @brief get prohibitions (BLocked connections)
|
||||
const NBConnectionProhibits& getProhibitions() {
|
||||
return myBlockedConnections;
|
||||
}
|
||||
|
||||
/// @brief whether this is structurally similar to a geometry node
|
||||
bool geometryLike() const;
|
||||
bool geometryLike(const EdgeVector& incoming, const EdgeVector& outgoing) const;
|
||||
|
||||
/// @brief update the type of this node as a roundabout
|
||||
void setRoundabout();
|
||||
|
||||
/// @brief return whether this node is part of a roundabout
|
||||
bool isRoundabout() const;
|
||||
|
||||
/// @brief add a pedestrian crossing to this node
|
||||
NBNode::Crossing* addCrossing(EdgeVector edges, double width, bool priority, int tlIndex = -1, int tlIndex2 = -1,
|
||||
const PositionVector& customShape = PositionVector::EMPTY, bool fromSumoNet = false);
|
||||
|
||||
/// @brief add custom shape for walkingArea
|
||||
void addWalkingAreaShape(EdgeVector edges, const PositionVector& shape);
|
||||
|
||||
/// @brief remove a pedestrian crossing from this node (identified by its edges)
|
||||
void removeCrossing(const EdgeVector& edges);
|
||||
|
||||
/// @brief discard all current (and optionally future) crossings
|
||||
void discardAllCrossings(bool rejectAll);
|
||||
|
||||
/// @brief discard previously built walkingareas (required for repeated computation by netedit)
|
||||
void discardWalkingareas();
|
||||
|
||||
/// @brief get num of crossings from sumo net
|
||||
int numCrossingsFromSumoNet() const {
|
||||
return myCrossingsLoadedFromSumoNet;
|
||||
}
|
||||
|
||||
/// @brief return this junctions pedestrian crossings
|
||||
std::vector<Crossing*> getCrossings() const;
|
||||
inline const std::vector<std::unique_ptr<Crossing> >& getCrossingsIncludingInvalid() const {
|
||||
return myCrossings;
|
||||
}
|
||||
|
||||
/// @brief return this junctions pedestrian walking areas
|
||||
inline const std::vector<WalkingArea>& getWalkingAreas() const {
|
||||
return myWalkingAreas;
|
||||
}
|
||||
|
||||
const std::vector<WalkingAreaCustomShape>& getWalkingAreaCustomShapes() const {
|
||||
return myWalkingAreaCustomShapes;
|
||||
}
|
||||
|
||||
/// @brief return the crossing with the given id
|
||||
Crossing* getCrossing(const std::string& id) const;
|
||||
|
||||
/// @brief return the crossing with the given Edges
|
||||
Crossing* getCrossing(const EdgeVector& edges, bool hardFail = true) const;
|
||||
|
||||
/* @brief set tl indices of this nodes crossing starting at the given index
|
||||
* @return Whether a custom index was used
|
||||
*/
|
||||
bool setCrossingTLIndices(const std::string& tlID, int startIndex);
|
||||
|
||||
/// @brief return the number of lane-to-lane connections at this junction (excluding crossings)
|
||||
int numNormalConnections() const;
|
||||
|
||||
/// @brief fix overlap
|
||||
void avoidOverlap();
|
||||
|
||||
/// @brief whether the given index must yield to the foeIndex while turing right on a red light
|
||||
bool rightOnRedConflict(int index, int foeIndex) const;
|
||||
|
||||
/// @brief sort all edge containers for this node
|
||||
void sortEdges(bool useNodeShape);
|
||||
|
||||
/// @brief return the index of the given connection
|
||||
int getConnectionIndex(const NBEdge* from, const NBEdge::Connection& con) const;
|
||||
|
||||
/**
|
||||
* @class nodes_by_id_sorter
|
||||
* @brief Used for sorting the cells by the begin time they describe
|
||||
*/
|
||||
class nodes_by_id_sorter {
|
||||
public:
|
||||
/// @brief Constructor
|
||||
explicit nodes_by_id_sorter() { }
|
||||
|
||||
/// @brief Comparing operator
|
||||
int operator()(NBNode* n1, NBNode* n2) const {
|
||||
return n1->getID() < n2->getID();
|
||||
}
|
||||
};
|
||||
|
||||
/** @class edge_by_direction_sorter
|
||||
* @brief Sorts outgoing before incoming edges
|
||||
*/
|
||||
class edge_by_direction_sorter {
|
||||
public:
|
||||
/// @brief constructor
|
||||
explicit edge_by_direction_sorter(NBNode* n) : myNode(n) {}
|
||||
|
||||
/// @brief operator of selection
|
||||
int operator()(NBEdge* e1, NBEdge* e2) const {
|
||||
UNUSED_PARAMETER(e2);
|
||||
return e1->getFromNode() == myNode;
|
||||
}
|
||||
|
||||
private:
|
||||
/// @brief The node to compute the relative angle of
|
||||
NBNode* myNode;
|
||||
|
||||
};
|
||||
|
||||
/// @brief returns the node id for internal lanes, crossings and walkingareas
|
||||
static std::string getNodeIDFromInternalLane(const std::string id);
|
||||
|
||||
|
||||
/// @brief return whether the given type is a traffic light
|
||||
static bool isTrafficLight(SumoXMLNodeType type);
|
||||
|
||||
/// @brief check if node is a simple continuation
|
||||
bool isSimpleContinuation(bool checkLaneNumbers = true, bool checkWidth = false) const;
|
||||
|
||||
/// @brief mark whether a priority road turns at this node
|
||||
void markBentPriority(bool isBent) {
|
||||
myIsBentPriority = isBent;
|
||||
}
|
||||
|
||||
/// @brief return whether a priority road turns at this node
|
||||
bool isBentPriority() const {
|
||||
return myIsBentPriority;
|
||||
}
|
||||
|
||||
/// @brief return whether a priority road turns at this node
|
||||
bool typeWasGuessed() const {
|
||||
return myTypeWasGuessed;
|
||||
}
|
||||
|
||||
/// @brief detects whether a given junction splits or merges lanes while keeping constant road width
|
||||
bool isConstantWidthTransition() const;
|
||||
|
||||
/// @brief return list of unique endpoint coordinates of all edges at this node
|
||||
std::vector<std::pair<Position, std::string> > getEndPoints() const;
|
||||
|
||||
private:
|
||||
/// @brief sets the priorites in case of a priority junction
|
||||
void setPriorityJunctionPriorities();
|
||||
|
||||
/// @brief returns a list of edges which are connected to the given outgoing edge
|
||||
void getEdgesThatApproach(NBEdge* currentOutgoing, EdgeVector& approaching);
|
||||
|
||||
/// @brief replace incoming connections prohibitions
|
||||
void replaceInConnectionProhibitions(NBEdge* which, NBEdge* by, int whichLaneOff, int byLaneOff);
|
||||
|
||||
/// @brief remap removed
|
||||
void remapRemoved(NBTrafficLightLogicCont& tc, NBEdge* removed, const EdgeVector& incoming, const EdgeVector& outgoing);
|
||||
|
||||
/// @brief return whether there is a non-sidewalk lane after the given index;
|
||||
bool forbidsPedestriansAfter(std::vector<std::pair<NBEdge*, bool> > normalizedLanes, int startIndex);
|
||||
|
||||
/// @brief returns the list of all edges sorted clockwise by getAngleAtNodeToCenter
|
||||
EdgeVector getEdgesSortedByAngleAtNodeCenter() const;
|
||||
|
||||
/// @brief check if is long enough
|
||||
static bool isLongEnough(NBEdge* out, double minLength);
|
||||
|
||||
/// @brief remove all traffic light definitions that are part of a joined tls
|
||||
void removeJoinedTrafficLights();
|
||||
|
||||
/// @brief displace lane shapes to account for change in lane width at this node
|
||||
void displaceShapeAtWidthChange(const NBEdge* from, const NBEdge::Connection& con, PositionVector& fromShape, PositionVector& toShape) const;
|
||||
|
||||
/// @brief returns whether sub is a subset of super
|
||||
static bool includes(const std::set<NBEdge*, ComparatorIdLess>& super,
|
||||
const std::set<const NBEdge*, ComparatorIdLess>& sub);
|
||||
|
||||
NBEdge* getNextCompatibleOutgoing(const NBEdge* incoming, SVCPermissions vehPerm, EdgeVector::const_iterator start, bool clockwise) const;
|
||||
|
||||
/// @brief get the reduction in driving lanes at this junction
|
||||
void getReduction(const NBEdge* in, const NBEdge* out, int& inOffset, int& outOffset, int& reduction) const;
|
||||
|
||||
/// @brief check whether this edge has extra lanes on the right side
|
||||
int addedLanesRight(NBEdge* out, int addedLanes) const;
|
||||
|
||||
private:
|
||||
/// @brief The position the node lies at
|
||||
Position myPosition;
|
||||
|
||||
/// @brief Vector of incoming edges
|
||||
EdgeVector myIncomingEdges;
|
||||
|
||||
/// @brief Vector of outgoing edges
|
||||
EdgeVector myOutgoingEdges;
|
||||
|
||||
/// @brief Vector of incoming and outgoing edges
|
||||
EdgeVector myAllEdges;
|
||||
|
||||
/// @brief Vector of crossings
|
||||
std::vector<std::unique_ptr<Crossing> > myCrossings;
|
||||
|
||||
/// @brief Vector of walking areas
|
||||
std::vector<WalkingArea> myWalkingAreas;
|
||||
|
||||
/// @brief Vector of custom walking areas shapes
|
||||
std::vector<WalkingAreaCustomShape> myWalkingAreaCustomShapes;
|
||||
|
||||
/// @brief The type of the junction
|
||||
SumoXMLNodeType myType;
|
||||
|
||||
/// @brief The container for connection block dependencies
|
||||
NBConnectionProhibits myBlockedConnections;
|
||||
|
||||
/// @brief The district the node is the centre of
|
||||
NBDistrict* myDistrict;
|
||||
|
||||
/// @brief the (outer) shape of the junction
|
||||
PositionVector myPoly;
|
||||
|
||||
/// @brief whether this nodes shape was set by the user
|
||||
bool myHaveCustomPoly;
|
||||
|
||||
/// @brief Node requests
|
||||
NBRequest* myRequest;
|
||||
|
||||
/// @brief traffic lights of node
|
||||
std::set<NBTrafficLightDefinition*> myTrafficLights;
|
||||
|
||||
/// @brief the turning radius (for all corners) at this node in m.
|
||||
double myRadius;
|
||||
|
||||
/// @brief whether the junction area must be kept clear
|
||||
bool myKeepClear;
|
||||
|
||||
/// @brief how to compute right of way for this node
|
||||
RightOfWay myRightOfWay;
|
||||
|
||||
/// @brief fringe type of this node
|
||||
FringeType myFringeType;
|
||||
|
||||
/// @brief The intersection name (or whatever arbitrary string you wish to attach)
|
||||
std::string myName;
|
||||
|
||||
/// @brief whether to discard all pedestrian crossings
|
||||
bool myDiscardAllCrossings;
|
||||
|
||||
/// @brief number of crossings loaded from a sumo net
|
||||
int myCrossingsLoadedFromSumoNet;
|
||||
|
||||
/// @brief geometry error after computation of internal lane shapes
|
||||
double myDisplacementError;
|
||||
|
||||
/* @brief whether this junction is a bent priority junction (main direction turns)
|
||||
* @note see NBEdgePriorityComputer
|
||||
*/
|
||||
bool myIsBentPriority;
|
||||
|
||||
/// @brief whether the node type was guessed rather than loaded
|
||||
bool myTypeWasGuessed;
|
||||
|
||||
private:
|
||||
/// @brief invalidated copy constructor
|
||||
NBNode(const NBNode& s);
|
||||
|
||||
/// @brief invalidated assignment operator
|
||||
NBNode& operator=(const NBNode& s);
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,421 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBNodeCont.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Yun-Pang Floetteroed
|
||||
/// @author Michael Behrisch
|
||||
/// @author Walter Bamberger
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// Container for nodes during the netbuilding process
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utils/common/NamedRTree.h>
|
||||
#include <utils/geom/Position.h>
|
||||
#include "NBCont.h"
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBNode.h"
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBDistrict;
|
||||
class OptionsCont;
|
||||
class OutputDevice;
|
||||
class NBParkingCont;
|
||||
class NBPTLineCont;
|
||||
class NBPTStopCont;
|
||||
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBNodeCont
|
||||
* @brief Container for nodes during the netbuilding process
|
||||
*/
|
||||
class NBNodeCont {
|
||||
public:
|
||||
/// @brief Definition of a node cluster container
|
||||
typedef std::vector<NodeSet> NodeClusters;
|
||||
typedef std::pair<NBNode*, double> NodeAndDist;
|
||||
|
||||
/// @brief Constructor
|
||||
NBNodeCont();
|
||||
|
||||
/// @brief Destructor
|
||||
~NBNodeCont();
|
||||
|
||||
/// @name Insertion/removal/retrieval of nodes
|
||||
/// @{
|
||||
/** @brief Inserts a node into the map
|
||||
* @param[in] id The node's id
|
||||
* @param[in] position The node's position
|
||||
* @param[in] A district assigned to the node
|
||||
* @return Whether the node could be added (no other with the same id or position is stored)
|
||||
*/
|
||||
bool insert(const std::string& id, const Position& position, NBDistrict* district = 0);
|
||||
|
||||
/** @brief Inserts a node into the map
|
||||
* @param[in] node The node to insert
|
||||
* @return Whether the node could be added (no other with the same id or position is stored)
|
||||
*/
|
||||
bool insert(NBNode* node);
|
||||
|
||||
/** @brief Removes the given node, deleting it
|
||||
* @param[in] node The node to delete and remove
|
||||
* @return Whether the node could be removed (existed)
|
||||
*/
|
||||
bool erase(NBNode* node);
|
||||
|
||||
/** @brief Removes the given node but does not delete it
|
||||
* @param[in] node The node to delete and remove
|
||||
* @param[in] remember Whether to keep the node for future reference
|
||||
* @return Whether the node could be removed (existed)
|
||||
*/
|
||||
bool extract(NBNode* node, bool remember = false);
|
||||
|
||||
/** @brief Returns the node with the given name
|
||||
* @param[in] id The id of the node to retrieve
|
||||
* @return The node with the given id, or 0 if no such node exists
|
||||
*/
|
||||
NBNode* retrieve(const std::string& id) const;
|
||||
|
||||
/** @brief Returns the node with the given coordinates
|
||||
* @param[in] position The position at which the node to retrieve lies
|
||||
* @param[in] offset An offset which can be applied in the case positions are blurred
|
||||
* @return The node at the given position, or 0 if no such node exists
|
||||
*/
|
||||
NBNode* retrieve(const Position& position, const double offset = 0.) const;
|
||||
|
||||
/// @brief Returns the pointer to the begin of the stored nodes
|
||||
std::map<std::string, NBNode*>::const_iterator begin() const {
|
||||
return myNodes.begin();
|
||||
}
|
||||
|
||||
/// @brief Returns the pointer to the end of the stored nodes
|
||||
std::map<std::string, NBNode*>::const_iterator end() const {
|
||||
return myNodes.end();
|
||||
}
|
||||
/// @}
|
||||
|
||||
/// @name Methods for for joining nodes
|
||||
/// @{
|
||||
/* @brief add ids of nodes wich shall not be joined
|
||||
* @param[in] ids A list of ids to exclude from joining
|
||||
* @param[in] check Whether to check if these nodes are known
|
||||
* @note checking is off by default because all nodes may not have been loaded yet
|
||||
*/
|
||||
void addJoinExclusion(const std::vector<std::string>& ids, bool check = false);
|
||||
|
||||
/** @brief add ids of nodes which shall be joined into a single node
|
||||
* @param[in] cluster The cluster to add
|
||||
*/
|
||||
void addCluster2Join(std::set<std::string> cluster, NBNode* node);
|
||||
|
||||
/// @brief Joins loaded junction clusters (see NIXMLNodesHandler)
|
||||
int joinLoadedClusters(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/// @brief Joins junctions that are very close together
|
||||
int joinJunctions(double maxDist, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, NBPTStopCont& sc);
|
||||
|
||||
/// @brief remove geometry-like fringe nodes from cluster
|
||||
void pruneClusterFringe(NodeSet& cluster) const;
|
||||
|
||||
/// @brief avoid removal of long edges when joinining junction clusters
|
||||
static void pruneLongEdges(NodeSet& cluster, double maxDist);
|
||||
|
||||
/// @brief remove nodes that form a slip lane from cluster
|
||||
void pruneSlipLaneNodes(NodeSet& cluster) const;
|
||||
|
||||
/// @brief return all cluster neighbors for the given node
|
||||
static NodeSet getClusterNeighbors(const NBNode* n, NodeSet& cluster);
|
||||
|
||||
/// @brief check whether the given node maybe the start of a slip lane
|
||||
bool maybeSlipLaneStart(const NBNode* n, EdgeVector& outgoing, double& inAngle) const;
|
||||
/// @brief check whether the given node maybe the end of a slip lane
|
||||
bool maybeSlipLaneEnd(const NBNode* n, EdgeVector& incoming, double& outAngle) const;
|
||||
|
||||
/// @brief determine wether the cluster is not too complex for joining
|
||||
bool feasibleCluster(const NodeSet& cluster, const NBEdgeCont& ec, const NBPTStopCont& sc, std::string& reason) const;
|
||||
|
||||
/// @brief try to find a joinable subset (recursively)
|
||||
bool reduceToCircle(NodeSet& cluster, int circleSize, NodeSet startNodes, std::vector<NBNode*> cands = std::vector<NBNode*>()) const;
|
||||
|
||||
/// @brief find closest neighbor for building circle
|
||||
NBEdge* shortestEdge(const NodeSet& cluster, const NodeSet& startNodes, const std::vector<NBNode*>& exclude) const;
|
||||
/// @}
|
||||
|
||||
/// @name Adapting the input
|
||||
/// @{
|
||||
/** @brief Removes self-loop edges (edges where the source and the destination node are the same)
|
||||
* @param[in, opt. changed] dc The districts container to update
|
||||
* @param[in, opt. changed] ec The edge container to remove the edges from
|
||||
* @param[in, opt. changed] tc The traffic lights container to update
|
||||
* @post Each edge is a uni-directional connection between two different nodes
|
||||
*/
|
||||
void removeSelfLoops(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tc);
|
||||
|
||||
/** @brief Joins edges connecting the same nodes
|
||||
* @param[in, opt. changed] dc The districts container to update
|
||||
* @param[in, opt. changed] ec The edge container to remove the edges from
|
||||
* @param[in, opt. changed] tc The traffic lights container to update
|
||||
* @post No two edges with same geometry connecting same nodes exist
|
||||
*/
|
||||
void joinSimilarEdges(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/// @brief fix overlap
|
||||
void avoidOverlap();
|
||||
|
||||
/** @brief Removes sequences of edges that are not connected with a junction.
|
||||
* Simple roads without junctions sometimes remain when converting from OpenStreetMap,
|
||||
* but they make no sense. Remaining empty nodes are also deleted.
|
||||
*
|
||||
* @param[in, opt. changed] dc The district container needed if edges shall be removed
|
||||
* @param[in, opt. changed] ec The container with the edge to be tested
|
||||
*/
|
||||
void removeIsolatedRoads(NBDistrictCont& dc, NBEdgeCont& ec);
|
||||
|
||||
/** @brief Checks the network for weak connectivity and removes all but the largest components.
|
||||
* The connectivity check is done regardless of edge direction and vclass.
|
||||
*
|
||||
* @param[in, opt. changed] dc The district container needed if edges shall be removed
|
||||
* @param[in, opt. changed] ec The container with the edge to be tested
|
||||
* @param[in] numKeep The number of components to keep
|
||||
*/
|
||||
void removeComponents(NBDistrictCont& dc, NBEdgeCont& ec, const int numKeep);
|
||||
|
||||
/** @brief Removes "unwished" nodes
|
||||
*
|
||||
* Removes nodes if a) no incoming/outgoing edges exist or
|
||||
* b) if the node is a "geometry" node. In the second case,
|
||||
* edges that participate at the node will be joined.
|
||||
* Whether the node is a geometry node or not, is determined
|
||||
* by a call to NBNode::checkIsRemovable.
|
||||
* The node is removed from the list of tls-controlled nodes.
|
||||
* @param[in, opt. changed] dc The district container needed if a node shall be removed
|
||||
* @param[in, opt. changed] ec The edge container needed for joining edges
|
||||
* @param[in, opt. changed] tlc The traffic lights container to remove nodes from
|
||||
* @param[in] removeGeometryNodes Whether geometry nodes shall also be removed
|
||||
* @return The number of removed nodes
|
||||
*/
|
||||
int removeUnwishedNodes(NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc,
|
||||
NBPTStopCont& sc, NBPTLineCont& lc,
|
||||
NBParkingCont& pc,
|
||||
bool removeGeometryNodes);
|
||||
/// @}
|
||||
|
||||
/// @name Methods for guessing/computing traffic lights
|
||||
/// @{
|
||||
/** @brief Guesses which junctions or junction clusters shall be controlled by tls
|
||||
* @param[in] oc The options that steer the guessing process
|
||||
* @param[filled] tlc The traffic lights control into which new traffic light definitions shall be stored
|
||||
* @todo Recheck exception handling
|
||||
*/
|
||||
void guessTLs(OptionsCont& oc, NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/// @brief recheck myGuessedTLS after node logics are computed
|
||||
void recheckGuessedTLS(NBTrafficLightLogicCont& tlc);
|
||||
|
||||
/** @brief Builds clusters of tls-controlled junctions and joins the control if possible
|
||||
* @param[changed] tlc The traffic lights control for adding/removing new/prior tls
|
||||
* @param[in] maxdist The maximum distance between nodes for clustering
|
||||
* @todo Recheck exception handling
|
||||
*/
|
||||
void joinTLS(NBTrafficLightLogicCont& tlc, double maxdist);
|
||||
|
||||
/** @brief Sets the given node as being controlled by a tls
|
||||
* @param[in] node The node that shall be controlled by a tls
|
||||
* @param[in] tlc The traffic lights control into which the new traffic light definition shall be stored
|
||||
* @param[in] type The type of the new tls
|
||||
* @param[in] id The id of the tls to add
|
||||
* @todo Recheck exception handling
|
||||
*/
|
||||
void setAsTLControlled(NBNode* node, NBTrafficLightLogicCont& tlc, TrafficLightType type, std::string id = "");
|
||||
/// @}
|
||||
|
||||
/** @brief Returns whether the node with the id was deleted explicitly
|
||||
*/
|
||||
bool wasRemoved(std::string id) const {
|
||||
return myExtractedNodes.count(id) != 0;
|
||||
}
|
||||
|
||||
|
||||
/// @brief Renames the node. Throws exception if newID already exists
|
||||
void rename(NBNode* node, const std::string& newID);
|
||||
|
||||
/// divides the incoming lanes on outgoing lanes
|
||||
void computeLanes2Lanes();
|
||||
|
||||
/// @brief build the list of outgoing edges and lanes
|
||||
void computeLogics(const NBEdgeCont& ec);
|
||||
|
||||
/// @brief compute right-of-way logic for all lane-to-lane connections
|
||||
void computeLogics2(const NBEdgeCont& ec, OptionsCont& oc);
|
||||
|
||||
/// @brief Returns the number of nodes stored in this container
|
||||
int size() const {
|
||||
return (int) myNodes.size();
|
||||
}
|
||||
|
||||
/// @brief deletes all nodes
|
||||
void clear();
|
||||
|
||||
/// @brief generates a new node ID
|
||||
std::string getFreeID();
|
||||
|
||||
/** @brief Compute the junction shape for this node
|
||||
* @param[in] mismatchThreshold The threshold for warning about shapes which are away from myPosition
|
||||
*/
|
||||
void computeNodeShapes(double mismatchThreshold = -1);
|
||||
|
||||
/** @brief Prints statistics about built nodes
|
||||
*
|
||||
* Goes through stored nodes, computes the numbers of unregulated, priority and right-before-left
|
||||
* junctions and prints them.
|
||||
*/
|
||||
void printBuiltNodesStatistics() const;
|
||||
|
||||
/// @brief get all node names
|
||||
std::vector<std::string> getAllNames() const;
|
||||
|
||||
/* @brief analyzes a cluster of nodes which shall be joined
|
||||
* @param[in] cluster The nodes to be joined
|
||||
* @param[out] id The name for the new node
|
||||
* @param[out] pos The position of the new node
|
||||
* @param[out] hasTLS Whether the new node has a traffic light
|
||||
* @param[out] tlType The type of traffic light (if any)
|
||||
*/
|
||||
void analyzeCluster(NodeSet cluster, std::string& id, Position& pos,
|
||||
bool& hasTLS, TrafficLightType& type, SumoXMLNodeType& nodeType);
|
||||
|
||||
/// @brief gets all joined clusters (see doc for myClusters2Join)
|
||||
void registerJoinedCluster(const NodeSet& cluster);
|
||||
|
||||
/// @brief gets all joined clusters (see doc for myClusters2Join)
|
||||
const std::vector<std::set<std::string> >& getJoinedClusters() const {
|
||||
return myJoinedClusters;
|
||||
}
|
||||
|
||||
/* @brief discards traffic lights
|
||||
* @param[in] geometryLike Whether only tls at geometry-like nodes shall be discarded
|
||||
*/
|
||||
void discardTrafficLights(NBTrafficLightLogicCont& tlc, bool geometryLike, bool guessSignals);
|
||||
|
||||
/* @brief discards rail signals
|
||||
*/
|
||||
void discardRailSignals();
|
||||
|
||||
/// @brief mark a node as being created form a split
|
||||
void markAsSplit(const NBNode* node) {
|
||||
mySplit.insert(node);
|
||||
}
|
||||
|
||||
/// @brief remap node IDs accoring to options --numerical-ids and --reserved-ids
|
||||
int remapIDs(bool numericaIDs, bool reservedIDs, const std::string& prefix);
|
||||
|
||||
/// @brief guess and mark fringe nodes
|
||||
int guessFringe();
|
||||
|
||||
private:
|
||||
|
||||
/// @name Helper methods for for joining nodes
|
||||
/// @{
|
||||
/** @brief Builds node clusters
|
||||
*
|
||||
* A node cluster is made up from nodes which are near by (distance<maxDist) and connected.
|
||||
*
|
||||
* @param[in] maxDist The maximum distance between two nodes for clustering
|
||||
* @param[in, filled] into The container to store the clusters in
|
||||
*/
|
||||
void generateNodeClusters(double maxDist, NodeClusters& into) const;
|
||||
|
||||
/// @brief joins the given node clusters
|
||||
void joinNodeClusters(NodeClusters clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc);
|
||||
void joinNodeCluster(NodeSet clusters, NBDistrictCont& dc, NBEdgeCont& ec, NBTrafficLightLogicCont& tlc, NBNode* predefined = nullptr);
|
||||
|
||||
/// @}
|
||||
|
||||
/// @name Helper methods for guessing/computing traffic lights
|
||||
/// @{
|
||||
/** @brief Returns whethe the given node cluster should be controlled by a tls
|
||||
* @param[in] c The node cluster
|
||||
* @param[in] laneSpeedThreshold threshold for determining whether a node or cluster should be tls controlled
|
||||
* @return Whether this node cluster shall be controlled by a tls
|
||||
*/
|
||||
bool shouldBeTLSControlled(const NodeSet& c, double laneSpeedThreshold) const;
|
||||
|
||||
/// @brief check wheter the set of nodes only contains pedestrian crossings
|
||||
bool onlyCrossings(const NodeSet& c) const;
|
||||
|
||||
/// @brief check wheter the set of nodes contains traffic lights with custom id
|
||||
bool customTLID(const NodeSet& c) const;
|
||||
/// @}
|
||||
|
||||
/// @brief update pareto frontier with the given node
|
||||
void paretoCheck(NBNode* node, NodeSet& frontier, int xSign, int ySign);
|
||||
|
||||
private:
|
||||
/// @brief The running internal id
|
||||
int myInternalID;
|
||||
|
||||
/// @brief Definition of the map of names to nodes
|
||||
typedef std::map<std::string, NBNode*> NodeCont;
|
||||
|
||||
/// @brief The map of names to nodes
|
||||
NodeCont myNodes;
|
||||
|
||||
/// @brief The extracted nodes which are kept for reference
|
||||
NodeCont myExtractedNodes;
|
||||
|
||||
/// @brief set of node ids which should not be joined
|
||||
std::set<std::string> myJoinExclusions;
|
||||
|
||||
/// @brief loaded sets of node ids to join (cleared after use)
|
||||
std::vector<std::pair<std::set<std::string>, NBNode*> > myClusters2Join;
|
||||
|
||||
/// @brief sets of node ids which were joined
|
||||
std::vector<std::set<std::string> > myJoinedClusters;
|
||||
|
||||
/// @brief ids found in loaded join clusters used for error checking
|
||||
std::set<std::string> myJoined;
|
||||
|
||||
/// @brief nodes that were created when splitting an edge
|
||||
std::set<const NBNode*> mySplit;
|
||||
|
||||
/// @brief nodes that received a traffic light due to guessing (--tls.guess)
|
||||
std::set<NBNode*> myGuessedTLS;
|
||||
|
||||
/// @brief node positions for faster lookup
|
||||
NamedRTree myRTree;
|
||||
|
||||
|
||||
private:
|
||||
/// @brief invalidated copy constructor
|
||||
NBNodeCont(const NBNodeCont& s);
|
||||
|
||||
/// @brief invalidated assignment operator
|
||||
NBNodeCont& operator=(const NBNodeCont& s);
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,167 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBNodeShapeComputer.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Michael Behrisch
|
||||
/// @date 2004-01-12
|
||||
///
|
||||
// This class computes shapes of junctions
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <utils/geom/PositionVector.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
class NBNode;
|
||||
class NBEdge;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBNodeShapeComputer
|
||||
* @brief This class computes shapes of junctions
|
||||
*/
|
||||
class NBNodeShapeComputer {
|
||||
public:
|
||||
/// Constructor
|
||||
NBNodeShapeComputer(const NBNode& node);
|
||||
|
||||
/// Destructor
|
||||
~NBNodeShapeComputer();
|
||||
|
||||
/// Computes the shape of the assigned junction
|
||||
PositionVector compute();
|
||||
|
||||
/// @brief get computed radius for node
|
||||
double getRadius() const {
|
||||
return myRadius;
|
||||
}
|
||||
|
||||
private:
|
||||
typedef std::map<NBEdge*, PositionVector> GeomsMap;
|
||||
|
||||
/** @brief Computes the node geometry
|
||||
* Edges with the same direction are grouped.
|
||||
* Then the node geometry is built from intersection between the borders
|
||||
* of adjacent edge groups
|
||||
*/
|
||||
PositionVector computeNodeShapeDefault(bool simpleContinuation);
|
||||
|
||||
/** @brief Computes the node geometry using normals
|
||||
*
|
||||
* In the case the other method does not work, this method computes the geometry
|
||||
* of a node by adding points to the polygon which are computed by building
|
||||
* the normals of participating edges' geometry boundaries (cw/ccw)
|
||||
* at the node's height (the length of the edge the edge would cross the node
|
||||
* point).
|
||||
*
|
||||
* @note This usually gives a very small node shape, appropriate for
|
||||
* dead-ends or turn-around-only situations
|
||||
*/
|
||||
PositionVector computeNodeShapeSmall();
|
||||
|
||||
/// @brief compute clockwise/counter-clockwise edge boundaries
|
||||
void computeEdgeBoundaries(const EdgeVector& edges,
|
||||
GeomsMap& geomsCCW,
|
||||
GeomsMap& geomsCW);
|
||||
|
||||
/** @brief Joins edges and computes ccw/cw boundaries
|
||||
*
|
||||
* This method goes through all edges and stores each edge's ccw and cw
|
||||
* boundary in geomsCCW/geomsCW. This boundary is extrapolated by 100m
|
||||
* at the node's position.
|
||||
* In addition, "same" is filled so that this map contains a list of
|
||||
* all edges within the value-vector which direction at the node differs
|
||||
* less than 1 from the key-edge's direction.
|
||||
*/
|
||||
void joinSameDirectionEdges(const EdgeVector& edges, std::map<NBEdge*, std::set<NBEdge*> >& same);
|
||||
|
||||
/** @brief Joins edges
|
||||
*
|
||||
* This methods joins edges which are in marked as being "same" in the means
|
||||
* as given by joinSameDirectionEdges. The result (list of so-to-say "directions"
|
||||
* is returned;
|
||||
*/
|
||||
EdgeVector computeUniqueDirectionList(
|
||||
const EdgeVector& all,
|
||||
std::map<NBEdge*, std::set<NBEdge*> >& same,
|
||||
GeomsMap& geomsCCW,
|
||||
GeomsMap& geomsCW);
|
||||
|
||||
/** @brief Compute smoothed corner shape
|
||||
* @param[in] begShape
|
||||
* @param[in] endShape
|
||||
* @param[in] begPoint
|
||||
* @param[in] endPoint
|
||||
* @param[in] cornerDetail
|
||||
* @return shape to be appended between begPoint and endPoint
|
||||
*/
|
||||
PositionVector getSmoothCorner(PositionVector begShape, PositionVector endShape,
|
||||
const Position& begPoint, const Position& endPoint, int cornerDetail);
|
||||
|
||||
/** @brief Initialize neighbors and angles
|
||||
* @param[in] edges The list of edges sorted in clockwise direction
|
||||
* @param[in] current An iterator to the current edge
|
||||
* @param[in] geomsCW geometry map
|
||||
* @param[in] geomsCCW geometry map
|
||||
* @param[out] cwi An iterator to the clockwise neighbor
|
||||
* @param[out] ccwi An iterator to the counter-clockwise neighbor
|
||||
* @param[out] cad The angle difference to the clockwise neighbor
|
||||
* @param[out] ccad The angle difference to the counter-clockwise neighbor
|
||||
*/
|
||||
static void initNeighbors(const EdgeVector& edges, const EdgeVector::const_iterator& current,
|
||||
GeomsMap& geomsCW,
|
||||
GeomsMap& geomsCCW,
|
||||
EdgeVector::const_iterator& cwi,
|
||||
EdgeVector::const_iterator& ccwi,
|
||||
double& cad,
|
||||
double& ccad);
|
||||
|
||||
/// @return whether trying to intersect these edges would probably fail
|
||||
bool badIntersection(const NBEdge* e1, const NBEdge* e2, double distance);
|
||||
|
||||
/// @brief return the intersection point closest to the given offset
|
||||
double closestIntersection(const PositionVector& geom1, const PositionVector& geom2, double offset);
|
||||
|
||||
/// @brief whether the given edges (along with those in the same direction) requires a large turning radius
|
||||
bool needsLargeTurn(NBEdge* e1, NBEdge* e2,
|
||||
std::map<NBEdge*, std::set<NBEdge*> >& same) const;
|
||||
|
||||
/// @brief determine the default radius appropriate for the current junction
|
||||
double getDefaultRadius(const OptionsCont& oc);
|
||||
|
||||
/// @brief compute with of rightmost lanes that exlude the given permissions
|
||||
static double getExtraWidth(const NBEdge* e, SVCPermissions exclude);
|
||||
|
||||
private:
|
||||
/// The node to compute the geometry for
|
||||
const NBNode& myNode;
|
||||
|
||||
/// @brief the computed node radius
|
||||
double myRadius;
|
||||
|
||||
static const SVCPermissions SVC_LARGE_TURN;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated assignment operator
|
||||
NBNodeShapeComputer& operator=(const NBNodeShapeComputer& s);
|
||||
|
||||
};
|
File diff suppressed because it is too large
Load Diff
|
@ -1,281 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBOwnTLDef.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Sascha Krieg
|
||||
/// @date Tue, 29.05.2005
|
||||
///
|
||||
// A traffic light logics which must be computed (only nodes/edges are given)
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <utils/xml/SUMOXMLDefinitions.h>
|
||||
#include "NBTrafficLightDefinition.h"
|
||||
#include "NBNode.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBOwnTLDef
|
||||
* @brief A traffic light logics which must be computed (only nodes/edges are given)
|
||||
*/
|
||||
class NBOwnTLDef : public NBTrafficLightDefinition {
|
||||
public:
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] junctions Junctions controlled by this tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBOwnTLDef(const std::string& id,
|
||||
const std::vector<NBNode*>& junctions,
|
||||
SUMOTime offset,
|
||||
TrafficLightType type);
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] junction The junction controlled by this tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBOwnTLDef(const std::string& id, NBNode* junction, SUMOTime offset,
|
||||
TrafficLightType type);
|
||||
|
||||
|
||||
/** @brief Constructor
|
||||
* @param[in] id The id of the tls
|
||||
* @param[in] offset The offset of the plan
|
||||
* @param[in] type The algorithm type for the computed traffic light
|
||||
*/
|
||||
NBOwnTLDef(const std::string& id, SUMOTime offset, TrafficLightType type);
|
||||
|
||||
|
||||
/// @brief Destructor
|
||||
~NBOwnTLDef();
|
||||
|
||||
|
||||
/// @name Public methods from NBTrafficLightDefinition-interface
|
||||
/// @{
|
||||
|
||||
/** @brief Replaces occurences of the removed edge in incoming/outgoing edges of all definitions
|
||||
* @param[in] removed The removed edge
|
||||
* @param[in] incoming The edges to use instead if an incoming edge was removed
|
||||
* @param[in] outgoing The edges to use instead if an outgoing edge was removed
|
||||
* @see NBTrafficLightDefinition::remapRemoved
|
||||
*/
|
||||
void remapRemoved(NBEdge* removed,
|
||||
const EdgeVector& incoming, const EdgeVector& outgoing);
|
||||
|
||||
|
||||
/** @brief Informs edges about being controlled by a tls
|
||||
* @see NBTrafficLightDefinition::setTLControllingInformation
|
||||
*/
|
||||
void setTLControllingInformation() const;
|
||||
/// @}
|
||||
|
||||
|
||||
/** @brief Forces the definition not to compute an additional phase for left-movers
|
||||
*/
|
||||
void setSinglePhase() {
|
||||
myHaveSinglePhase = true;
|
||||
}
|
||||
|
||||
/// @brief add an additional pedestrian phase if there are crossings that did not get green yet
|
||||
static void addPedestrianScramble(NBTrafficLightLogic* logic, int noLinksAll,
|
||||
SUMOTime greenTime, SUMOTime yellowTime,
|
||||
const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);
|
||||
|
||||
/// @brief add 1 or 2 phases depending on the presence of pedestrian crossings
|
||||
static std::string addPedestrianPhases(NBTrafficLightLogic* logic, SUMOTime greenTime,
|
||||
SUMOTime minDur, SUMOTime maxDur,
|
||||
std::string state, const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);
|
||||
|
||||
/// @brief compute phase state in regard to pedestrian crossings
|
||||
static std::string patchStateForCrossings(const std::string& state,
|
||||
const std::vector<NBNode::Crossing*>& crossings, const EdgeVector& fromEdges, const EdgeVector& toEdges);
|
||||
|
||||
/** @brief helper function for myCompute
|
||||
* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls
|
||||
* @param[in] onlyConts whether the method is only called to compute myNeedsContRelation
|
||||
* @return The computed logic
|
||||
*/
|
||||
NBTrafficLightLogic* computeLogicAndConts(int brakingTimeSeconds, bool onlyConts = false);
|
||||
|
||||
/* initialize myNeedsContRelation and set myNeedsContRelationReady to true */
|
||||
void initNeedsContRelation() const;
|
||||
|
||||
/* build optional all-red phase */
|
||||
void buildAllRedState(SUMOTime allRedTime, NBTrafficLightLogic* logic, const std::string& state);
|
||||
|
||||
///@brief Returns the maximum index controlled by this traffic light
|
||||
int getMaxIndex();
|
||||
|
||||
protected:
|
||||
/// @name Protected methods from NBTrafficLightDefinition-interface
|
||||
/// @{
|
||||
|
||||
/** @brief Computes the traffic light logic finally in dependence to the type
|
||||
* @param[in] brakingTime Duration a vehicle needs for braking in front of the tls
|
||||
* @return The computed logic
|
||||
* @see NBTrafficLightDefinition::myCompute
|
||||
*/
|
||||
NBTrafficLightLogic* myCompute(int brakingTimeSeconds);
|
||||
|
||||
|
||||
/** @brief Collects the links participating in this traffic light
|
||||
* @exception ProcessError If a link could not be found
|
||||
* @see NBTrafficLightDefinition::collectLinks
|
||||
*/
|
||||
void collectLinks();
|
||||
|
||||
|
||||
/** @brief Replaces a removed edge/lane
|
||||
* @param[in] removed The edge to replace
|
||||
* @param[in] removedLane The lane of this edge to replace
|
||||
* @param[in] by The edge to insert instead
|
||||
* @param[in] byLane This edge's lane to insert instead
|
||||
* @see NBTrafficLightDefinition::replaceRemoved
|
||||
*/
|
||||
void replaceRemoved(NBEdge* removed, int removedLane,
|
||||
NBEdge* by, int byLane, bool incoming);
|
||||
/// @}
|
||||
|
||||
|
||||
protected:
|
||||
|
||||
/// @brief test whether a joined tls with layout 'opposites' would be built without dedicated left-turn phase
|
||||
bool corridorLike() const;
|
||||
|
||||
/** @brief Returns the weight of a stream given its direction
|
||||
* @param[in] dir The direction of the stream
|
||||
* @return This stream's weight
|
||||
* @todo There are several magic numbers; describe
|
||||
*/
|
||||
double getDirectionalWeight(LinkDirection dir);
|
||||
|
||||
|
||||
/** @brief Returns this edge's priority at the node it ends at
|
||||
* @param[in] e The edge to ask for his priority
|
||||
* @return The edge's priority at his destination node
|
||||
*/
|
||||
int getToPrio(const NBEdge* const e);
|
||||
|
||||
|
||||
/** @brief Returns how many streams outgoing from the edges can pass the junction without being blocked
|
||||
* @param[in] e1 The first edge
|
||||
* @param[in] e2 The second edge
|
||||
* @todo There are several magic numbers; describe
|
||||
*/
|
||||
double computeUnblockedWeightedStreamNumber(const NBEdge* const e1, const NBEdge* const e2);
|
||||
|
||||
|
||||
/** @brief Returns the combination of two edges from the given which has most unblocked streams
|
||||
* @param[in] edges The list of edges to include in the computation
|
||||
* @return The two edges for which the weighted number of unblocked streams is the highest
|
||||
*/
|
||||
std::pair<NBEdge*, NBEdge*> getBestCombination(const EdgeVector& edges);
|
||||
|
||||
|
||||
/** @brief Returns the combination of two edges from the given which has most unblocked streams
|
||||
*
|
||||
* The chosen edges are removed from the given vector
|
||||
*
|
||||
* @param[in, changed] incoming The list of edges which are participating in the logic
|
||||
* @return The two edges for which the weighted number of unblocked streams is the highest
|
||||
*/
|
||||
std::pair<NBEdge*, NBEdge*> getBestPair(EdgeVector& incoming);
|
||||
|
||||
|
||||
/// @brief compute whether the given connection is crossed by pedestrians
|
||||
static bool hasCrossing(const NBEdge* from, const NBEdge* to, const std::vector<NBNode::Crossing*>& crossings);
|
||||
|
||||
/// @brief get edges that have connections
|
||||
static EdgeVector getConnectedOuterEdges(const EdgeVector& incoming);
|
||||
|
||||
|
||||
/// @brief allow connections that are compatible with the chosen edges
|
||||
std::string allowCompatible(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
|
||||
const std::vector<int>& fromLanes, const std::vector<int>& toLanes);
|
||||
|
||||
std::string allowSingleEdge(std::string state, const EdgeVector& fromEdges);
|
||||
|
||||
std::string allowFollowers(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges);
|
||||
|
||||
std::string allowPredecessors(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
|
||||
const std::vector<int>& fromLanes, const std::vector<int>& toLanes);
|
||||
|
||||
std::string allowUnrelated(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
|
||||
const std::vector<bool>& isTurnaround,
|
||||
const std::vector<NBNode::Crossing*>& crossings);
|
||||
|
||||
std::string allowByVClass(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges, SVCPermissions perm);
|
||||
|
||||
/// @brief whether the given index is forbidden by a green link in the current state
|
||||
bool forbidden(const std::string& state, int index, const EdgeVector& fromEdges, const EdgeVector& toEdges);
|
||||
|
||||
/** @brief change 'G' to 'g' for conflicting connections
|
||||
* @param[in] state
|
||||
* @param[in] fromEdges
|
||||
* @param[in] toEdges
|
||||
* @param[in] isTurnaround
|
||||
* @param[in] fromLanes
|
||||
* @param[in] hadGreenMajor
|
||||
* @param[out] haveForbiddenLeftMover
|
||||
* @param[out] rightTurnConflicts
|
||||
* @return The corrected state
|
||||
*/
|
||||
std::string correctConflicting(std::string state, const EdgeVector& fromEdges, const EdgeVector& toEdges,
|
||||
const std::vector<bool>& isTurnaround,
|
||||
const std::vector<int>& fromLanes,
|
||||
const std::vector<bool>& hadGreenMajor,
|
||||
bool& haveForbiddenLeftMover, std::vector<bool>& rightTurnConflicts);
|
||||
|
||||
/// @brief fix states in regard to custom crossing indices
|
||||
void checkCustomCrossingIndices(NBTrafficLightLogic* logic) const;
|
||||
|
||||
/** @class edge_by_incoming_priority_sorter
|
||||
* @brief Sorts edges by their priority within the node they end at
|
||||
*/
|
||||
class edge_by_incoming_priority_sorter {
|
||||
public:
|
||||
/** @brief comparing operator
|
||||
* @param[in] e1 an edge
|
||||
* @param[in] e2 an edge
|
||||
*/
|
||||
int operator()(const NBEdge* const e1, const NBEdge* const e2) const {
|
||||
if (e1->getJunctionPriority(e1->getToNode()) != e2->getJunctionPriority(e2->getToNode())) {
|
||||
return e1->getJunctionPriority(e1->getToNode()) > e2->getJunctionPriority(e2->getToNode());
|
||||
}
|
||||
return e1->getID() > e2->getID();
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
/// @brief Whether left-mover should not have an additional phase
|
||||
bool myHaveSinglePhase;
|
||||
|
||||
};
|
|
@ -1,265 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTLine.cpp
|
||||
/// @author Gregor Laemmel
|
||||
/// @author Nikita Cherednychek
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// The representation of one direction of a single pt line
|
||||
/****************************************************************************/
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
|
||||
#include <utility>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBPTLine.h"
|
||||
#include "NBPTStop.h"
|
||||
|
||||
NBPTLine::NBPTLine(const std::string& id, const std::string& name, const std::string& type, const std::string& ref, int interval, const std::string& nightService,
|
||||
SUMOVehicleClass vClass) :
|
||||
myName(name),
|
||||
myType(type),
|
||||
myPTLineId(id),
|
||||
myRef(ref != "" ? ref : name),
|
||||
myInterval(interval),
|
||||
myNightService(nightService),
|
||||
myVClass(vClass)
|
||||
{ }
|
||||
|
||||
void NBPTLine::addPTStop(NBPTStop* pStop) {
|
||||
myPTStops.push_back(pStop);
|
||||
|
||||
}
|
||||
|
||||
std::vector<NBPTStop*> NBPTLine::getStops() {
|
||||
return myPTStops;
|
||||
}
|
||||
|
||||
void NBPTLine::write(OutputDevice& device, NBEdgeCont& ec) {
|
||||
device.openTag(SUMO_TAG_PT_LINE);
|
||||
device.writeAttr(SUMO_ATTR_ID, myPTLineId);
|
||||
if (!myName.empty()) {
|
||||
device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
|
||||
}
|
||||
|
||||
device.writeAttr(SUMO_ATTR_LINE, StringUtils::escapeXML(myRef));
|
||||
device.writeAttr(SUMO_ATTR_TYPE, myType);
|
||||
device.writeAttr(SUMO_ATTR_VCLASS, toString(myVClass));
|
||||
if (myInterval > 0) {
|
||||
// write seconds
|
||||
device.writeAttr(SUMO_ATTR_PERIOD, 60 * myInterval);
|
||||
}
|
||||
if (myNightService != "") {
|
||||
device.writeAttr("nightService", myNightService);
|
||||
}
|
||||
device.writeAttr("completeness", toString((double)myPTStops.size() / (double)myNumOfStops));
|
||||
|
||||
std::vector<std::string> validEdgeIDs;
|
||||
// filter out edges that have been removed due to joining junctions
|
||||
// (the rest of the route is valid)
|
||||
for (NBEdge* e : myRoute) {
|
||||
if (ec.retrieve(e->getID())) {
|
||||
validEdgeIDs.push_back(e->getID());
|
||||
}
|
||||
}
|
||||
if (!myRoute.empty()) {
|
||||
device.openTag(SUMO_TAG_ROUTE);
|
||||
device.writeAttr(SUMO_ATTR_EDGES, validEdgeIDs);
|
||||
device.closeTag();
|
||||
}
|
||||
|
||||
for (auto& myPTStop : myPTStops) {
|
||||
device.openTag(SUMO_TAG_BUS_STOP);
|
||||
device.writeAttr(SUMO_ATTR_ID, myPTStop->getID());
|
||||
device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myPTStop->getName()));
|
||||
device.closeTag();
|
||||
}
|
||||
device.closeTag();
|
||||
|
||||
}
|
||||
|
||||
void NBPTLine::addWayNode(long long int way, long long int node) {
|
||||
std::string wayStr = toString(way);
|
||||
if (wayStr != myCurrentWay) {
|
||||
myCurrentWay = wayStr;
|
||||
myWays.push_back(wayStr);
|
||||
}
|
||||
myWaysNodes[wayStr].push_back(node);
|
||||
|
||||
}
|
||||
const std::vector<std::string>& NBPTLine::getMyWays() const {
|
||||
return myWays;
|
||||
}
|
||||
std::vector<long long int>* NBPTLine::getWaysNodes(std::string wayId) {
|
||||
if (myWaysNodes.find(wayId) != myWaysNodes.end()) {
|
||||
return &myWaysNodes[wayId];
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
void
|
||||
NBPTLine::setEdges(const std::vector<NBEdge*>& edges) {
|
||||
myRoute = edges;
|
||||
// ensure permissions
|
||||
for (NBEdge* e : edges) {
|
||||
SVCPermissions permissions = e->getPermissions();
|
||||
if ((permissions & myVClass) != myVClass) {
|
||||
SVCPermissions nVuln = ~(SVC_PEDESTRIAN | SVC_BICYCLE);
|
||||
if (permissions != 0 && (permissions & nVuln) == 0) {
|
||||
// this is a footpath or sidewalk. Add another lane
|
||||
e->addRestrictedLane(SUMO_const_laneWidth, myVClass);
|
||||
} else {
|
||||
// add permissions to the rightmost lane that is not exclusively used for pedestrians / bicycles
|
||||
for (int i = 0; i < (int)e->getNumLanes(); i++) {
|
||||
if ((e->getPermissions(i) & nVuln) != 0) {
|
||||
e->allowVehicleClass(i, myVClass);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NBPTLine::setMyNumOfStops(int numStops) {
|
||||
myNumOfStops = numStops;
|
||||
}
|
||||
const std::vector<NBEdge*>& NBPTLine::getRoute() const {
|
||||
return myRoute;
|
||||
}
|
||||
|
||||
std::vector<NBEdge*>
|
||||
NBPTLine::getStopEdges(const NBEdgeCont& ec) const {
|
||||
std::vector<NBEdge*> result;
|
||||
for (NBPTStop* stop : myPTStops) {
|
||||
NBEdge* e = ec.retrieve(stop->getEdgeId());
|
||||
if (e != nullptr) {
|
||||
result.push_back(e);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
NBEdge*
|
||||
NBPTLine::getRouteStart(const NBEdgeCont& ec) const {
|
||||
std::vector<NBEdge*> validEdges;
|
||||
// filter out edges that have been removed due to joining junctions
|
||||
for (NBEdge* e : myRoute) {
|
||||
if (ec.retrieve(e->getID())) {
|
||||
validEdges.push_back(e);
|
||||
}
|
||||
}
|
||||
if (validEdges.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
// filter out edges after the first stop
|
||||
if (myPTStops.size() > 0) {
|
||||
NBEdge* firstStopEdge = ec.retrieve(myPTStops.front()->getEdgeId());
|
||||
if (firstStopEdge == nullptr) {
|
||||
WRITE_WARNING("Could not retrieve edge '" + myPTStops.front()->getEdgeId() + "' for first stop of line '" + myPTLineId + "'");
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
auto it = std::find(validEdges.begin(), validEdges.end(), firstStopEdge);
|
||||
if (it == validEdges.end()) {
|
||||
WRITE_WARNING("First stop edge '" + firstStopEdge->getID() + "' is not part of the route of line '" + myPTLineId + "'");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return validEdges.front();
|
||||
}
|
||||
|
||||
NBEdge*
|
||||
NBPTLine::getRouteEnd(const NBEdgeCont& ec) const {
|
||||
std::vector<NBEdge*> validEdges;
|
||||
// filter out edges that have been removed due to joining junctions
|
||||
for (NBEdge* e : myRoute) {
|
||||
if (ec.retrieve(e->getID())) {
|
||||
validEdges.push_back(e);
|
||||
}
|
||||
}
|
||||
if (validEdges.size() == 0) {
|
||||
return nullptr;
|
||||
}
|
||||
// filter out edges after the last stop
|
||||
if (myPTStops.size() > 0) {
|
||||
NBEdge* lastStopEdge = ec.retrieve(myPTStops.back()->getEdgeId());
|
||||
if (lastStopEdge == nullptr) {
|
||||
WRITE_WARNING("Could not retrieve edge '" + myPTStops.back()->getEdgeId() + "' for last stop of line '" + myPTLineId + "'");
|
||||
return nullptr;
|
||||
|
||||
}
|
||||
auto it = std::find(validEdges.begin(), validEdges.end(), lastStopEdge);
|
||||
if (it == validEdges.end()) {
|
||||
WRITE_WARNING("Last stop edge '" + lastStopEdge->getID() + "' is not part of the route of line '" + myPTLineId + "'");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
return validEdges.back();
|
||||
}
|
||||
|
||||
void
|
||||
NBPTLine::replaceStop(NBPTStop* oldStop, NBPTStop* newStop) {
|
||||
for (int i = 0; i < (int)myPTStops.size(); i++) {
|
||||
if (myPTStops[i] == oldStop) {
|
||||
myPTStops[i] = newStop;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
NBPTLine::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
|
||||
EdgeVector oldRoute = myRoute;
|
||||
int stopIndex = 0;
|
||||
myRoute.clear();
|
||||
std::vector<NBPTStop*> unassigned;
|
||||
for (NBEdge* e : oldRoute) {
|
||||
if (e->getID() == edgeID) {
|
||||
myRoute.insert(myRoute.end(), replacement.begin(), replacement.end());
|
||||
} else {
|
||||
myRoute.push_back(e);
|
||||
}
|
||||
while (stopIndex < (int)myPTStops.size() && myPTStops[stopIndex]->getEdgeId() == e->getID()) {
|
||||
if (e->getID() == edgeID) {
|
||||
NBPTStop* stop = myPTStops[stopIndex];
|
||||
// find best edge among replacement edges
|
||||
double bestDist = std::numeric_limits<double>::max();
|
||||
NBEdge* bestEdge = nullptr;
|
||||
for (NBEdge* cand : replacement) {
|
||||
double dist = cand->getGeometry().distance2D(stop->getPosition());
|
||||
if (dist < bestDist) {
|
||||
bestDist = dist;
|
||||
bestEdge = cand;
|
||||
}
|
||||
}
|
||||
if (bestDist != std::numeric_limits<double>::max()) {
|
||||
stop->findLaneAndComputeBusStopExtent(bestEdge);
|
||||
if ((bestEdge->getPermissions() & SVC_PEDESTRIAN) != 0) {
|
||||
// no need for access
|
||||
stop->clearAccess();
|
||||
}
|
||||
} else {
|
||||
WRITE_WARNING("Could not re-assign ptstop '" + stop->getID() + "' after replacing edge '" + edgeID + "'");
|
||||
unassigned.push_back(stop);
|
||||
}
|
||||
}
|
||||
stopIndex++;
|
||||
}
|
||||
}
|
||||
for (NBPTStop* stop: unassigned) {
|
||||
myPTStops.erase(std::find(myPTStops.begin(), myPTStops.end(), stop));
|
||||
}
|
||||
}
|
|
@ -1,125 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTLine.h
|
||||
/// @author Gregor Laemmel
|
||||
/// @author Nikita Cherednychek
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// The representation of one direction of a single pt line
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include "NBEdge.h" // Cherednychek
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OutputDevice;
|
||||
class NBPTStop;
|
||||
class NBEdgeCont;
|
||||
|
||||
class NBPTLine {
|
||||
|
||||
public:
|
||||
explicit NBPTLine(const std::string& id, const std::string& name,
|
||||
const std::string& type, const std::string& ref, int interval, const std::string& nightService,
|
||||
SUMOVehicleClass vClass);
|
||||
|
||||
void addPTStop(NBPTStop* pStop);
|
||||
|
||||
const std::string& getLineID() const {
|
||||
return myPTLineId;
|
||||
}
|
||||
|
||||
const std::string& getName() const {
|
||||
return myName;
|
||||
}
|
||||
|
||||
const std::string& getType() const {
|
||||
return myType;
|
||||
}
|
||||
|
||||
std::vector<NBPTStop*> getStops();
|
||||
void write(OutputDevice& device, NBEdgeCont& ec);
|
||||
void addWayNode(long long int way, long long int node);
|
||||
|
||||
void setMyNumOfStops(int numStops);
|
||||
|
||||
/// @brief get line reference (not unique)
|
||||
const std::string& getRef() const {
|
||||
return myRef;
|
||||
}
|
||||
|
||||
void replaceStops(std::vector<NBPTStop*> stops) {
|
||||
myPTStops = stops;
|
||||
}
|
||||
/// @brief get stop edges
|
||||
std::vector<NBEdge*> getStopEdges(const NBEdgeCont& ec) const;
|
||||
|
||||
/// @brief return first valid edge of myRoute (if it doest not lie after the first stop)
|
||||
NBEdge* getRouteStart(const NBEdgeCont& ec) const;
|
||||
|
||||
/// @brief return last valid edge of myRoute (if it doest not lie before the last stop)
|
||||
NBEdge* getRouteEnd(const NBEdgeCont& ec) const;
|
||||
|
||||
/// @brief replace the given stop
|
||||
void replaceStop(NBPTStop* oldStop, NBPTStop* newStop);
|
||||
|
||||
/// @brief replace the edge with the given edge list
|
||||
void replaceEdge(const std::string& edgeID, const EdgeVector& replacement);
|
||||
|
||||
void setName(const std::string& name) {
|
||||
myName = name;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string myName;
|
||||
std::string myType;
|
||||
std::vector<NBPTStop*> myPTStops;
|
||||
|
||||
private:
|
||||
std::map<std::string, std::vector<long long int> > myWaysNodes;
|
||||
std::vector<std::string> myWays;
|
||||
public:
|
||||
const std::vector<std::string>& getMyWays() const;
|
||||
std::vector<long long int>* getWaysNodes(std::string wayId);
|
||||
private:
|
||||
|
||||
std::string myCurrentWay;
|
||||
std::string myPTLineId;
|
||||
std::string myRef;
|
||||
|
||||
// @brief the service interval in minutes
|
||||
int myInterval;
|
||||
|
||||
std::string myNightService;
|
||||
SUMOVehicleClass myVClass;
|
||||
|
||||
public:
|
||||
void setEdges(const std::vector<NBEdge*>& edges);
|
||||
private:
|
||||
// route of ptline
|
||||
std::vector<NBEdge*> myRoute;
|
||||
public:
|
||||
const std::vector<NBEdge*>& getRoute() const;
|
||||
private:
|
||||
|
||||
int myNumOfStops;
|
||||
};
|
||||
|
||||
|
|
@ -1,491 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTLineCont.cpp
|
||||
/// @author Gregor Laemmel
|
||||
/// @author Nikita Cherednychek
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// Container for NBPTLine during netbuild
|
||||
/****************************************************************************/
|
||||
|
||||
#include <iostream>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/common/ToString.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/router/DijkstraRouter.h>
|
||||
#include "NBPTLineCont.h"
|
||||
#include "NBPTStop.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBNode.h"
|
||||
#include "NBVehicle.h"
|
||||
#include "NBPTStopCont.h"
|
||||
|
||||
//#define DEBUG_FIND_WAY
|
||||
#define DEBUGSTOPID ""
|
||||
|
||||
// ===========================================================================
|
||||
// static value definitions
|
||||
// ===========================================================================
|
||||
const int NBPTLineCont::FWD(1);
|
||||
const int NBPTLineCont::BWD(-1);
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
|
||||
NBPTLineCont::NBPTLineCont() { }
|
||||
|
||||
|
||||
NBPTLineCont::~NBPTLineCont() {
|
||||
for (auto& myPTLine : myPTLines) {
|
||||
delete myPTLine.second;
|
||||
}
|
||||
myPTLines.clear();
|
||||
}
|
||||
|
||||
void
|
||||
NBPTLineCont::insert(NBPTLine* ptLine) {
|
||||
myPTLines[ptLine->getLineID()] = ptLine;
|
||||
}
|
||||
|
||||
void NBPTLineCont::process(NBEdgeCont& ec, NBPTStopCont& sc) {
|
||||
for (auto& item : myPTLines) {
|
||||
if (item.second->getMyWays().size() > 0) {
|
||||
// loaded from OSM rather than ptline input. We can use extra
|
||||
// information to reconstruct route and stops
|
||||
constructRoute(item.second, ec);
|
||||
// map stops to ways, using the constructed route for loose stops
|
||||
reviseStops(item.second, ec, sc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void NBPTLineCont::reviseStops(NBPTLine* line, const NBEdgeCont& ec, NBPTStopCont& sc) {
|
||||
const std::vector<std::string>& waysIds = line->getMyWays();
|
||||
if (waysIds.size() <= 1) {
|
||||
WRITE_WARNING("Cannot revise pt stop localization for pt line: " + line->getLineID() + ", which consist of one way only. Ignoring!");
|
||||
return;
|
||||
}
|
||||
if (line->getRoute().size() == 0) {
|
||||
WRITE_WARNING("Cannot revise pt stop localization for pt line: " + line->getLineID() + ", which has no route edges. Ignoring!");
|
||||
return;
|
||||
}
|
||||
std::vector<NBPTStop*> stops = line->getStops();
|
||||
for (NBPTStop* stop : stops) {
|
||||
//get the corresponding and one of the two adjacent ways
|
||||
stop = findWay(line, stop, ec, sc);
|
||||
auto waysIdsIt = std::find(waysIds.begin(), waysIds.end(), stop->getOrigEdgeId());
|
||||
if (waysIdsIt == waysIds.end()) {
|
||||
// warning already given
|
||||
continue;
|
||||
}
|
||||
// find directional edge (OSM ways are bidirectional)
|
||||
std::vector<long long int>* way = line->getWaysNodes(stop->getOrigEdgeId());
|
||||
if (way == nullptr) {
|
||||
WRITE_WARNING("Cannot assign stop '" + stop->getID() + "' on edge '" + stop->getOrigEdgeId() + "' to pt line '" + line->getLineID() + "' (wayNodes not found). Ignoring!");
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
int dir;
|
||||
std::string adjIdPrev;
|
||||
std::string adjIdNext;
|
||||
if (waysIdsIt != waysIds.begin()) {
|
||||
adjIdPrev = *(waysIdsIt - 1);
|
||||
}
|
||||
if (waysIdsIt != (waysIds.end() - 1)) {
|
||||
adjIdNext = *(waysIdsIt + 1);
|
||||
}
|
||||
std::vector<long long int>* wayPrev = line->getWaysNodes(adjIdPrev);
|
||||
std::vector<long long int>* wayNext = line->getWaysNodes(adjIdNext);
|
||||
if (wayPrev == nullptr && wayNext == nullptr) {
|
||||
WRITE_WARNING("Cannot revise pt stop localization for incomplete pt line: " + line->getLineID()
|
||||
+ ". Ignoring!");
|
||||
continue;
|
||||
}
|
||||
long long int wayEnds = *(way->end() - 1);
|
||||
long long int wayBegins = *(way->begin());
|
||||
long long int wayPrevEnds = wayPrev != nullptr ? *(wayPrev->end() - 1) : 0;
|
||||
long long int wayPrevBegins = wayPrev != nullptr ? *(wayPrev->begin()) : 0;
|
||||
long long int wayNextEnds = wayNext != nullptr ? *(wayNext->end() - 1) : 0;
|
||||
long long int wayNextBegins = wayNext != nullptr ? *(wayNext->begin()) : 0;
|
||||
if (wayBegins == wayPrevEnds || wayBegins == wayPrevBegins || wayEnds == wayNextBegins
|
||||
|| wayEnds == wayNextEnds) {
|
||||
dir = FWD;
|
||||
} else if (wayEnds == wayPrevBegins || wayEnds == wayPrevEnds || wayBegins == wayNextEnds
|
||||
|| wayBegins == wayNextBegins) {
|
||||
dir = BWD;
|
||||
} else {
|
||||
WRITE_WARNING("Cannot revise pt stop localization for incomplete pt line: " + line->getLineID()
|
||||
+ ". Ignoring!");
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string edgeId = stop->getEdgeId();
|
||||
NBEdge* current = ec.getByID(edgeId);
|
||||
int assignedTo = edgeId.at(0) == '-' ? BWD : FWD;
|
||||
|
||||
if (dir != assignedTo) {
|
||||
NBEdge* reverse = NBPTStopCont::getReverseEdge(current);
|
||||
if (reverse == nullptr) {
|
||||
WRITE_WARNING("Could not re-assign PT stop: " + stop->getID() + " probably broken osm file");
|
||||
continue;
|
||||
}
|
||||
stop->setEdgeId(reverse->getID(), ec);
|
||||
WRITE_WARNING("PT stop: " + stop->getID() + " has been moved to edge: " + reverse->getID());
|
||||
}
|
||||
myServedPTStops.insert(stop->getID());
|
||||
stop->addLine(line->getRef());
|
||||
}
|
||||
}
|
||||
|
||||
NBPTStop*
|
||||
NBPTLineCont::findWay(NBPTLine* line, NBPTStop* stop, const NBEdgeCont& ec, NBPTStopCont& sc) const {
|
||||
const std::vector<std::string>& waysIds = line->getMyWays();
|
||||
#ifdef DEBUG_FIND_WAY
|
||||
if (stop->getID() == DEBUGSTOPID) {
|
||||
std::cout << " stop=" << stop->getID() << " line=" << line->getLineID() << " edgeID=" << stop->getEdgeId() << " origID=" << stop->getOrigEdgeId() << "\n";
|
||||
}
|
||||
#endif
|
||||
if (stop->isLoose()) {
|
||||
// find closest edge in route
|
||||
double minDist = std::numeric_limits<double>::max();
|
||||
NBEdge* best = nullptr;
|
||||
for (NBEdge* edge : line->getRoute()) {
|
||||
const double dist = edge->getLaneShape(0).distance2D(stop->getPosition());
|
||||
if (dist < minDist) {
|
||||
best = edge;
|
||||
minDist = dist;
|
||||
}
|
||||
}
|
||||
#ifdef DEBUG_FIND_WAY
|
||||
if (stop->getID() == DEBUGSTOPID) {
|
||||
std::cout << " best=" << Named::getIDSecure(best) << " minDist=" << minDist << " wayID=" << getWayID(best->getID())
|
||||
<< " found=" << (std::find(waysIds.begin(), waysIds.end(), getWayID(best->getID())) != waysIds.end())
|
||||
<< " wayIDs=" << toString(waysIds) << "\n";
|
||||
}
|
||||
#endif
|
||||
if (minDist < OptionsCont::getOptions().getFloat("ptline.match-dist")) {
|
||||
const std::string wayID = getWayID(best->getID());
|
||||
if (stop->getEdgeId() == "") {
|
||||
stop->setEdgeId(best->getID(), ec);
|
||||
stop->setMyOrigEdgeId(wayID);
|
||||
} else if (stop->getEdgeId() != best->getID()) {
|
||||
// stop is used by multiple lines and mapped to different edges.
|
||||
// check if an alterantive stop already exists
|
||||
NBPTStop* newStop = sc.findStop(wayID, stop->getPosition());
|
||||
if (newStop == nullptr) {
|
||||
newStop = new NBPTStop(stop->getID() + "@" + line->getLineID(), stop->getPosition(), best->getID(), wayID, stop->getLength(), stop->getName(), stop->getPermissions());
|
||||
newStop->setEdgeId(best->getID(), ec); // trigger lane assignment
|
||||
sc.insert(newStop);
|
||||
}
|
||||
line->replaceStop(stop, newStop);
|
||||
stop = newStop;
|
||||
}
|
||||
} else {
|
||||
WRITE_WARNING("Could not assign stop '" + stop->getID() + "' to pt line '" + line->getLineID()
|
||||
+ "' (closest edge '" + best->getID() + "', distance " + toString(minDist) + "). Ignoring!");
|
||||
}
|
||||
} else {
|
||||
// if the stop is part of an edge, find that edge among the line edges
|
||||
auto waysIdsIt = waysIds.begin();
|
||||
for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
|
||||
if ((*waysIdsIt) == stop->getOrigEdgeId()) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (waysIdsIt == waysIds.end()) {
|
||||
// stop edge not found, try additional edges
|
||||
for (auto& edgeCand : stop->getMyAdditionalEdgeCandidates()) {
|
||||
bool found = false;
|
||||
waysIdsIt = waysIds.begin();
|
||||
for (; waysIdsIt != waysIds.end(); waysIdsIt++) {
|
||||
if ((*waysIdsIt) == edgeCand.first) {
|
||||
if (stop->setEdgeId(edgeCand.second, ec)) {
|
||||
stop->setMyOrigEdgeId(edgeCand.first);
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (waysIdsIt == waysIds.end()) {
|
||||
WRITE_WARNING("Cannot assign stop '" + stop->getID() + "' on edge '" + stop->getOrigEdgeId() + "' to pt line '" + line->getLineID() + "'. Ignoring!");
|
||||
}
|
||||
}
|
||||
}
|
||||
return stop;
|
||||
}
|
||||
|
||||
|
||||
void NBPTLineCont::constructRoute(NBPTLine* pTLine, NBEdgeCont& cont) {
|
||||
std::vector<NBEdge*> edges;
|
||||
|
||||
NBNode* first = nullptr;
|
||||
NBNode* last = nullptr;
|
||||
std::vector<NBEdge*> prevWayEdges;
|
||||
std::vector<NBEdge*> prevWayMinusEdges;
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
std::vector<NBEdge*> currentWayEdges;
|
||||
std::vector<NBEdge*> currentWayMinusEdges;
|
||||
for (auto it3 = pTLine->getMyWays().begin();
|
||||
it3 != pTLine->getMyWays().end(); it3++) {
|
||||
|
||||
if (cont.retrieve(*it3, false) != nullptr) {
|
||||
currentWayEdges.push_back(cont.retrieve(*it3, false));
|
||||
} else {
|
||||
int i = 0;
|
||||
while (cont.retrieve(*it3 + "#" + std::to_string(i), false) != nullptr) {
|
||||
currentWayEdges.push_back(cont.retrieve(*it3 + "#" + std::to_string(i), false));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
if (cont.retrieve("-" + *it3, false) != nullptr) {
|
||||
currentWayMinusEdges.push_back(cont.retrieve("-" + *it3, false));
|
||||
} else {
|
||||
int i = 0;
|
||||
while (cont.retrieve("-" + *it3 + "#" + std::to_string(i), false) != nullptr) {
|
||||
currentWayMinusEdges.insert(currentWayMinusEdges.begin(),
|
||||
cont.retrieve("-" + *it3 + "#" + std::to_string(i), false));
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (currentWayEdges.empty()) {
|
||||
continue;
|
||||
}
|
||||
if (last == currentWayEdges.front()->getFromNode() && last != nullptr) {
|
||||
if (!prevWayEdges.empty()) {
|
||||
edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
}
|
||||
edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
|
||||
last = currentWayEdges.back()->getToNode();
|
||||
} else if (last == currentWayEdges.back()->getToNode() && last != nullptr) {
|
||||
if (!prevWayEdges.empty()) {
|
||||
edges.insert(edges.end(), prevWayEdges.begin(), prevWayEdges.end());
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
}
|
||||
if (currentWayMinusEdges.empty()) {
|
||||
currentWayEdges.clear();
|
||||
last = nullptr;
|
||||
continue;
|
||||
} else {
|
||||
edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
|
||||
last = currentWayMinusEdges.back()->getToNode();
|
||||
}
|
||||
} else if (first == currentWayEdges.front()->getFromNode() && first != nullptr) {
|
||||
edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
|
||||
edges.insert(edges.end(), currentWayEdges.begin(), currentWayEdges.end());
|
||||
last = currentWayEdges.back()->getToNode();
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
} else if (first == currentWayEdges.back()->getToNode() && first != nullptr) {
|
||||
edges.insert(edges.end(), prevWayMinusEdges.begin(), prevWayMinusEdges.end());
|
||||
if (currentWayMinusEdges.empty()) {
|
||||
currentWayEdges.clear();
|
||||
last = nullptr;
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
continue;
|
||||
} else {
|
||||
edges.insert(edges.end(), currentWayMinusEdges.begin(), currentWayMinusEdges.end());
|
||||
last = currentWayMinusEdges.back()->getToNode();
|
||||
prevWayEdges.clear();
|
||||
prevWayMinusEdges.clear();
|
||||
}
|
||||
} else {
|
||||
if (it3 != pTLine->getMyWays().begin()) {
|
||||
WRITE_WARNING("Incomplete route for ptline '" + toString(pTLine->getLineID()) +
|
||||
(pTLine->getName() != "" ? "' (" + pTLine->getName() + ")" : ""));
|
||||
}
|
||||
prevWayEdges = currentWayEdges;
|
||||
prevWayMinusEdges = currentWayMinusEdges;
|
||||
if (!prevWayEdges.empty()) {
|
||||
first = prevWayEdges.front()->getFromNode();
|
||||
last = prevWayEdges.back()->getToNode();
|
||||
} else {
|
||||
first = nullptr;
|
||||
last = nullptr;
|
||||
}
|
||||
}
|
||||
currentWayEdges.clear();
|
||||
currentWayMinusEdges.clear();
|
||||
}
|
||||
pTLine->setEdges(edges);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTLineCont::addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into) {
|
||||
if (oc.isSet("ptline-output")) {
|
||||
for (auto& item : myPTLines) {
|
||||
for (auto edge : item.second->getRoute()) {
|
||||
into.insert(edge->getID());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTLineCont::replaceEdge(const std::string& edgeID, const EdgeVector& replacement) {
|
||||
//std::cout << " replaceEdge " << edgeID << " replacement=" << toString(replacement) << "\n";
|
||||
for (auto& item : myPTLines) {
|
||||
item.second->replaceEdge(edgeID, replacement);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::set<std::string>&
|
||||
NBPTLineCont::getServedPTStops() {
|
||||
return myServedPTStops;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTLineCont::fixBidiStops(const NBEdgeCont& ec) {
|
||||
std::map<std::string, SUMOVehicleClass> types;
|
||||
types["bus"] = SVC_BUS;
|
||||
types["tram"] = SVC_TRAM;
|
||||
types["train"] = SVC_RAIL;
|
||||
types["subway"] = SVC_RAIL_URBAN;
|
||||
types["light_rail"] = SVC_RAIL_URBAN;
|
||||
types["ferry"] = SVC_SHIP;
|
||||
|
||||
SUMOAbstractRouter<NBRouterEdge, NBVehicle>* const router = new DijkstraRouter<NBRouterEdge, NBVehicle>(
|
||||
ec.getAllRouterEdges(), true, &NBRouterEdge::getTravelTimeStatic, nullptr, true);
|
||||
|
||||
for (auto& item : myPTLines) {
|
||||
NBPTLine* line = item.second;
|
||||
std::vector<NBPTStop*> stops = line->getStops();
|
||||
if (stops.size() < 2) {
|
||||
continue;
|
||||
}
|
||||
if (types.count(line->getType()) == 0) {
|
||||
WRITE_WARNING("Could not determine vehicle class for public transport line of type '"
|
||||
+ line->getType() + "'.");
|
||||
continue;
|
||||
}
|
||||
NBVehicle veh(line->getRef(), types[line->getType()]);
|
||||
std::vector<NBPTStop*> newStops;
|
||||
NBPTStop* from = nullptr;
|
||||
for (auto it = stops.begin(); it != stops.end(); ++it) {
|
||||
NBPTStop* to = *it;
|
||||
NBPTStop* used = *it;
|
||||
if (to->getBidiStop() != nullptr) {
|
||||
double best = std::numeric_limits<double>::max();
|
||||
NBPTStop* to2 = to->getBidiStop();
|
||||
if (from == nullptr) {
|
||||
if ((it + 1) != stops.end()) {
|
||||
from = to;
|
||||
NBPTStop* from2 = to2;
|
||||
to = *(it + 1);
|
||||
const double c1 = getCost(ec, *router, from, to, &veh);
|
||||
const double c2 = getCost(ec, *router, from2, to, &veh);
|
||||
//std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
|
||||
//std::cout << " from2=" << from2->getID() << " to=" << to->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
|
||||
best = c1;
|
||||
if (to->getBidiStop() != nullptr) {
|
||||
to2 = to->getBidiStop();
|
||||
const double c3 = getCost(ec, *router, from, to2, &veh);
|
||||
const double c4 = getCost(ec, *router, from2, to2, &veh);
|
||||
//std::cout << " from=" << from->getID() << " to2=" << to2->getID() << " c3=" << MIN2(10000.0, c3) << "\n";
|
||||
//std::cout << " from2=" << from2->getID() << " to2=" << to2->getID() << " c4=" << MIN2(10000.0, c4) << "\n";
|
||||
if (c2 < best) {
|
||||
used = from2;
|
||||
best = c2;
|
||||
}
|
||||
if (c3 < best) {
|
||||
used = from;
|
||||
best = c3;
|
||||
}
|
||||
if (c4 < best) {
|
||||
used = from2;
|
||||
best = c4;
|
||||
}
|
||||
} else {
|
||||
if (c2 < c1) {
|
||||
used = from2;
|
||||
best = c2;
|
||||
} else {
|
||||
best = c1;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const double c1 = getCost(ec, *router, from, to, &veh);
|
||||
const double c2 = getCost(ec, *router, from, to2, &veh);
|
||||
//std::cout << " from=" << from->getID() << " to=" << to->getID() << " c1=" << MIN2(10000.0, c1) << "\n";
|
||||
//std::cout << " from=" << from->getID() << " t2o=" << to2->getID() << " c2=" << MIN2(10000.0, c2) << "\n";
|
||||
if (c2 < c1) {
|
||||
used = to2;
|
||||
best = c2;
|
||||
} else {
|
||||
best = c1;
|
||||
}
|
||||
|
||||
}
|
||||
if (best < std::numeric_limits<double>::max()) {
|
||||
from = used;
|
||||
} else {
|
||||
WRITE_WARNING("Could not determine direction for line '" + toString(line->getLineID()) + "' at stop '" + used->getID() + "'");
|
||||
};
|
||||
}
|
||||
from = used;
|
||||
newStops.push_back(used);
|
||||
}
|
||||
assert(stops.size() == newStops.size());
|
||||
line->replaceStops(newStops);
|
||||
}
|
||||
delete router;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBPTLineCont::getCost(const NBEdgeCont& ec, SUMOAbstractRouter<NBRouterEdge, NBVehicle>& router,
|
||||
const NBPTStop* from, const NBPTStop* to, const NBVehicle* veh) {
|
||||
NBEdge* fromEdge = ec.getByID(from->getEdgeId());
|
||||
NBEdge* toEdge = ec.getByID(to->getEdgeId());
|
||||
if (fromEdge == nullptr || toEdge == nullptr) {
|
||||
return std::numeric_limits<double>::max();
|
||||
}
|
||||
std::vector<const NBRouterEdge*> route;
|
||||
router.compute(fromEdge, toEdge, veh, 0, route);
|
||||
if (route.size() == 0) {
|
||||
return std::numeric_limits<double>::max();
|
||||
} else {
|
||||
return router.recomputeCosts(route, veh, 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string
|
||||
NBPTLineCont::getWayID(const std::string& edgeID) {
|
||||
std::size_t found = edgeID.rfind("#");
|
||||
std::string result = edgeID;
|
||||
if (found != std::string::npos) {
|
||||
result = edgeID.substr(0, found);
|
||||
}
|
||||
if (result[0] == '-') {
|
||||
result = result.substr(1);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,82 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTLineCont.h
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// Container for NBPTLine during netbuild
|
||||
/****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <vector>
|
||||
#include "utils/router/SUMOAbstractRouter.h"
|
||||
#include "NBPTLine.h"
|
||||
#include "NBEdgeCont.h"
|
||||
|
||||
class NBPTLineCont {
|
||||
|
||||
public:
|
||||
/// @brief constructor
|
||||
NBPTLineCont();
|
||||
|
||||
/// @brief destructor
|
||||
~NBPTLineCont();
|
||||
|
||||
/// @brief insert new line
|
||||
void insert(NBPTLine* ptLine);
|
||||
|
||||
const std::map<std::string, NBPTLine*>& getLines() const {
|
||||
return myPTLines;
|
||||
}
|
||||
|
||||
void process(NBEdgeCont& ec, NBPTStopCont& sc);
|
||||
|
||||
/// @brief add edges that must be kept
|
||||
void addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into);
|
||||
|
||||
/// @brief replace the edge with the given edge list in all lines
|
||||
void replaceEdge(const std::string& edgeID, const EdgeVector& replacement);
|
||||
|
||||
/// @brief select the correct stop on superposed rail edges
|
||||
void fixBidiStops(const NBEdgeCont& ec);
|
||||
|
||||
std::set<std::string>& getServedPTStops();
|
||||
private:
|
||||
|
||||
static const int FWD;
|
||||
static const int BWD;
|
||||
|
||||
/// @brief The map of names to pt lines
|
||||
std::map<std::string, NBPTLine*> myPTLines;
|
||||
|
||||
/// @brief find directional edge for all stops of the line
|
||||
void reviseStops(NBPTLine* line, const NBEdgeCont& ec, NBPTStopCont& sc);
|
||||
|
||||
/* @brief find way element corresponding to the stop
|
||||
* @note: if the edge id is updated, the stop extent is recomputed */
|
||||
NBPTStop* findWay(NBPTLine* line, NBPTStop* stop, const NBEdgeCont& ec, NBPTStopCont& sc) const;
|
||||
|
||||
void constructRoute(NBPTLine* myPTLine, NBEdgeCont& cont);
|
||||
|
||||
std::set<std::string> myServedPTStops;
|
||||
|
||||
static double getCost(const NBEdgeCont& ec, SUMOAbstractRouter<NBRouterEdge, NBVehicle>& router,
|
||||
const NBPTStop* from, const NBPTStop* to, const NBVehicle* veh);
|
||||
|
||||
static std::string getWayID(const std::string& edgeID);
|
||||
};
|
||||
|
||||
|
|
@ -1,40 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTPlatform.cpp
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 24 Aug 2017
|
||||
///
|
||||
// The representation of a pt platform
|
||||
/****************************************************************************/
|
||||
#include "NBPTPlatform.h"
|
||||
NBPTPlatform::NBPTPlatform(Position position, double d): myPos(position), myLength(d) {
|
||||
}
|
||||
|
||||
|
||||
const Position&
|
||||
NBPTPlatform::getPos() const {
|
||||
return myPos;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTPlatform::reshiftPosition(const double offsetX, const double offsetY) {
|
||||
myPos.add(offsetX, offsetY, 0);
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBPTPlatform::getLength() const {
|
||||
return myLength;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTPlatform.h
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 24 Aug 2017
|
||||
///
|
||||
// The representation of a pt platform
|
||||
/****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <utils/geom/Position.h>
|
||||
class NBPTPlatform {
|
||||
public:
|
||||
NBPTPlatform(Position position, double d);
|
||||
public:
|
||||
const Position& getPos() const;
|
||||
void reshiftPosition(const double offsetX, const double offsetY);
|
||||
double getLength() const;
|
||||
private:
|
||||
Position myPos;
|
||||
double myLength;
|
||||
};
|
||||
|
||||
|
|
@ -1,259 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTStop.cpp
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// The representation of a single pt stop
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include <utils/common/StringUtils.h>
|
||||
#include "NBPTStop.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBEdgeCont.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBPTStop::NBPTStop(std::string ptStopId, Position position, std::string edgeId, std::string origEdgeId, double length,
|
||||
std::string name, SVCPermissions svcPermissions, double parkingLength) :
|
||||
myPTStopId(ptStopId),
|
||||
myPosition(position),
|
||||
myEdgeId(edgeId),
|
||||
myOrigEdgeId(origEdgeId),
|
||||
myPTStopLength(length),
|
||||
myName(name),
|
||||
myParkingLength(parkingLength),
|
||||
myPermissions(svcPermissions),
|
||||
myBidiStop(nullptr),
|
||||
myIsLoose(origEdgeId == ""),
|
||||
myIsMultipleStopPositions(false) {
|
||||
}
|
||||
|
||||
std::string
|
||||
NBPTStop::getID() const {
|
||||
return myPTStopId;
|
||||
}
|
||||
|
||||
const std::string
|
||||
NBPTStop::getOrigEdgeId() const {
|
||||
return myOrigEdgeId;
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
NBPTStop::getEdgeId() const {
|
||||
return myEdgeId;
|
||||
}
|
||||
|
||||
|
||||
const std::string
|
||||
NBPTStop::getName() const {
|
||||
return myName;
|
||||
}
|
||||
|
||||
|
||||
const Position&
|
||||
NBPTStop::getPosition() const {
|
||||
return myPosition;
|
||||
}
|
||||
|
||||
void
|
||||
NBPTStop::mirrorX() {
|
||||
myPosition.mul(1, -1);
|
||||
}
|
||||
|
||||
void
|
||||
NBPTStop::computeExtent(double center, double edgeLength) {
|
||||
myStartPos = MAX2(0.0, center - myPTStopLength / 2.);
|
||||
myEndPos = MIN2(center + myPTStopLength / 2., edgeLength);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::addLine(const std::string& line) {
|
||||
const std::string l = StringUtils::escapeXML(line);
|
||||
if (std::find(myLines.begin(), myLines.end(), l) == myLines.end()) {
|
||||
myLines.push_back(l);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::write(OutputDevice& device) {
|
||||
device.openTag(SUMO_TAG_BUS_STOP);
|
||||
device.writeAttr(SUMO_ATTR_ID, myPTStopId);
|
||||
if (!myName.empty()) {
|
||||
device.writeAttr(SUMO_ATTR_NAME, StringUtils::escapeXML(myName));
|
||||
}
|
||||
device.writeAttr(SUMO_ATTR_LANE, myLaneId);
|
||||
device.writeAttr(SUMO_ATTR_STARTPOS, myStartPos);
|
||||
device.writeAttr(SUMO_ATTR_ENDPOS, myEndPos);
|
||||
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, "true");
|
||||
if (myLines.size() > 0) {
|
||||
device.writeAttr(SUMO_ATTR_LINES, toString(myLines));
|
||||
}
|
||||
if (myParkingLength > 0) {
|
||||
device.writeAttr(SUMO_ATTR_PARKING_LENGTH, myParkingLength);
|
||||
}
|
||||
if (!myAccesses.empty()) {
|
||||
std::sort(myAccesses.begin(), myAccesses.end());
|
||||
for (auto tuple : myAccesses) {
|
||||
device.openTag(SUMO_TAG_ACCESS);
|
||||
device.writeAttr(SUMO_ATTR_LANE, std::get<0>(tuple));
|
||||
device.writeAttr(SUMO_ATTR_POSITION, std::get<1>(tuple));
|
||||
device.writeAttr(SUMO_ATTR_LENGTH, std::get<2>(tuple));
|
||||
device.writeAttr(SUMO_ATTR_FRIENDLY_POS, true);
|
||||
device.closeTag();
|
||||
}
|
||||
}
|
||||
device.closeTag();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::reshiftPosition(const double offsetX, const double offsetY) {
|
||||
myPosition.add(offsetX, offsetY, 0);
|
||||
for (NBPTPlatform& platformCand : myPlatformCands) {
|
||||
platformCand.reshiftPosition(offsetX, offsetY);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
SVCPermissions
|
||||
NBPTStop::getPermissions() const {
|
||||
return myPermissions;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::addPlatformCand(NBPTPlatform platform) {
|
||||
myPlatformCands.push_back(platform);
|
||||
}
|
||||
|
||||
|
||||
const std::vector<NBPTPlatform>&
|
||||
NBPTStop::getPlatformCands() {
|
||||
return myPlatformCands;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBPTStop::getIsMultipleStopPositions() const {
|
||||
return myIsMultipleStopPositions;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::setIsMultipleStopPositions(bool multipleStopPositions) {
|
||||
myIsMultipleStopPositions = multipleStopPositions;
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBPTStop::getLength() const {
|
||||
return myPTStopLength;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBPTStop::setEdgeId(std::string edgeId, const NBEdgeCont& ec) {
|
||||
myEdgeId = edgeId;
|
||||
return findLaneAndComputeBusStopExtent(ec);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::registerAdditionalEdge(std::string wayId, std::string edgeId) {
|
||||
myAdditionalEdgeCandidates[wayId] = edgeId;
|
||||
}
|
||||
|
||||
|
||||
const std::map<std::string, std::string>&
|
||||
NBPTStop::getMyAdditionalEdgeCandidates() const {
|
||||
return myAdditionalEdgeCandidates;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::setMyOrigEdgeId(const std::string& myOrigEdgeId) {
|
||||
NBPTStop::myOrigEdgeId = myOrigEdgeId;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::setMyPTStopLength(double myPTStopLength) {
|
||||
NBPTStop::myPTStopLength = myPTStopLength;
|
||||
}
|
||||
|
||||
bool
|
||||
NBPTStop::findLaneAndComputeBusStopExtent(const NBEdgeCont& ec) {
|
||||
NBEdge* edge = ec.getByID(myEdgeId);
|
||||
return findLaneAndComputeBusStopExtent(edge);
|
||||
}
|
||||
|
||||
bool
|
||||
NBPTStop::findLaneAndComputeBusStopExtent(const NBEdge* edge) {
|
||||
if (edge != nullptr) {
|
||||
myEdgeId = edge->getID();
|
||||
int laneNr = -1;
|
||||
for (const auto& it : edge->getLanes()) {
|
||||
if ((it.permissions & getPermissions()) == getPermissions()) {
|
||||
++laneNr;
|
||||
break;
|
||||
}
|
||||
laneNr++;
|
||||
}
|
||||
if (laneNr != -1) {
|
||||
myLaneId = edge->getLaneID(laneNr);
|
||||
const PositionVector& shape = edge->getLaneShape(laneNr);
|
||||
double offset = shape.nearest_offset_to_point2D(getPosition(), false);
|
||||
offset = offset * edge->getLoadedLength() / edge->getLength();
|
||||
computeExtent(offset, edge->getLoadedLength());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return myEdgeId == ""; // loose stop. Try later when processing lines
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStop::setMyPTStopId(std::string id) {
|
||||
myPTStopId = id;
|
||||
}
|
||||
|
||||
void
|
||||
NBPTStop::clearAccess() {
|
||||
myAccesses.clear();
|
||||
}
|
||||
|
||||
void
|
||||
NBPTStop::addAccess(std::string laneID, double offset, double length) {
|
||||
const std::string newEdgeID = SUMOXMLDefinitions::getEdgeIDFromLane(laneID);
|
||||
// avoid duplicate access
|
||||
for (auto it = myAccesses.begin(); it != myAccesses.end();) {
|
||||
if (SUMOXMLDefinitions::getEdgeIDFromLane(std::get<0>(*it)) == newEdgeID) {
|
||||
it = myAccesses.erase(it);
|
||||
} else {
|
||||
it++;
|
||||
}
|
||||
}
|
||||
myAccesses.push_back(std::make_tuple(laneID, offset, length));
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,146 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTStop.h
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// The representation of a single pt stop
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <utils/geom/Position.h>
|
||||
#include "utils/common/SUMOVehicleClass.h"
|
||||
#include "NBPTPlatform.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OutputDevice;
|
||||
class NBEdgeCont;
|
||||
class NBEdge;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBPTStop
|
||||
* @brief The representation of a single pt stop
|
||||
*/
|
||||
class NBPTStop {
|
||||
|
||||
public:
|
||||
/**@brief Constructor
|
||||
* @param[in] id The id of the pt stop
|
||||
* @param[in] position The position of the pt stop
|
||||
* @param[in] edgeId The edge id of the pt stop
|
||||
* @param[in] length The length of the pt stop
|
||||
*/
|
||||
NBPTStop(std::string ptStopId, Position position, std::string edgeId, std::string origEdgeId, double length, std::string name,
|
||||
SVCPermissions svcPermissions, double parkingLength = 0);
|
||||
std::string getID() const;
|
||||
|
||||
const std::string getEdgeId() const;
|
||||
const std::string getOrigEdgeId() const;
|
||||
const std::string getName() const;
|
||||
const Position& getPosition() const;
|
||||
SVCPermissions getPermissions() const;
|
||||
void write(OutputDevice& device);
|
||||
void reshiftPosition(const double offsetX, const double offsetY);
|
||||
|
||||
const std::vector<NBPTPlatform>& getPlatformCands();
|
||||
bool getIsMultipleStopPositions() const;
|
||||
void setIsMultipleStopPositions(bool multipleStopPositions);
|
||||
double getLength() const;
|
||||
bool setEdgeId(std::string edgeId, const NBEdgeCont& ec);
|
||||
void registerAdditionalEdge(std::string wayId, std::string edgeId);
|
||||
void addPlatformCand(NBPTPlatform platform);
|
||||
bool findLaneAndComputeBusStopExtent(const NBEdgeCont& ec);
|
||||
|
||||
bool findLaneAndComputeBusStopExtent(const NBEdge* edge);
|
||||
|
||||
void setMyPTStopId(std::string id);
|
||||
void addAccess(std::string laneID, double offset, double length);
|
||||
|
||||
/// @brief remove all access definitions
|
||||
void clearAccess();
|
||||
|
||||
/// @brief register line that services this stop (for displaying)
|
||||
void addLine(const std::string& line);
|
||||
|
||||
void setBidiStop(NBPTStop* bidiStop) {
|
||||
myBidiStop = bidiStop;
|
||||
}
|
||||
|
||||
NBPTStop* getBidiStop() const {
|
||||
return myBidiStop;
|
||||
}
|
||||
|
||||
bool isLoose() const {
|
||||
return myIsLoose;
|
||||
}
|
||||
|
||||
/// @brief mirror coordinates along the x-axis
|
||||
void mirrorX();
|
||||
|
||||
private:
|
||||
void computeExtent(double center, double d);
|
||||
|
||||
private:
|
||||
std::string myPTStopId;
|
||||
Position myPosition;
|
||||
std::string myEdgeId;
|
||||
std::map<std::string, std::string> myAdditionalEdgeCandidates;
|
||||
public:
|
||||
const std::map<std::string, std::string>& getMyAdditionalEdgeCandidates() const;
|
||||
private:
|
||||
std::string myOrigEdgeId;
|
||||
public:
|
||||
void setMyOrigEdgeId(const std::string& myOrigEdgeId);
|
||||
private:
|
||||
double myPTStopLength;
|
||||
public:
|
||||
void setMyPTStopLength(double myPTStopLength);
|
||||
private:
|
||||
const std::string myName;
|
||||
const double myParkingLength;
|
||||
std::string myLaneId;
|
||||
const SVCPermissions myPermissions;
|
||||
|
||||
double myStartPos;
|
||||
double myEndPos;
|
||||
|
||||
/// @brief laneId, lanePos, accessLength
|
||||
std::vector<std::tuple<std::string, double, double>> myAccesses;
|
||||
|
||||
/// @brief list of public transport lines (for displaying)
|
||||
std::vector<std::string> myLines;
|
||||
|
||||
NBPTStop* myBidiStop;
|
||||
|
||||
/// @brief whether the stop was not part of the road network and must be mapped
|
||||
bool myIsLoose;
|
||||
|
||||
private:
|
||||
/// @brief Invalidated assignment operator.
|
||||
NBPTStop& operator=(const NBPTStop&);
|
||||
|
||||
|
||||
std::vector<NBPTPlatform> myPlatformCands;
|
||||
bool myIsMultipleStopPositions;
|
||||
};
|
||||
|
|
@ -1,428 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTStopCont.cpp
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// Container for pt stops during the netbuilding process
|
||||
/****************************************************************************/
|
||||
|
||||
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include <utils/geom/Boundary.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <microsim/MSLane.h>
|
||||
#include "NBPTStopCont.h"
|
||||
#include "NBEdgeCont.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBNode.h"
|
||||
#include <utils/geom/Position.h>
|
||||
|
||||
|
||||
NBPTStopCont::~NBPTStopCont() {
|
||||
for (auto& myPTStop : myPTStops) {
|
||||
delete myPTStop.second;
|
||||
}
|
||||
myPTStops.clear();
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NBPTStopCont::insert(NBPTStop* ptStop) {
|
||||
std::string id = ptStop->getID();
|
||||
auto i = myPTStops.find(id);
|
||||
if (i != myPTStops.end()) {
|
||||
return false;
|
||||
}
|
||||
myPTStops[id] = ptStop;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
NBPTStop*
|
||||
NBPTStopCont::get(std::string id) {
|
||||
if (myPTStops.find(id) != myPTStops.end()) {
|
||||
return myPTStops.find(id)->second;
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStopCont::localizePTStops(NBEdgeCont& cont) {
|
||||
std::vector<NBPTStop*> reverseStops;
|
||||
//first pass localize pt stop at correct side of the street; create stop for opposite side if needed
|
||||
for (auto& myPTStop : myPTStops) {
|
||||
|
||||
NBPTStop* stop = myPTStop.second;
|
||||
|
||||
bool multipleStopPositions = stop->getIsMultipleStopPositions();
|
||||
bool platformsDefined = !stop->getPlatformCands().empty();
|
||||
if (!platformsDefined) {
|
||||
//create pt stop for reverse edge if edge exists
|
||||
NBPTStop* reverseStop = getReverseStop(stop, cont);
|
||||
if (reverseStop != nullptr) {
|
||||
reverseStops.push_back(reverseStop);
|
||||
}
|
||||
} else if (multipleStopPositions) {
|
||||
//create pt stop for closest platform at corresponding edge
|
||||
assignPTStopToEdgeOfClosestPlatform(stop, cont);
|
||||
|
||||
} else {
|
||||
//create pt stop for each side of the street where a platform is defined (create additional pt stop as needed)
|
||||
NBPTStop* additionalStop = assignAndCreatNewPTStopAsNeeded(stop, cont);
|
||||
if (additionalStop != nullptr) {
|
||||
reverseStops.push_back(additionalStop);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//insrt new stops if any
|
||||
for (auto& reverseStop : reverseStops) {
|
||||
insert(reverseStop);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void NBPTStopCont::assignLanes(NBEdgeCont& cont) {
|
||||
//scnd pass set correct lane
|
||||
for (auto i = myPTStops.begin(); i != myPTStops.end();) {
|
||||
NBPTStop* stop = i->second;
|
||||
|
||||
if (!stop->findLaneAndComputeBusStopExtent(cont)) {
|
||||
WRITE_WARNING("Could not find corresponding edge or compatible lane for pt stop '" + i->first
|
||||
+ "' (" + i->second->getName() + "). Thus, it will be removed!");
|
||||
EdgeVector edgeVector = cont.getGeneratedFrom((*i).second->getOrigEdgeId());
|
||||
//std::cout << edgeVector.size() << std::endl;
|
||||
myPTStops.erase(i++);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBPTStopCont::generateBidiStops(NBEdgeCont& ec) {
|
||||
//scnd pass set correct lane
|
||||
std::vector<NBPTStop*> toAdd;
|
||||
for (auto i = myPTStops.begin(); i != myPTStops.end(); i++) {
|
||||
NBPTStop* stop = i->second;
|
||||
NBEdge* edge = ec.getByID(stop->getEdgeId());
|
||||
if (edge != nullptr && edge->isBidiRail()) {
|
||||
NBEdge* bidiEdge = edge->getTurnDestination(true);
|
||||
assert(bidiEdge != 0);
|
||||
const std::string id = getReverseID(stop->getID());
|
||||
if (myPTStops.count(id) > 0) {
|
||||
if (myPTStops[id]->getEdgeId() != bidiEdge->getID()) {
|
||||
WRITE_WARNING("Could not create reverse-direction stop for superposed edge '" + bidiEdge->getID()
|
||||
+ "' (origStop '" + i->first + "'). Stop id '" + id
|
||||
+ "' already in use by stop on edge '" + myPTStops[id]->getEdgeId() + "'.");
|
||||
}
|
||||
continue;
|
||||
}
|
||||
NBPTStop* bidiStop = new NBPTStop(id,
|
||||
stop->getPosition(),
|
||||
bidiEdge->getID(),
|
||||
stop->getOrigEdgeId(),
|
||||
stop->getLength(),
|
||||
stop->getName(),
|
||||
stop->getPermissions());
|
||||
if (bidiStop->findLaneAndComputeBusStopExtent(ec)) {
|
||||
toAdd.push_back(bidiStop);
|
||||
stop->setBidiStop(bidiStop);
|
||||
bidiStop->setBidiStop(stop);
|
||||
} else {
|
||||
// should not happen
|
||||
assert(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (NBPTStop* newStop : toAdd) {
|
||||
myPTStops[newStop->getID()] = newStop;
|
||||
}
|
||||
if (toAdd.size() > 0) {
|
||||
WRITE_MESSAGE("Added " + toString(toAdd.size()) + " stops for superposed rail edges.");
|
||||
}
|
||||
return (int)toAdd.size();
|
||||
}
|
||||
|
||||
|
||||
NBPTStop*
|
||||
NBPTStopCont::getReverseStop(NBPTStop* pStop, NBEdgeCont& cont) {
|
||||
std::string edgeId = pStop->getEdgeId();
|
||||
NBEdge* edge = cont.getByID(edgeId);
|
||||
NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
|
||||
if (reverse != nullptr) {
|
||||
const std::string reverseID = getReverseID(pStop->getID());
|
||||
if (myPTStops.count(reverseID) == 0) {
|
||||
return new NBPTStop(reverseID, pStop->getPosition(), reverse->getID(), reverse->getID(),
|
||||
pStop->getLength(), pStop->getName(), pStop->getPermissions());
|
||||
} else {
|
||||
return myPTStops[reverseID];
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
NBPTStop*
|
||||
NBPTStopCont::assignAndCreatNewPTStopAsNeeded(NBPTStop* pStop, NBEdgeCont& cont) {
|
||||
std::string edgeId = pStop->getEdgeId();
|
||||
NBEdge* edge = cont.getByID(edgeId);
|
||||
bool rightOfEdge = false;
|
||||
bool leftOfEdge = false;
|
||||
const NBPTPlatform* left = nullptr;
|
||||
for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
|
||||
double crossProd = computeCrossProductEdgePosition(edge, platform.getPos());
|
||||
//TODO consider driving on the left!!! [GL May '17]
|
||||
if (crossProd > 0) {
|
||||
leftOfEdge = true;
|
||||
left = &platform;
|
||||
} else {
|
||||
rightOfEdge = true;
|
||||
pStop->setMyPTStopLength(platform.getLength());
|
||||
}
|
||||
}
|
||||
|
||||
if (leftOfEdge && rightOfEdge) {
|
||||
NBPTStop* leftStop = getReverseStop(pStop, cont);
|
||||
leftStop->setMyPTStopLength(left->getLength());
|
||||
return leftStop;
|
||||
} else if (leftOfEdge) {
|
||||
NBEdge* reverse = getReverseEdge(edge);
|
||||
if (reverse != nullptr) {
|
||||
pStop->setEdgeId(reverse->getID(), cont);
|
||||
pStop->setMyPTStopLength(left->getLength());
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStopCont::assignPTStopToEdgeOfClosestPlatform(NBPTStop* pStop, NBEdgeCont& cont) {
|
||||
std::string edgeId = pStop->getEdgeId();
|
||||
NBEdge* edge = cont.getByID(edgeId);
|
||||
NBEdge* reverse = NBPTStopCont::getReverseEdge(edge);
|
||||
const NBPTPlatform* closestPlatform = getClosestPlatformToPTStopPosition(pStop);
|
||||
pStop->setMyPTStopLength(closestPlatform->getLength());
|
||||
if (reverse != nullptr) {
|
||||
|
||||
//TODO make isLeft in PositionVector static [GL May '17]
|
||||
// if (PositionVector::isLeft(edge->getFromNode()->getPosition(),edge->getToNode()->getPosition(),closestPlatform)){
|
||||
//
|
||||
// }
|
||||
double crossProd = computeCrossProductEdgePosition(edge, closestPlatform->getPos());
|
||||
|
||||
//TODO consider driving on the left!!! [GL May '17]
|
||||
if (crossProd > 0) { //pt stop is on the left of the orig edge
|
||||
pStop->setEdgeId(reverse->getID(), cont);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
double
|
||||
NBPTStopCont::computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const {
|
||||
PositionVector geom = edge->getGeometry();
|
||||
int idxTmp = geom.indexOfClosest(closestPlatform);
|
||||
double offset = geom.nearest_offset_to_point2D(closestPlatform, true);
|
||||
double offset2 = geom.offsetAtIndex2D(idxTmp);
|
||||
int idx1, idx2;
|
||||
if (offset2 < offset) {
|
||||
idx1 = idxTmp;
|
||||
idx2 = idx1 + 1;
|
||||
} else {
|
||||
idx2 = idxTmp;
|
||||
idx1 = idxTmp - 1;
|
||||
}
|
||||
if (idx1 < 0 || idx1 >= (int) geom.size() || idx2 < 0 || idx2 >= (int) geom.size()) {
|
||||
WRITE_WARNING("Could not determine cross product");
|
||||
return 0;
|
||||
}
|
||||
Position p1 = geom[idx1];
|
||||
Position p2 = geom[idx2];
|
||||
|
||||
double x0 = p1.x();
|
||||
double y0 = p1.y();
|
||||
double x1 = p2.x();
|
||||
double y1 = p2.y();
|
||||
double x2 = closestPlatform.x();
|
||||
double y2 = closestPlatform.y();
|
||||
double crossProd = (x1 - x0) * (y2 - y0) - (y1 - y0) * (x2 - x0);
|
||||
return crossProd;
|
||||
}
|
||||
|
||||
|
||||
const NBPTPlatform*
|
||||
NBPTStopCont::getClosestPlatformToPTStopPosition(NBPTStop* pStop) {
|
||||
Position stopPosition = pStop->getPosition();
|
||||
const NBPTPlatform* closest = nullptr;
|
||||
double minSqrDist = std::numeric_limits<double>::max();
|
||||
for (const NBPTPlatform& platform : pStop->getPlatformCands()) {
|
||||
double sqrDist = stopPosition.distanceSquaredTo2D(platform.getPos());
|
||||
if (sqrDist < minSqrDist) {
|
||||
minSqrDist = sqrDist;
|
||||
closest = &platform;
|
||||
}
|
||||
}
|
||||
return closest;
|
||||
}
|
||||
|
||||
//static functions
|
||||
|
||||
NBEdge*
|
||||
NBPTStopCont::getReverseEdge(NBEdge* edge) {
|
||||
if (edge != nullptr) {
|
||||
for (auto it = edge->getToNode()->getOutgoingEdges().begin();
|
||||
it != edge->getToNode()->getOutgoingEdges().end();
|
||||
it++) {
|
||||
if ((*it)->getToNode() == edge->getFromNode()) {
|
||||
return (*it);
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
int
|
||||
NBPTStopCont::cleanupDeleted(NBEdgeCont& cont) {
|
||||
int numDeleted = 0;
|
||||
for (auto i = myPTStops.begin(); i != myPTStops.end();) {
|
||||
if (cont.getByID((*i).second->getEdgeId()) == nullptr) {
|
||||
WRITE_WARNING("Removing pt stop:" + (*i).first + " on non existing edge: " + (*i).second->getEdgeId());
|
||||
myPTStops.erase(i++);
|
||||
numDeleted++;
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return numDeleted;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStopCont::addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into) {
|
||||
if (oc.isSet("ptstop-output")) {
|
||||
for (auto stop : myPTStops) {
|
||||
into.insert(stop.second->getEdgeId());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStopCont::postprocess(std::set<std::string>& usedStops) {
|
||||
for (auto i = myPTStops.begin(); i != myPTStops.end();) {
|
||||
if (usedStops.find(i->second->getID()) == usedStops.end()) {
|
||||
myPTStops.erase(i++);
|
||||
} else {
|
||||
i++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string
|
||||
NBPTStopCont::getReverseID(const std::string& id) {
|
||||
return id.size() > 0 && id[0] == '-' ? id.substr(1) : "-" + id;
|
||||
}
|
||||
|
||||
void
|
||||
NBPTStopCont::alignIdSigns() {
|
||||
PTStopsCont stops = myPTStops;
|
||||
for (auto& i : stops) {
|
||||
const std::string& stopId = i.second->getID();
|
||||
if (i.second->getEdgeId() == "") {
|
||||
continue;
|
||||
}
|
||||
const char edgeSign = i.second->getEdgeId().at(0);
|
||||
const char stopSign = stopId.at(0);
|
||||
if (edgeSign != stopSign && (edgeSign == '-' || stopSign == '-')) {
|
||||
i.second->setMyPTStopId(getReverseID(stopId));
|
||||
myPTStops.erase(stopId);
|
||||
myPTStops[i.second->getID()] = i.second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBPTStopCont::findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor) {
|
||||
NamedRTree r;
|
||||
for (auto edge : cont) {
|
||||
const Boundary& bound = edge.second->getGeometry().getBoxBoundary();
|
||||
float min[2] = { static_cast<float>(bound.xmin()), static_cast<float>(bound.ymin()) };
|
||||
float max[2] = { static_cast<float>(bound.xmax()), static_cast<float>(bound.ymax()) };
|
||||
r.Insert(min, max, edge.second);
|
||||
}
|
||||
for (auto& ptStop : myPTStops) {
|
||||
const std::string& stopEdgeID = ptStop.second->getEdgeId();
|
||||
NBEdge* stopEdge = cont.getByID(stopEdgeID);
|
||||
//std::cout << "findAccessEdgesForRailStops edge=" << stopEdgeID << " exists=" << (stopEdge != 0) << "\n";
|
||||
if (stopEdge != nullptr && (stopEdge->getPermissions() & SVC_PEDESTRIAN) == 0) {
|
||||
//if (stopEdge != 0 && isRailway(stopEdge->getPermissions())) {
|
||||
std::set<const Named*> edges;
|
||||
Named::StoringVisitor visitor(edges);
|
||||
const Position& pos = ptStop.second->getPosition();
|
||||
float min[2] = {static_cast<float>(pos.x() - maxRadius), static_cast<float>(pos.y() - maxRadius)};
|
||||
float max[2] = {static_cast<float>(pos.x() + maxRadius), static_cast<float>(pos.y() + maxRadius)};
|
||||
r.Search(min, max, visitor);
|
||||
std::vector<NBEdge*> edgCants;
|
||||
for (const Named* namedEdge : edges) {
|
||||
NBEdge* e = const_cast<NBEdge*>(dynamic_cast<const NBEdge*>(namedEdge));
|
||||
edgCants.push_back(e);
|
||||
}
|
||||
std::sort(edgCants.begin(), edgCants.end(), [pos](NBEdge * a, NBEdge * b) {
|
||||
return a->getLaneShape(0).distance2D(pos, false) < b->getLaneShape(0).distance2D(pos, false);
|
||||
});
|
||||
int cnt = 0;
|
||||
for (auto edge : edgCants) {
|
||||
int laneIdx = 0;
|
||||
for (auto lane : edge->getLanes()) {
|
||||
if ((lane.permissions & SVC_PEDESTRIAN) != 0) {
|
||||
double offset = lane.shape.nearest_offset_to_point2D(pos, false);
|
||||
double finalLength = edge->getFinalLength();
|
||||
double laneLength = lane.shape.length();
|
||||
double accessLength = pos.distanceTo2D(lane.shape.positionAtOffset2D(offset)) * accessFactor;
|
||||
ptStop.second->addAccess(edge->getLaneID(laneIdx), offset * finalLength / laneLength, accessLength);
|
||||
cnt++;
|
||||
break;
|
||||
}
|
||||
laneIdx++;
|
||||
}
|
||||
if (cnt == maxCount) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
NBPTStop*
|
||||
NBPTStopCont::findStop(const std::string& origEdgeID, Position pos, double threshold) const {
|
||||
for (auto& item : myPTStops) {
|
||||
if (item.second->getOrigEdgeId() == origEdgeID &&
|
||||
item.second->getPosition().distanceTo2D(pos) < threshold) {
|
||||
return item.second;
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
/****************************************************************************/
|
|
@ -1,114 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBPTStopCont.h
|
||||
/// @author Gregor Laemmel
|
||||
/// @date Tue, 20 Mar 2017
|
||||
///
|
||||
// Container for pt stops during the netbuilding process
|
||||
/****************************************************************************/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "NBPTStop.h"
|
||||
|
||||
class NBEdge;
|
||||
class NBEdgeCont;
|
||||
|
||||
class NBPTStopCont {
|
||||
|
||||
public:
|
||||
|
||||
~NBPTStopCont();
|
||||
|
||||
/** @brief Inserts a node into the map
|
||||
* @param[in] stop The pt stop to insert
|
||||
* @return Whether the pt stop could be added
|
||||
*/
|
||||
bool insert(NBPTStop* ptStop);
|
||||
|
||||
/// @brief Retrieve a previously inserted pt stop
|
||||
NBPTStop* get(std::string id);
|
||||
|
||||
/// @brief Returns the number of pt stops stored in this container
|
||||
int size() const {
|
||||
return (int) myPTStops.size();
|
||||
}
|
||||
|
||||
/** @brief Returns the pointer to the begin of the stored pt stops
|
||||
* @return The iterator to the beginning of stored pt stops
|
||||
*/
|
||||
std::map<std::string, NBPTStop*>::const_iterator begin() const {
|
||||
return myPTStops.begin();
|
||||
}
|
||||
|
||||
/** @brief Returns the pointer to the end of the stored pt stops
|
||||
* @return The iterator to the end of stored pt stops
|
||||
*/
|
||||
std::map<std::string, NBPTStop*>::const_iterator end() const {
|
||||
return myPTStops.end();
|
||||
}
|
||||
|
||||
const std::map<std::string, NBPTStop*>& getStops() const {
|
||||
return myPTStops;
|
||||
}
|
||||
|
||||
|
||||
/** @brief remove stops on non existing (removed) edges
|
||||
*
|
||||
* @param cont
|
||||
*/
|
||||
int cleanupDeleted(NBEdgeCont& cont);
|
||||
|
||||
void assignLanes(NBEdgeCont& cont);
|
||||
|
||||
/// @brief duplicate stops for superposed rail edges and return the number of generated stops
|
||||
int generateBidiStops(NBEdgeCont& cont);
|
||||
|
||||
void localizePTStops(NBEdgeCont& cont);
|
||||
|
||||
void findAccessEdgesForRailStops(NBEdgeCont& cont, double maxRadius, int maxCount, double accessFactor);
|
||||
|
||||
void postprocess(std::set<std::string>& usedStops);
|
||||
|
||||
/// @brief add edges that must be kept
|
||||
void addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into);
|
||||
|
||||
NBPTStop* findStop(const std::string& origEdgeID, Position pos, double threshold = 1) const;
|
||||
|
||||
private:
|
||||
/// @brief Definition of the map of names to pt stops
|
||||
typedef std::map<std::string, NBPTStop*> PTStopsCont;
|
||||
|
||||
/// @brief The map of names to pt stops
|
||||
PTStopsCont myPTStops;
|
||||
|
||||
NBPTStop* getReverseStop(NBPTStop* pStop, NBEdgeCont& cont);
|
||||
|
||||
|
||||
void assignPTStopToEdgeOfClosestPlatform(NBPTStop* pStop, NBEdgeCont& cont);
|
||||
const NBPTPlatform* getClosestPlatformToPTStopPosition(NBPTStop* pStop);
|
||||
NBPTStop* assignAndCreatNewPTStopAsNeeded(NBPTStop* pStop, NBEdgeCont& cont);
|
||||
double computeCrossProductEdgePosition(const NBEdge* edge, const Position& closestPlatform) const;
|
||||
|
||||
static std::string getReverseID(const std::string& id);
|
||||
|
||||
public:
|
||||
static NBEdge* getReverseEdge(NBEdge* edge);
|
||||
|
||||
|
||||
void alignIdSigns();
|
||||
};
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBParking.cpp
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Tue, 14 Nov 2017
|
||||
///
|
||||
// The representation of an imported parking area
|
||||
/****************************************************************************/
|
||||
#include <config.h>
|
||||
|
||||
#include <utils/iodevices/OutputDevice.h>
|
||||
#include <utils/options/OptionsCont.h>
|
||||
#include <utils/common/MsgHandler.h>
|
||||
#include "NBParking.h"
|
||||
#include "NBEdge.h"
|
||||
#include "NBEdgeCont.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// method definitions
|
||||
// ===========================================================================
|
||||
NBParking::NBParking(const std::string& id, const std::string& edgeID, const std::string& name) :
|
||||
Named(id),
|
||||
myEdgeID(edgeID),
|
||||
myName(name) {
|
||||
}
|
||||
|
||||
void
|
||||
NBParking::write(OutputDevice& device, NBEdgeCont& ec) const {
|
||||
const NBEdge* e = ec.retrieve(myEdgeID);
|
||||
if (e != nullptr) {
|
||||
if ((e->getPermissions() & SVC_PASSENGER) == 0) {
|
||||
WRITE_WARNINGF("Ignoring parking area on edge '%' due to invalid permissions.", e->getID());
|
||||
return;
|
||||
}
|
||||
// keep minimum distance of 5m to junction corners
|
||||
const int cornerDistance = 5;
|
||||
int capacity = (int)((e->getFinalLength() - 2 * cornerDistance) / 7.5);
|
||||
if (capacity <= 0) {
|
||||
WRITE_WARNINGF("Ignoring parking area on edge '%' due to insufficient space.", e->getID());
|
||||
return;
|
||||
}
|
||||
int lane = 0;
|
||||
for (; lane < e->getNumLanes(); ++lane) {
|
||||
if ((e->getPermissions(lane) & SVC_PASSENGER) != 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
device.openTag(SUMO_TAG_PARKING_AREA);
|
||||
device.writeAttr(SUMO_ATTR_ID, getID());
|
||||
device.writeAttr(SUMO_ATTR_LANE, e->getLaneID(lane));
|
||||
device.writeAttr(SUMO_ATTR_STARTPOS, cornerDistance);
|
||||
device.writeAttr(SUMO_ATTR_ENDPOS, -cornerDistance);
|
||||
device.writeAttr(SUMO_ATTR_ROADSIDE_CAPACITY, capacity);
|
||||
if (!myName.empty()) {
|
||||
device.writeAttr(SUMO_ATTR_NAME, myName);
|
||||
}
|
||||
device.closeTag();
|
||||
} else {
|
||||
WRITE_WARNINGF("could not find edge for parkingArea '%s'", getID());
|
||||
}
|
||||
// XXX else: prevent edge merging via --geometry.remove
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NBParkingCont::addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into) {
|
||||
if (oc.isSet("parking-output")) {
|
||||
for (NBParking& p : *this) {
|
||||
into.insert(p.getEdgeID());
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,71 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBParking.h
|
||||
/// @author Jakob Erdmann
|
||||
/// @date Tue, 14 Nov 2017
|
||||
///
|
||||
// The representation of an imported parking area
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include "utils/common/Named.h"
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class OutputDevice;
|
||||
class NBEdgeCont;
|
||||
class OptionsCont;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBParking
|
||||
* @brief The representation of a single pt stop
|
||||
*/
|
||||
class NBParking : public Named {
|
||||
|
||||
public:
|
||||
/**@brief Constructor
|
||||
* @param[in] id The id of the pt stop
|
||||
* @param[in] position The position of the pt stop
|
||||
* @param[in] edgeId The edge id of the pt stop
|
||||
* @param[in] length The length of the pt stop
|
||||
*/
|
||||
NBParking(const std::string& id, const std::string& edgeID, const std::string& name = "");
|
||||
|
||||
void write(OutputDevice& device, NBEdgeCont& ec) const;
|
||||
|
||||
const std::string getEdgeID() const {
|
||||
return myEdgeID;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string myEdgeID;
|
||||
std::string myName;
|
||||
|
||||
};
|
||||
|
||||
class NBParkingCont : public std::vector<NBParking> {
|
||||
|
||||
public:
|
||||
/// @brief add edges that must be kept
|
||||
void addEdges2Keep(const OptionsCont& oc, std::set<std::string>& into);
|
||||
};
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -1,279 +0,0 @@
|
|||
/****************************************************************************/
|
||||
// Eclipse SUMO, Simulation of Urban MObility; see https://eclipse.org/sumo
|
||||
// Copyright (C) 2001-2020 German Aerospace Center (DLR) and others.
|
||||
// This program and the accompanying materials are made available under the
|
||||
// terms of the Eclipse Public License 2.0 which is available at
|
||||
// https://www.eclipse.org/legal/epl-2.0/
|
||||
// This Source Code may also be made available under the following Secondary
|
||||
// Licenses when the conditions for such availability set forth in the Eclipse
|
||||
// Public License 2.0 are satisfied: GNU General Public License, version 2
|
||||
// or later which is available at
|
||||
// https://www.gnu.org/licenses/old-licenses/gpl-2.0-standalone.html
|
||||
// SPDX-License-Identifier: EPL-2.0 OR GPL-2.0-or-later
|
||||
/****************************************************************************/
|
||||
/// @file NBRequest.h
|
||||
/// @author Daniel Krajzewicz
|
||||
/// @author Jakob Erdmann
|
||||
/// @author Sascha Krieg
|
||||
/// @author Michael Behrisch
|
||||
/// @date Tue, 20 Nov 2001
|
||||
///
|
||||
// This class computes the logic of a junction
|
||||
/****************************************************************************/
|
||||
#pragma once
|
||||
#include <config.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <map>
|
||||
#include <bitset>
|
||||
#include "NBConnectionDefs.h"
|
||||
#include "NBContHelper.h"
|
||||
#include <utils/common/UtilExceptions.h>
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class declarations
|
||||
// ===========================================================================
|
||||
class NBEdge;
|
||||
class NBJunctionTypeIO;
|
||||
class NBTrafficLightLogic;
|
||||
class OptionsCont;
|
||||
class NBTrafficLightDefinition;
|
||||
class NBEdgeCont;
|
||||
class OutputDevice;
|
||||
|
||||
|
||||
// ===========================================================================
|
||||
// class definitions
|
||||
// ===========================================================================
|
||||
/**
|
||||
* @class NBRequest
|
||||
* Given a special node, this class builds the logic of this (junction)
|
||||
* regarding the relationships between the incoming and outgoing edges and
|
||||
* their priorities. The junction's logic is saved when it does not yet exist.
|
||||
*/
|
||||
class NBRequest {
|
||||
public:
|
||||
/** constructor
|
||||
The parameter are the logic's lists of edges (all, incoming only and
|
||||
outgoing only edges). By now no further informations are needed to
|
||||
describe the junctions. These parameter must not be changed during the
|
||||
logic's building */
|
||||
NBRequest(const NBEdgeCont& ec,
|
||||
NBNode* junction,
|
||||
const EdgeVector& all,
|
||||
const EdgeVector& incoming,
|
||||
const EdgeVector& outgoing,
|
||||
const NBConnectionProhibits& loadedProhibits);
|
||||
|
||||
/// @brief destructor
|
||||
~NBRequest();
|
||||
|
||||
/// @brief builds the bitset-representation of the logic
|
||||
void buildBitfieldLogic();
|
||||
|
||||
/// @brief @brief returns the number of the junction's lanes and the number of the junction's links in respect. @note: only connected lanes are counted
|
||||
std::pair<int, int> getSizes() const;
|
||||
|
||||
/** @brief Returns the information whether "prohibited" flow must let "prohibitor" flow pass
|
||||
* @param[in] possProhibitorFrom The maybe prohibiting connection's begin
|
||||
* @param[in] possProhibitorTo The maybe prohibiting connection's end
|
||||
* @param[in] possProhibitedFrom The maybe prohibited connection's begin
|
||||
* @param[in] possProhibitedTo The maybe prohibited connection's end
|
||||
* @return Whether the first flow prohibits the second one
|
||||
*/
|
||||
bool mustBrake(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
|
||||
const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo) const;
|
||||
|
||||
|
||||
/** @brief Returns the information whether the described flow must let any other flow pass
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] to The connection's end edge
|
||||
* @param[in] fromLane The connection starting lane
|
||||
* @param[in] includePedCrossings Whether braking due to a pedestrian crossing counts
|
||||
* @return Whether the described connection must brake (has higher priorised foes)
|
||||
*/
|
||||
bool mustBrake(const NBEdge* const from, const NBEdge* const to, int fromLane, int toLane, bool includePedCrossings) const;
|
||||
|
||||
/** @brief Returns the information whether the described flow must brake for the given crossing
|
||||
* @param[in] node The parent node of this request
|
||||
* @param[in] from The connection's start edge
|
||||
* @param[in] to The connection's end edge
|
||||
* @param[in] crossing The pedestrian crossing to check
|
||||
* @return Whether the described connection must brake (has higher priorised foes)
|
||||
*/
|
||||
static bool mustBrakeForCrossing(const NBNode* node, const NBEdge* const from, const NBEdge* const to, const NBNode::Crossing& crossing);
|
||||
|
||||
/** @brief Returns the information whether the given flows cross
|
||||
* @param[in] from1 The starting edge of the first stream
|
||||
* @param[in] to1 The ending edge of the first stream
|
||||
* @param[in] from2 The starting edge of the second stream
|
||||
* @param[in] to2 The ending edge of the second stream
|
||||
* @return Whether both stream are foes (cross)
|
||||
*/
|
||||
bool foes(const NBEdge* const from1, const NBEdge* const to1,
|
||||
const NBEdge* const from2, const NBEdge* const to2) const;
|
||||
|
||||
|
||||
/** @brief Returns the information whether "prohibited" flow must let "prohibitor" flow pass
|
||||
* @param[in] possProhibitorFrom The maybe prohibiting connection's begin
|
||||
* @param[in] possProhibitorTo The maybe prohibiting connection's end
|
||||
* @param[in] possProhibitedFrom The maybe prohibited connection's begin
|
||||
* @param[in] possProhibitedTo The maybe prohibited connection's end
|
||||
* @param[in] regardNonSignalisedLowerPriority Whether the right of way rules without traffic lights shall be regarded
|
||||
* @return Whether the first flow prohibits the second one
|
||||
*/
|
||||
bool forbids(const NBEdge* const possProhibitorFrom, const NBEdge* const possProhibitorTo,
|
||||
const NBEdge* const possProhibitedFrom, const NBEdge* const possProhibitedTo,
|
||||
bool regardNonSignalisedLowerPriority) const;
|
||||
|
||||
/// @brief writes the XML-representation of the logic as a bitset-logic XML representation
|
||||
void computeLogic(const bool checkLaneFoes);
|
||||
|
||||
void writeLogic(OutputDevice& into) const;
|
||||
|
||||
const std::string& getFoes(int linkIndex) const;
|
||||
const std::string& getResponse(int linkIndex) const;
|
||||
|
||||
/// @brief prints the request
|
||||
friend std::ostream& operator<<(std::ostream& os, const NBRequest& r);
|
||||
|
||||
/// @brief reports warnings if any occurred
|
||||
static void reportWarnings();
|
||||
|
||||
/// @brief whether the given connections crosses the foe connection from the same lane and must yield
|
||||
bool rightTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
|
||||
const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const;
|
||||
|
||||
/// @brief whether multple connections from the same edge target the same lane
|
||||
bool mergeConflict(const NBEdge* from, const NBEdge::Connection& con,
|
||||
const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const;
|
||||
|
||||
/// @brief whether opposite left turns intersect
|
||||
bool oppositeLeftTurnConflict(const NBEdge* from, const NBEdge::Connection& con,
|
||||
const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon, bool foes) const;
|
||||
|
||||
|
||||
/// @brief whether there are conflicting streams of traffic at this node
|
||||
bool hasConflict() const;
|
||||
|
||||
private:
|
||||
/** sets the information that the edge from1->to1 blocks the edge
|
||||
from2->to2 (is higher priorised than this) */
|
||||
void setBlocking(NBEdge* from1, NBEdge* to1, NBEdge* from2, NBEdge* to2);
|
||||
|
||||
/** @brief computes the response of a certain lane
|
||||
Returns the next link index within the junction */
|
||||
int computeLaneResponse(NBEdge* from, int lane, int pos, const bool checkLaneFoes);
|
||||
|
||||
/** @brief computes the response of a certain crossing
|
||||
Returns the next link index within the junction */
|
||||
int computeCrossingResponse(const NBNode::Crossing& crossing, int pos);
|
||||
|
||||
/** @brief Writes the response of a certain link
|
||||
*
|
||||
* For the link (described by the connected edges and lanes), the response in dependence
|
||||
* to all other links of this junction is computed. Herefor, the method
|
||||
* goes through all links of this junction and writes a '0' if the link
|
||||
* is not blocked by the currently investigated one, or '1' if it is.
|
||||
*
|
||||
* In the case "mayDefinitelyPass" is true, the link will not be disturbed by
|
||||
* any other (special case for on-ramps).
|
||||
*
|
||||
* @param[in] tlIndex The tl index of the connection for which the responses shall be written
|
||||
* @param[in] from The link's starting edge
|
||||
* @param[in] to The link's destination edge
|
||||
* @param[in] fromLane The link's starting lane
|
||||
* @param[in] toLane The link's destination lane
|
||||
* @param[in] mayDefinitelyPass Whether this link is definitely not disturbed
|
||||
* @return the response string
|
||||
* @exception IOError not yet implemented
|
||||
*/
|
||||
std::string getResponseString(const NBEdge* const from, const NBEdge::Connection& c, const bool checkLaneFoes) const;
|
||||
|
||||
|
||||
/** writes which participating links are foes to the given */
|
||||
std::string getFoesString(NBEdge* from, NBEdge* to,
|
||||
int fromLane, int toLane, const bool checkLaneFoes) const;
|
||||
|
||||
|
||||
/** @brief Returns the index to the internal combination container for the given edge combination
|
||||
*
|
||||
* If one of the edges is not known, -1 is returned.
|
||||
*
|
||||
* @param[in] from The starting edge (incoming to this logic)
|
||||
* @param[in] to The destination edge (outgoing from this logic)
|
||||
* @return The index within the internal container
|
||||
*/
|
||||
int getIndex(const NBEdge* const from, const NBEdge* const to) const;
|
||||
|
||||
|
||||
/// @brief returns the distance between the incoming (from) and the outgoing (to) edge clockwise in edges
|
||||
int distanceCounterClockwise(NBEdge* from, NBEdge* to);
|
||||
|
||||
/// @brief computes the relationships between links outgoing right of the given link */
|
||||
void computeRightOutgoingLinkCrossings(NBEdge* from, NBEdge* to);
|
||||
|
||||
/// @brief computes the relationships between links outgoing left of the given link
|
||||
void computeLeftOutgoingLinkCrossings(NBEdge* from, NBEdge* to);
|
||||
|
||||
|
||||
void resetSignalised();
|
||||
|
||||
/// @brief reset foes it the number of lanes matches (or exceeds) the number of incoming connections for an edge
|
||||
void resetCooperating();
|
||||
|
||||
/// @brief whether the given connections must be checked for lane conflicts due to the vClasses involved
|
||||
bool checkLaneFoesByClass(const NBEdge::Connection& con,
|
||||
const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const;
|
||||
|
||||
/// @brief whether the given connections must be checked for lane conflicts due to disjunct target lanes
|
||||
bool checkLaneFoesByCooperation(const NBEdge* from, const NBEdge::Connection& con,
|
||||
const NBEdge* prohibitorFrom, const NBEdge::Connection& prohibitorCon) const;
|
||||
|
||||
/** @brief return whether the given laneToLane connections prohibit each other
|
||||
* under the assumption that the edge2edge connections are in conflict
|
||||
*/
|
||||
bool laneConflict(const NBEdge* from, const NBEdge* to, int toLane, const NBEdge* prohibitorFrom, const NBEdge* prohibitorTo, int prohibitorToLane) const;
|
||||
|
||||
|
||||
/// @brief return to total number of edge-to-edge connections of this request-logic
|
||||
inline int numLinks() const;
|
||||
|
||||
private:
|
||||
/// @brief the node the request is assigned to
|
||||
NBNode* myJunction;
|
||||
|
||||
/// @brief all (icoming and outgoing) of the junctions edges
|
||||
const EdgeVector& myAll;
|
||||
|
||||
/// @brief edges incoming to the junction
|
||||
const EdgeVector& myIncoming;
|
||||
|
||||
/// @brief edges outgoing from the junction
|
||||
const EdgeVector& myOutgoing;
|
||||
|
||||
/// @brief definition of a container to store boolean informations about a link into
|
||||
typedef std::vector<bool> LinkInfoCont;
|
||||
|
||||
/// @brief definition of a container for link(edge->edge) X link(edge->edge) combinations (size = |myIncoming|*|myOutgoing|)
|
||||
typedef std::vector<LinkInfoCont> CombinationsCont;
|
||||
|
||||
/// @brief the link X link blockings
|
||||
CombinationsCont myForbids;
|
||||
|
||||
/// @brief the link X link is done-checks
|
||||
CombinationsCont myDone;
|
||||
|
||||
/// @brief precomputed right-of-way matrices for each lane-to-lane link
|
||||
std::vector<std::string> myFoes;
|
||||
std::vector<std::string> myResponse;
|
||||
std::vector<bool> myHaveVia;
|
||||
|
||||
private:
|
||||
static int myGoodBuilds, myNotBuild;
|
||||
|
||||
/// @brief Invalidated assignment operator
|
||||
NBRequest& operator=(const NBRequest& s) = delete;
|
||||
};
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue