Moved OSM2ODR to a different repo

This commit is contained in:
Axel 2021-03-15 11:07:03 +01:00 committed by bernat
parent f6b85cb48a
commit be76107b44
544 changed files with 26 additions and 127086 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -1 +0,0 @@
bin

View File

@ -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>

View File

@ -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}")

View File

@ -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": []
}
]
}

View File

@ -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.

View File

@ -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'

View File

@ -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 ()

View File

@ -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)

View File

@ -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

View File

@ -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

View File

@ -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))

View File

@ -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

View File

@ -1,2 +0,0 @@
add_subdirectory(tcpip)
add_subdirectory(eulerspiral)

View File

@ -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")

View File

@ -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.

View File

@ -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;
}

View File

@ -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 );

View File

@ -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;
}
}
};

View File

@ -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

View File

@ -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;
};

View File

@ -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 ()

View File

@ -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: $
*-----------------------------------------------------------------------*/

View File

@ -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:$
*-----------------------------------------------------------------------*/

View File

@ -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: $
*-----------------------------------------------------------------------*/

View File

@ -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: $
*-----------------------------------------------------------------------*/

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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;
};
}

View File

@ -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

View File

@ -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;
};
}

View File

@ -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

View File

@ -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;
};

View File

@ -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);
};

View File

@ -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);
};

View File

@ -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
};

View File

@ -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&);
};

View File

@ -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")

View File

@ -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());
}
/****************************************************************************/

View File

@ -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

View File

@ -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);
};

View File

@ -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);
}
/****************************************************************************/

View File

@ -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);
};

View File

@ -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;
};

View File

@ -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;
}
/****************************************************************************/

View File

@ -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;
};

View File

@ -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;

View File

@ -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;

View File

@ -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;
}
/****************************************************************************/

View File

@ -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;
};
};

View File

@ -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;
}
/****************************************************************************/

View File

@ -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);
};

View File

@ -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);
}
}
/****************************************************************************/

View File

@ -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

View File

@ -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);
};

View File

@ -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;
}
/****************************************************************************/

View File

@ -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();
};

View File

@ -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);
}
/****************************************************************************/

View File

@ -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;
}

View File

@ -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 + "'.");
}
}
/****************************************************************************/

View File

@ -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);
};

View File

@ -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;

View File

@ -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);
}
}
}
}
/****************************************************************************/

View File

@ -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);
};
};

View File

@ -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;
}
}
/****************************************************************************/

View File

@ -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;
};

View File

@ -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");
}
/****************************************************************************/

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -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));
}
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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));
}
/****************************************************************************/

View File

@ -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;
};

View File

@ -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;
}
/****************************************************************************/

View File

@ -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();
};

View File

@ -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());
}
}
}

View File

@ -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

View File

@ -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