Compare commits

...

17 Commits

Author SHA1 Message Date
Patrick Niklaus
9f625d2446
Update changelog 2016-07-31 23:03:17 +02:00
Michael Krasnyk
0c6cca1ca4
Fix #2706 by using correct fallback u-turn
Regression is due to a combination of 08248e3853
and http://www.openstreetmap.org/changeset/40938983
where in ways http://www.openstreetmap.org/way/27292481
and http://www.openstreetmap.org/way/432488408
nodes
4315134884 (part of way 432488408)
4315134891 (part of way 432488408)
4315134886 (part of way 432488408)
form a u-turn that has index 0 after sorting and used as an allowed one
with a reversed edge.
A u-turn that corresponds to the condition uturn_could_be_valid == true has index 1
and ignored.
2016-07-31 12:05:40 +02:00
Patrick Niklaus
9224158835
Update changelog and bump to 5.2.7 2016-07-20 17:14:15 +02:00
Michael Krasnyk
3414519cb8
Fix ambiguity in edge weights by using minimal weight 2016-07-20 17:00:48 +02:00
Moritz Kobitzsch
16cee3a7d3
fix 2672 2016-07-20 16:59:39 +02:00
Patrick Niklaus
3ef936217f
[skip ci] Fix OSRM version 2016-06-24 17:17:34 +02:00
Patrick Niklaus
5bcd00a778
Add changelog entry for current bug fix 2016-06-24 16:32:28 +02:00
Moritz Kobitzsch
a6828010ec
fix invalid circle centers 2016-06-24 16:31:21 +02:00
Daniel Patterson
17adeeecf5 Fix segfault when route includes very short segments. 2016-06-22 14:55:20 -07:00
Patrick Niklaus
edafb0a83c
[skip ci] Add breaking notice to changelog 2016-06-21 19:49:13 +02:00
Patrick Niklaus
f7cc89400a
Update the v5.2.4 changelog 2016-06-21 19:47:39 +02:00
Lauren Budorick
473e4e129c
Update tests to catch 0-subtraction error 2016-06-21 19:41:01 +02:00
Patrick Niklaus
2ac497c6b8
Fix fromTop and fromLeft calculation 2016-06-21 19:40:50 +02:00
Michael Krasnyk
defdc8cc4b
Fix omitting the last point's coordinates in the geometry field 2016-06-21 18:23:29 +02:00
Moritz Kobitzsch
4c5314676a
fix issues with roundabouts and intersections and sliproads 2016-06-21 18:23:06 +02:00
Moritz Kobitzsch
1da044f3e3 fix roundabout-handling when name changes 2016-06-17 11:19:27 -07:00
Patrick Niklaus
45516ef534 Enable travis builds for 5.2 branch 2016-06-14 14:36:41 +02:00
26 changed files with 332 additions and 97 deletions

View File

@ -13,6 +13,7 @@ notifications:
branches: branches:
only: only:
- master - master
- "5.2"
cache: cache:
ccache: true ccache: true

View File

@ -1,3 +1,33 @@
# 5.2.8
- Bugfixes:
- Handle an edge case that cause the turn instruction code to segfault during osrm-extract on Egypt.
# 5.2.7
- Bugfixes
- BREAKING: Fix bug that could result in failure to load 'osrm.icd' files. This breaks the dataformat
- Fix deduplication of parallel edges. Now uses correct weight.
# 5.2.6
- Bugfixes
- Fix numeric overflow in roundabout center calculation which throws an exception
# 5.2.5
- Bugfixes
- Fixes a segfault caused by incorrect trimming logic for very short steps.
# 5.2.4
Changes from 5.2.3:
- Bugfixes:
- Fixed a crash that arised on roundabouts in combination with intermediate intersections and sliproads
- Fixed #2518: Invalid bilinear interpolation when using raster data
- Fixed #2546: The geometry returned by the match service was missing the last coordinate.
BREAKING: The data format changed between 5.2.3 and 5.2.4, you need to reprocess.
# 5.2.3
- Bugfixes:
- Fixed an issue with name changes in roundabouts that could result in crashes
# 5.2.2 # 5.2.2
Changes from 5.2.1 Changes from 5.2.1
- Bugfixes: - Bugfixes:

View File

@ -10,7 +10,7 @@ endif()
project(OSRM C CXX) project(OSRM C CXX)
set(OSRM_VERSION_MAJOR 5) set(OSRM_VERSION_MAJOR 5)
set(OSRM_VERSION_MINOR 2) set(OSRM_VERSION_MINOR 2)
set(OSRM_VERSION_PATCH 0) set(OSRM_VERSION_PATCH 7)
# these two functions build up custom variables: # these two functions build up custom variables:
# OSRM_INCLUDE_PATHS and OSRM_DEFINES # OSRM_INCLUDE_PATHS and OSRM_DEFINES

View File

@ -144,10 +144,10 @@ Feature: Intersections Data
| hd | | | hd | |
When I route I should get When I route I should get
| waypoints | route | turns | intersections | | waypoints | route | turns | intersections |
| e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 | | e,f | ea,fb,fb | depart,abcda-exit-1,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:90 |
| e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0| | e,g | ea,gc,gc | depart,abcda-exit-2,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
| e,h | ea,hd,hd | depart,abcda-exit-3,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 | | e,h | ea,hd,hd | depart,abcda-exit-3,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270,true:30 true:180 false:330,true:90 false:210 true:330;true:270 |
| e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1| | e,2 | ea,abcda,abcda | depart,abcda-exit-undefined,arrive | true:180;false:0 false:150 true:210,false:30 true:150 true:270;true:327 +-1 |
| 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:0| | 1,g | abcda,gc,gc | depart,abcda-exit-2,arrive | true:214;false:30 true:150 true:270,true:30 true:180 false:330;true:0 |
| 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214| | 1,3 | abcda,abcda | depart,arrive | true:214,false:30 true:150 true:270,true:30 true:180 false:330;true:214 |

View File

@ -361,3 +361,79 @@ Feature: Basic Roundabout
| a,f | ab,ef,ef | depart,roundabout-exit-2,arrive | 0->180,180->270,180->0 | | a,f | ab,ef,ef | depart,roundabout-exit-2,arrive | 0->180,180->270,180->0 |
| a,h | ab,gh,gh | depart,roundabout-exit-1,arrive | 0->180,180->270,270->0 | | a,h | ab,gh,gh | depart,roundabout-exit-1,arrive | 0->180,180->270,270->0 |
Scenario: Motorway Roundabout
#See 39.933742 -75.082345
Given the node map
| | | | | l | | | | a | | i |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | | | | | b | | | | |
| | | | c | | | | | | | |
| | | | | | | | | | | |
| | | | | | | | | h | | |
| n | | | | | | | | | | |
| | | | | | | | | | | |
| | | d | | | | | | | | j |
| | | | | | | | | | | |
| | | | | m | | | g | | | |
| | | | | | | | | | | |
| | | | | | | | | | | |
| | | e | | f | | | | | | |
And the ways
| nodes | junction | name | highway | oneway | ref |
| ab | | crescent | trunk | yes | US 130 |
| bcd | roundabout | crescent | trunk | yes | US 130 |
| de | | crescent | trunk | yes | US 130 |
| fg | | crescent | trunk | yes | US 130 |
| gh | roundabout | crescent | trunk | yes | US 130 |
| hi | | crescent | trunk | yes | US 130 |
| jh | | | trunk_link | yes | NJ 38 |
| hb | roundabout | | trunk_link | yes | NJ 38 |
| bl | | | trunk_link | yes | NJ 38 |
| cnd | | kaighns | trunk_link | yes | |
| dmg | roundabout | | trunk_link | yes | |
When I route I should get
| waypoints | route | turns |
| a,e | crescent (US 130),crescent (US 130),crescent (US 130) | depart,roundabout-exit-3,arrive |
| j,l | NJ 38,NJ 38,NJ 38 | depart,roundabout-exit-2,arrive |
Scenario: Double Roundabout with through-lane
#http://map.project-osrm.org/?z=18&center=38.911752%2C-77.048667&loc=38.912003%2C-77.050831&loc=38.909277%2C-77.042516&hl=en&alt=0
Given the node map
| | | | | o | | | | | | | | | | | | n | | | | |
| | | | | e | | | | | | | | | | | | j | | | | |
| | | | | | | | | | | | | | | | | | | | | |
| | | | | | | q | | | | | | | | | | | | | | |
| a | | b | | | | | | s | | f | | | | g | | | | i | | k |
| | | | | | | r | | | | | | | | | | | p | | | |
| | | | | | | | | | | t | | | | | | | | | | |
| | | | | c | | d | | | | | | | | | | h | | | | |
| | | | | l | | | | | | | | | | | | m | | | | |
And the nodes
| node | highway |
| i | traffic_signals |
And the ways
| nodes | junction | name | oneway |
| bcdrqeb | roundabout | sheridan circle | yes |
| ghi | roundabout | dupont circle | yes |
| ijg | roundabout | dupont circle | yes |
| ab | | massachusetts | no |
| sfgpik | | massachusetts | no |
| cl | | 23rd street | no |
| oe | | r street | no |
| jn | | new hampshire | no |
| mh | | new hampshire | yes |
| rsq | | massachusetts | yes |
| ft | | suppressed | no |
And the relations
| type | way:from | way:to | node:via | restriction |
| restriction | sfgpik | ijg | i | no_left_turn |
When I route I should get
| waypoints | route | turns |
| a,k | massachusetts,massachusetts,massachusetts,massachusetts | depart,sheridan circle-exit-2,dupont circle-exit-1,arrive |

View File

@ -17,7 +17,7 @@ module.exports = function () {
this.setContractArgs(args, callback); this.setContractArgs(args, callback);
}); });
this.Given(/^a grid size of (\d+) meters$/, (meters, callback) => { this.Given(/^a grid size of ([0-9.]+) meters$/, (meters, callback) => {
this.setGridSize(meters); this.setGridSize(meters);
callback(); callback();
}); });

View File

@ -1,5 +1,6 @@
var util = require('util'); var util = require('util');
var d3 = require('d3-queue'); var d3 = require('d3-queue');
var polyline = require('polyline');
module.exports = function () { module.exports = function () {
this.When(/^I match I should get$/, (table, callback) => { this.When(/^I match I should get$/, (table, callback) => {
@ -35,6 +36,7 @@ module.exports = function () {
route = '', route = '',
duration = '', duration = '',
annotation = '', annotation = '',
geometry = '',
OSMIDs = ''; OSMIDs = '';
@ -63,6 +65,11 @@ module.exports = function () {
annotation = this.annotationList(json.matchings[0]); annotation = this.annotationList(json.matchings[0]);
} }
if (headers.has('geometry')) {
if (json.matchings.length != 1) throw new Error('*** Checking geometry only supported for matchings with one subtrace');
geometry = json.matchings[0].geometry;
}
if (headers.has('OSM IDs')) { if (headers.has('OSM IDs')) {
if (json.matchings.length != 1) throw new Error('*** CHecking annotation only supported for matchings with one subtrace'); if (json.matchings.length != 1) throw new Error('*** CHecking annotation only supported for matchings with one subtrace');
OSMIDs = this.OSMIDList(json.matchings[0]); OSMIDs = this.OSMIDList(json.matchings[0]);
@ -85,6 +92,13 @@ module.exports = function () {
got.annotation = annotation.toString(); got.annotation = annotation.toString();
} }
if (headers.has('geometry')) {
if (this.queryParams['geometries'] === 'polyline')
got.geometry = polyline.decode(geometry).toString();
else
got.geometry = geometry;
}
if (headers.has('OSM IDs')) { if (headers.has('OSM IDs')) {
got['OSM IDs'] = OSMIDs; got['OSM IDs'] = OSMIDs;
} }

View File

@ -251,3 +251,18 @@ Feature: Basic Routing
| from | to | route | | from | to | route |
| d | c | de,ce,ce | | d | c | de,ce,ce |
| e | d | de,de | | e | d | de,de |
Scenario: Ambiguous edge weights - Use minimal edge weight
Given the node map
| a | b |
And the ways
| nodes | highway | name |
| ab | tertiary | |
| ab | primary | |
| ab | secondary | |
When I route I should get
| from | to | route | time |
| a | b | , | 10s |
| b | a | , | 10s |

View File

@ -24,3 +24,18 @@ Feature: Fixed bugs, kept to check for regressions
When I route I should get When I route I should get
| from | to | route | | from | to | route |
| x | y | abc,abc | | x | y | abc,abc |
Scenario: Step trimming with very short segments
Given a grid size of 0.1 meters
Given the node map
| a | 1 | b | c | d | 2 | e |
Given the ways
| nodes | oneway |
| ab | yes |
| bcd | yes |
| de | yes |
When I route I should get
| from | to | route |
| 1 | 2 | bcd,bcd |

View File

@ -128,3 +128,21 @@ Feature: Basic Map Matching
| trace | matchings | OSM IDs | | trace | matchings | OSM IDs |
| abeh | abcedgh | 1,2,3,2,3,4,5,4,5,6,7 | | abeh | abcedgh | 1,2,3,2,3,4,5,4,5,6,7 |
| abci | abc,ci | 1,2,3,2,3,8,3,8 | | abci | abc,ci | 1,2,3,2,3,8,3,8 |
Scenario: Testbot - Geometry details
Given the query options
| overview | full |
| geometries | polyline |
Given the node map
| a | b | c |
| | d | |
And the ways
| nodes | oneway |
| abc | no |
| bd | no |
When I match I should get
| trace | matchings | geometry |
| abd | abd | 1,1,1,1.00009,1,1.00009,0.99991,1.00009 |

View File

@ -330,7 +330,7 @@ class InternalDataFacade final : public BaseDataFacade
std::vector<util::guidance::BearingClass> bearing_classes; std::vector<util::guidance::BearingClass> bearing_classes;
// and the actual bearing values // and the actual bearing values
std::uint64_t num_bearings; std::uint64_t num_bearings;
intersection_stream >> num_bearings; intersection_stream.read(reinterpret_cast<char*>(&num_bearings),sizeof(num_bearings));
m_bearing_values_table.resize(num_bearings); m_bearing_values_table.resize(num_bearings);
intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]), intersection_stream.read(reinterpret_cast<char *>(&m_bearing_values_table[0]),
sizeof(m_bearing_values_table[0]) * num_bearings); sizeof(m_bearing_values_table[0]) * num_bearings);

View File

@ -405,10 +405,10 @@ inline bool requiresNameAnnounced(const std::string &from,
(from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos); (from_ref.find(to_ref) != std::string::npos || to_ref.find(from_ref) != std::string::npos);
const auto ref_is_removed = !from_ref.empty() && to_ref.empty(); const auto ref_is_removed = !from_ref.empty() && to_ref.empty();
const auto obvious_change = (names_are_empty && refs_are_empty) || const auto obvious_change =
(names_are_equal && ref_is_contained) || (names_are_empty && refs_are_empty) || (names_are_equal && ref_is_contained) ||
(names_are_equal && refs_are_empty) || name_is_removed || (names_are_equal && refs_are_empty) || (ref_is_contained && name_is_removed) ||
ref_is_removed || is_suffix_change; (names_are_equal && ref_is_removed) || is_suffix_change;
return !obvious_change; return !obvious_change;
} }
@ -456,6 +456,26 @@ inline ConnectedRoad mirror(ConnectedRoad road)
return road; return road;
} }
inline bool hasRoundaboutType(const TurnInstruction instruction)
{
using namespace extractor::guidance::TurnType;
const constexpr TurnType::Enum valid_types[] = {TurnType::EnterRoundabout,
TurnType::EnterAndExitRoundabout,
TurnType::EnterRotary,
TurnType::EnterAndExitRotary,
TurnType::EnterRoundaboutIntersection,
TurnType::EnterAndExitRoundaboutIntersection,
TurnType::EnterRoundaboutAtExit,
TurnType::ExitRoundabout,
TurnType::EnterRotaryAtExit,
TurnType::ExitRotary,
TurnType::EnterRoundaboutIntersectionAtExit,
TurnType::ExitRoundaboutIntersection,
TurnType::StayOnRoundabout};
const auto valid_end = valid_types + 13;
return std::find(valid_types, valid_end, instruction.type) != valid_end;
};
} // namespace guidance } // namespace guidance
} // namespace extractor } // namespace extractor
} // namespace osrm } // namespace osrm

View File

@ -62,6 +62,13 @@ class EntryClass
friend std::size_t std::hash<EntryClass>::operator()(const EntryClass &) const; friend std::size_t std::hash<EntryClass>::operator()(const EntryClass &) const;
}; };
#if not defined __GNUC__ or __GNUC__ > 4
static_assert(std::is_trivially_copyable<EntryClass>::value,
"Class is serialized trivially in "
"the datafacades. Bytewise writing "
"requires trivially copyable type");
#endif
} // namespace guidance } // namespace guidance
} // namespace utilr } // namespace utilr
} // namespace osrm } // namespace osrm

View File

@ -9,7 +9,8 @@
"node-timeout": "0.0.4", "node-timeout": "0.0.4",
"request": "^2.69.0", "request": "^2.69.0",
"xmlbuilder": "^4.2.1", "xmlbuilder": "^4.2.1",
"chalk": "^1.1.3" "chalk": "^1.1.3",
"polyline": "^0.2.0"
}, },
"bin": { "bin": {
"cucumber": "./node_modules/cucumber/bin/cucumber.js" "cucumber": "./node_modules/cucumber/bin/cucumber.js"

View File

@ -85,12 +85,12 @@ std::vector<util::Coordinate> assembleOverview(const std::vector<LegGeometry> &l
std::vector<util::Coordinate> overview_geometry; std::vector<util::Coordinate> overview_geometry;
overview_geometry.reserve(overview_size); overview_geometry.reserve(overview_size);
auto leg_index = 0UL; auto leg_reverse_index = leg_geometries.size();
for (const auto &geometry : leg_geometries) for (const auto &geometry : leg_geometries)
{ {
auto begin = geometry.locations.begin(); auto begin = geometry.locations.begin();
auto end = geometry.locations.end(); auto end = geometry.locations.end();
if (leg_index < leg_geometries.size() - 1) if (--leg_reverse_index > 0)
{ {
end = std::prev(end); end = std::prev(end);
} }

View File

@ -154,7 +154,7 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source)
// Overwrites turn instruction and increases exit NR // Overwrites turn instruction and increases exit NR
destination.duration += source.duration; destination.duration += source.duration;
destination.distance += source.distance; destination.distance += source.distance;
destination.maneuver.exit = source.maneuver.exit;
if (destination.geometry_begin < source.geometry_begin) if (destination.geometry_begin < source.geometry_begin)
{ {
destination.intersections.insert(destination.intersections.end(), destination.intersections.insert(destination.intersections.end(),
@ -170,8 +170,6 @@ RouteStep forwardInto(RouteStep destination, const RouteStep &source)
destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin); destination.geometry_begin = std::min(destination.geometry_begin, source.geometry_begin);
destination.geometry_end = std::max(destination.geometry_end, source.geometry_end); destination.geometry_end = std::max(destination.geometry_end, source.geometry_end);
destination.maneuver.exit = destination.intersections.size() - 1;
return destination; return destination;
} }
@ -184,7 +182,6 @@ void fixFinalRoundabout(std::vector<RouteStep> &steps)
if (entersRoundabout(propagation_step.maneuver.instruction)) if (entersRoundabout(propagation_step.maneuver.instruction))
{ {
propagation_step.maneuver.exit = 0; propagation_step.maneuver.exit = 0;
propagation_step.geometry_end = steps.back().geometry_begin;
// remember the current name as rotary name in tha case we end in a rotary // remember the current name as rotary name in tha case we end in a rotary
if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary || if (propagation_step.maneuver.instruction.type == TurnType::EnterRotary ||
@ -265,9 +262,16 @@ void closeOffRoundabout(const bool on_roundabout,
// instruction and move it right to the beginning to make sure to immediately announce the // instruction and move it right to the beginning to make sure to immediately announce the
// exit. // exit.
BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) || BOOST_ASSERT(leavesRoundabout(steps[1].maneuver.instruction) ||
steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout); steps[1].maneuver.instruction.type == TurnType::StayOnRoundabout ||
steps[1].maneuver.instruction.type == TurnType::Suppressed ||
steps[1].maneuver.instruction.type == TurnType::NoTurn);
steps[0].geometry_end = 1; steps[0].geometry_end = 1;
steps[1].geometry_begin = 0;
steps[1] = forwardInto(steps[1], steps[0]); steps[1] = forwardInto(steps[1], steps[0]);
steps[1].intersections.erase(steps[1].intersections.begin()); // otherwise we copy the
// source
if (leavesRoundabout(steps[1].maneuver.instruction))
steps[1].maneuver.exit = 1;
steps[0].duration = 0; steps[0].duration = 0;
steps[0].distance = 0; steps[0].distance = 0;
const auto exitToEnter = [](const TurnType::Enum type) { const auto exitToEnter = [](const TurnType::Enum type) {
@ -305,7 +309,6 @@ void closeOffRoundabout(const bool on_roundabout,
if (entersRoundabout(propagation_step.maneuver.instruction)) if (entersRoundabout(propagation_step.maneuver.instruction))
{ {
propagation_step.maneuver.exit = step.maneuver.exit; propagation_step.maneuver.exit = step.maneuver.exit;
propagation_step.geometry_end = step.geometry_end;
const auto entry_intersection = propagation_step.intersections.front(); const auto entry_intersection = propagation_step.intersections.front();
// remember rotary name // remember rotary name
@ -335,8 +338,10 @@ void closeOffRoundabout(const bool on_roundabout,
} }
else else
{ {
BOOST_ASSERT(propagation_step.maneuver.instruction.type = BOOST_ASSERT(propagation_step.maneuver.instruction.type ==
TurnType::StayOnRoundabout); TurnType::StayOnRoundabout ||
propagation_step.maneuver.instruction.type == TurnType::Suppressed ||
propagation_step.maneuver.instruction.type == TurnType::NoTurn);
propagation_step.maneuver.instruction = propagation_step.maneuver.instruction =
TurnInstruction::NO_TURN(); // mark intermediate instructions invalid TurnInstruction::NO_TURN(); // mark intermediate instructions invalid
} }
@ -473,7 +478,6 @@ void collapseTurnAt(std::vector<RouteStep> &steps,
current_step.intersections.front() current_step.intersections.front()
.bearings[current_step.intersections.front().out]) && .bearings[current_step.intersections.front().out]) &&
compatible(one_back_step, current_step)) compatible(one_back_step, current_step))
{ {
BOOST_ASSERT(two_back_index < steps.size()); BOOST_ASSERT(two_back_index < steps.size());
// the simple case is a u-turn that changes directly into the in-name again // the simple case is a u-turn that changes directly into the in-name again
@ -584,12 +588,10 @@ std::vector<RouteStep> postProcess(std::vector<RouteStep> steps)
} }
else if (leavesRoundabout(instruction)) else if (leavesRoundabout(instruction))
{ {
if (!has_entered_roundabout) // if (!has_entered_roundabout)
{ // in case the we are not on a roundabout, the very first instruction
// in case the we are not on a roundabout, the very first instruction // after the depart will be transformed into a roundabout and become
// after the depart will be transformed into a roundabout and become // the first valid instruction
// the first valid instruction
}
closeOffRoundabout(has_entered_roundabout, steps, step_index); closeOffRoundabout(has_entered_roundabout, steps, step_index);
has_entered_roundabout = false; has_entered_roundabout = false;
on_roundabout = false; on_roundabout = false;
@ -661,7 +663,7 @@ std::vector<RouteStep> collapseTurns(std::vector<RouteStep> steps)
for (std::size_t step_index = 1; step_index + 1 < steps.size(); ++step_index) for (std::size_t step_index = 1; step_index + 1 < steps.size(); ++step_index)
{ {
const auto &current_step = steps[step_index]; const auto &current_step = steps[step_index];
if( current_step.maneuver.instruction.type == TurnType::NoTurn ) if (current_step.maneuver.instruction.type == TurnType::NoTurn)
continue; continue;
const auto one_back_index = getPreviousIndex(step_index); const auto one_back_index = getPreviousIndex(step_index);
BOOST_ASSERT(one_back_index < steps.size()); BOOST_ASSERT(one_back_index < steps.size());
@ -926,13 +928,13 @@ void trimShortSegments(std::vector<RouteStep> &steps, LegGeometry &geometry)
auto &next_to_last_step = *(steps.end() - 2); auto &next_to_last_step = *(steps.end() - 2);
// in the end, the situation with the roundabout cannot occur. As a result, we can remove // in the end, the situation with the roundabout cannot occur. As a result, we can remove
// all zero-length instructions // all zero-length instructions
if (next_to_last_step.distance <= 1) if (next_to_last_step.distance <= 1 && steps.size() > 2)
{ {
geometry.locations.pop_back(); geometry.locations.pop_back();
geometry.annotations.pop_back(); geometry.annotations.pop_back();
geometry.osm_node_ids.pop_back(); geometry.osm_node_ids.pop_back();
geometry.segment_offsets.pop_back(); geometry.segment_offsets.pop_back();
BOOST_ASSERT(geometry.segment_distances.back() < 1); BOOST_ASSERT(geometry.segment_distances.back() <= 1);
geometry.segment_distances.pop_back(); geometry.segment_distances.pop_back();
next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive; next_to_last_step.maneuver.waypoint_type = WaypointType::Arrive;

View File

@ -417,11 +417,13 @@ void ExtractionContainers::PrepareEdges(lua_State *segment_state)
all_edges_list[i].result.weight < min_forward_weight) all_edges_list[i].result.weight < min_forward_weight)
{ {
min_forward_idx = i; min_forward_idx = i;
min_forward_weight = all_edges_list[i].result.weight;
} }
if (all_edges_list[i].result.backward && if (all_edges_list[i].result.backward &&
all_edges_list[i].result.weight < min_backward_weight) all_edges_list[i].result.weight < min_backward_weight)
{ {
min_backward_idx = i; min_backward_idx = i;
min_backward_weight = all_edges_list[i].result.weight;
} }
// this also increments the outer loop counter! // this also increments the outer loop counter!

View File

@ -661,7 +661,7 @@ void Extractor::WriteIntersectionClassificationData(
util::RangeTable<> bearing_class_range_table(bearing_counts); util::RangeTable<> bearing_class_range_table(bearing_counts);
file_out_stream << bearing_class_range_table; file_out_stream << bearing_class_range_table;
file_out_stream << total_bearings; file_out_stream.write(reinterpret_cast<const char *>(&total_bearings), sizeof(total_bearings));
for (const auto &bearing_class : bearing_classes) for (const auto &bearing_class : bearing_classes)
{ {
const auto &bearings = bearing_class.getAvailableBearings(); const auto &bearings = bearing_class.getAvailableBearings();
@ -669,17 +669,18 @@ void Extractor::WriteIntersectionClassificationData(
sizeof(bearings[0]) * bearings.size()); sizeof(bearings[0]) * bearings.size());
} }
// FIXME if (!static_cast<bool>(file_out_stream))
// This should be here, but g++4.8 does not have it... {
// static_assert(std::is_trivially_copyable<util::guidance::EntryClass>::value, throw util::exception("Failed to write to " + output_file_name + ".");
// "EntryClass Serialization requires trivial copyable entry classes"); }
util::serializeVector(file_out_stream, entry_classes); util::serializeVector(file_out_stream, entry_classes);
TIMER_STOP(write_edges); TIMER_STOP(write_edges);
util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for " util::SimpleLogger().Write() << "ok, after " << TIMER_SEC(write_edges) << "s for "
<< node_based_intersection_classes.size() << " Indices into " << node_based_intersection_classes.size() << " Indices into "
<< bearing_classes.size() << " bearing classes and " << bearing_classes.size() << " bearing classes and "
<< entry_classes.size() << " entry classes"; << entry_classes.size() << " entry classes and " << total_bearings
<< " bearing values." << std::endl;
} }
} }
} }

View File

@ -138,7 +138,20 @@ Intersection IntersectionGenerator::getConnectedRoads(const NodeID from_node,
const auto valid_count = const auto valid_count =
boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; }); boost::count_if(intersection, [](const ConnectedRoad &road) { return road.entry_allowed; });
if (0 == valid_count && uturn_could_be_valid) if (0 == valid_count && uturn_could_be_valid)
intersection[0].entry_allowed = true; {
// after intersections sorting by angles, find the u-turn with (from_node == to_node)
// that was inserted together with setting uturn_could_be_valid flag
std::size_t self_u_turn = 0;
while (self_u_turn < intersection.size()
&& intersection[self_u_turn].turn.angle < std::numeric_limits<double>::epsilon()
&& from_node != node_based_graph.GetTarget(intersection[self_u_turn].turn.eid))
{
++self_u_turn;
}
BOOST_ASSERT(from_node == node_based_graph.GetTarget(intersection[self_u_turn].turn.eid));
intersection[self_u_turn].entry_allowed = true;
}
return mergeSegregatedRoads(std::move(intersection)); return mergeSegregatedRoads(std::move(intersection));
} }

View File

@ -1,5 +1,5 @@
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/constants.hpp" #include "extractor/guidance/constants.hpp"
#include "extractor/guidance/roundabout_handler.hpp"
#include "extractor/guidance/toolkit.hpp" #include "extractor/guidance/toolkit.hpp"
#include "util/coordinate_calculation.hpp" #include "util/coordinate_calculation.hpp"
@ -210,11 +210,11 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
return util::Coordinate(node_info_list[node].lon, node_info_list[node].lat); return util::Coordinate(node_info_list[node].lon, node_info_list[node].lat);
}; };
unsigned roundabout_name_id = 0; std::unordered_set<unsigned> roundabout_name_ids;
std::unordered_set<unsigned> connected_names; std::unordered_set<unsigned> connected_names;
const auto getNextOnRoundabout = const auto getNextOnRoundabout =
[this, &roundabout_name_id, &connected_names](const NodeID node) { [this, &roundabout_name_ids, &connected_names](const NodeID node) {
EdgeID continue_edge = SPECIAL_EDGEID; EdgeID continue_edge = SPECIAL_EDGEID;
for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node)) for (const auto edge : node_based_graph.GetAdjacentEdgeRange(node))
{ {
@ -226,16 +226,24 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
// fork in roundabout // fork in roundabout
return SPECIAL_EDGEID; return SPECIAL_EDGEID;
} }
// roundabout does not keep its name
if (roundabout_name_id != 0 && roundabout_name_id != edge_data.name_id &&
requiresNameAnnounced(name_table.GetNameForID(roundabout_name_id),
name_table.GetNameForID(edge_data.name_id),
street_name_suffix_table))
{
return SPECIAL_EDGEID;
}
roundabout_name_id = edge_data.name_id; if (EMPTY_NAMEID != edge_data.name_id)
{
bool add = true;
for (auto name_id : roundabout_name_ids)
{
if (!requiresNameAnnounced(name_table.GetNameForID(name_id),
name_table.GetNameForID(edge_data.name_id),
street_name_suffix_table))
{
add = false;
break;
}
}
if (add)
roundabout_name_ids.insert(edge_data.name_id);
}
continue_edge = edge; continue_edge = edge;
} }
@ -320,7 +328,8 @@ RoundaboutType RoundaboutHandler::getRoundaboutType(const NodeID nid) const
// used with a reference and without. This will be fixed automatically // used with a reference and without. This will be fixed automatically
// when we handle references separately or if the useage is more consistent // when we handle references separately or if the useage is more consistent
if (0 != roundabout_name_id && 0 == connected_names.count(roundabout_name_id)) if (1 == roundabout_name_ids.size() &&
0 == connected_names.count(*roundabout_name_ids.begin()))
return RoundaboutType::Rotary; return RoundaboutType::Rotary;
else else
return RoundaboutType::Roundabout; return RoundaboutType::Roundabout;

View File

@ -1,3 +1,4 @@
#include "extractor/guidance/classification_data.hpp"
#include "extractor/guidance/constants.hpp" #include "extractor/guidance/constants.hpp"
#include "extractor/guidance/turn_analysis.hpp" #include "extractor/guidance/turn_analysis.hpp"
@ -123,14 +124,12 @@ TurnAnalysis::setTurnTypes(const NodeID from_nid, const EdgeID, Intersection int
Intersection TurnAnalysis::handleSliproads(const EdgeID source_edge_id, Intersection TurnAnalysis::handleSliproads(const EdgeID source_edge_id,
Intersection intersection) const Intersection intersection) const
{ {
auto intersection_node_id = node_based_graph.GetTarget(source_edge_id); auto intersection_node_id = node_based_graph.GetTarget(source_edge_id);
const auto linkTest = [this](const ConnectedRoad &road) { const auto linkTest = [this](const ConnectedRoad &road) {
return // isLinkClass( return !node_based_graph.GetEdgeData(road.turn.eid).roundabout && road.entry_allowed &&
// node_based_graph.GetEdgeData(road.turn.eid).road_classification.road_class) && angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <= 2 * NARROW_TURN_ANGLE &&
!node_based_graph.GetEdgeData(road.turn.eid).roundabout && road.entry_allowed && !hasRoundaboutType(road.turn.instruction);
angularDeviation(road.turn.angle, STRAIGHT_ANGLE) <= 2 * NARROW_TURN_ANGLE;
}; };
bool hasNarrow = bool hasNarrow =

View File

@ -54,7 +54,9 @@ RasterDatum RasterSource::GetRasterInterpolate(const int lon, const int lat) con
} }
const auto xthP = (lon - xmin) / xstep; const auto xthP = (lon - xmin) / xstep;
const auto ythP = (ymax - lat) / ystep; const auto ythP =
(ymax - lat) /
ystep; // the raster texture uses a different coordinate system with y pointing downwards
const std::size_t top = static_cast<std::size_t>(fmax(floor(ythP), 0)); const std::size_t top = static_cast<std::size_t>(fmax(floor(ythP), 0));
const std::size_t bottom = static_cast<std::size_t>(fmin(ceil(ythP), height - 1)); const std::size_t bottom = static_cast<std::size_t>(fmin(ceil(ythP), height - 1));
@ -62,8 +64,8 @@ RasterDatum RasterSource::GetRasterInterpolate(const int lon, const int lat) con
const std::size_t right = static_cast<std::size_t>(fmin(ceil(xthP), width - 1)); const std::size_t right = static_cast<std::size_t>(fmin(ceil(xthP), width - 1));
// Calculate distances from corners for bilinear interpolation // Calculate distances from corners for bilinear interpolation
const float fromLeft = (lon - left * xstep + xmin) / xstep; const float fromLeft = xthP - left; // this is the fraction part of xthP
const float fromTop = (ymax - top * ystep - lat) / ystep; const float fromTop = ythP - top; // this is the fraction part of ythP
const float fromRight = 1 - fromLeft; const float fromRight = 1 - fromLeft;
const float fromBottom = 1 - fromTop; const float fromBottom = 1 - fromTop;

View File

@ -360,7 +360,7 @@ int Storage::Run()
} }
std::uint64_t num_bearings; std::uint64_t num_bearings;
intersection_stream >> num_bearings; intersection_stream.read(reinterpret_cast<char*>(&num_bearings),sizeof(num_bearings));
std::vector<DiscreteBearing> bearing_class_table(num_bearings); std::vector<DiscreteBearing> bearing_class_table(num_bearings);
intersection_stream.read(reinterpret_cast<char *>(&bearing_class_table[0]), intersection_stream.read(reinterpret_cast<char *>(&bearing_class_table[0]),

View File

@ -258,7 +258,10 @@ circleCenter(const Coordinate C1, const Coordinate C2, const Coordinate C3)
C2C1_slope * (C2_x + C3_x)) / C2C1_slope * (C2_x + C3_x)) /
(2 * (C3C2_slope - C2C1_slope)); (2 * (C3C2_slope - C2C1_slope));
const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y); const double lat = (0.5 * (C1_x + C2_x) - lon) / C2C1_slope + 0.5 * (C1_y + C2_y);
return Coordinate(FloatLongitude(lon), FloatLatitude(lat)); if (lon < -180.0 || lon > 180.0 || lat < -90.0 || lat > 90.0)
return boost::none;
else
return Coordinate(FloatLongitude(lon), FloatLatitude(lat));
} }
} }

View File

@ -24,58 +24,58 @@ BOOST_AUTO_TEST_CASE(raster_test)
{ {
SourceContainer sources; SourceContainer sources;
int source_id = sources.LoadRasterSource( int source_id = sources.LoadRasterSource(
"../unit_tests/fixtures/raster_data.asc", 0, 0.09, 0, 0.09, 10, 10); "../unit_tests/fixtures/raster_data.asc", 1, 1.09, 1, 1.09, 10, 10);
BOOST_CHECK_EQUAL(source_id, 0); BOOST_CHECK_EQUAL(source_id, 0);
// Expected nearest-neighbor queries // Expected nearest-neighbor queries
// EDGES // EDGES
CHECK_QUERY(0, 0.00, 0.00, 10); CHECK_QUERY(0, 1.00, 1.00, 10);
CHECK_QUERY(0, 0.00, 0.09, 10); CHECK_QUERY(0, 1.00, 1.09, 10);
CHECK_QUERY(0, 0.09, 0.00, 40); CHECK_QUERY(0, 1.09, 1.00, 40);
CHECK_QUERY(0, 0.09, 0.09, 100); CHECK_QUERY(0, 1.09, 1.09, 100);
CHECK_QUERY(0, 0.09, 0.07, 140); CHECK_QUERY(0, 1.09, 1.07, 140);
// OUT OF BOUNDS // OUT OF BOUNDS
CHECK_QUERY(0, -0.1, 0.07, RasterDatum::get_invalid()); CHECK_QUERY(0, -1.1, 1.07, RasterDatum::get_invalid());
CHECK_QUERY(0, -0.1, -3.0, RasterDatum::get_invalid()); CHECK_QUERY(0, -1.1, -3.0, RasterDatum::get_invalid());
CHECK_QUERY(0, 0.3, 23.0, RasterDatum::get_invalid()); CHECK_QUERY(0, 1.3, 23.0, RasterDatum::get_invalid());
// ARBITRARY - AT DATA // ARBITRARY - AT DATA
CHECK_QUERY(0, 0.06, 0.06, 100); CHECK_QUERY(0, 1.06, 1.06, 100);
CHECK_QUERY(0, 0.08, 0.05, 160); CHECK_QUERY(0, 1.08, 1.05, 160);
CHECK_QUERY(0, 0.01, 0.05, 20); CHECK_QUERY(0, 1.01, 1.05, 20);
// ARBITRARY - BETWEEN DATA // ARBITRARY - BETWEEN DATA
CHECK_QUERY(0, 0.054, 0.023, 40); CHECK_QUERY(0, 1.054, 1.023, 40);
CHECK_QUERY(0, 0.056, 0.028, 80); CHECK_QUERY(0, 1.056, 1.028, 80);
CHECK_QUERY(0, 0.05, 0.028, 60); CHECK_QUERY(0, 1.05, 1.028, 60);
// Expected bilinear interpolation queries // Expected bilinear interpolation queries
// EDGES - same as above // EDGES - same as above
CHECK_INTERPOLATE(0, 0.00, 0.00, 10); CHECK_INTERPOLATE(0, 1.00, 1.00, 10);
CHECK_INTERPOLATE(0, 0.00, 0.09, 10); CHECK_INTERPOLATE(0, 1.00, 1.09, 10);
CHECK_INTERPOLATE(0, 0.09, 0.00, 40); CHECK_INTERPOLATE(0, 1.09, 1.00, 40);
CHECK_INTERPOLATE(0, 0.09, 0.09, 100); CHECK_INTERPOLATE(0, 1.09, 1.09, 100);
CHECK_INTERPOLATE(0, 0.09, 0.07, 140); CHECK_INTERPOLATE(0, 1.09, 1.07, 140);
// OUT OF BOUNDS - same as above // OUT OF BOUNDS - same as above
CHECK_INTERPOLATE(0, -0.1, 0.07, RasterDatum::get_invalid()); CHECK_INTERPOLATE(0, -1.1, 1.07, RasterDatum::get_invalid());
CHECK_INTERPOLATE(0, -0.1, -3.0, RasterDatum::get_invalid()); CHECK_INTERPOLATE(0, -1.1, -3.0, RasterDatum::get_invalid());
CHECK_INTERPOLATE(0, 0.3, 23.0, RasterDatum::get_invalid()); CHECK_INTERPOLATE(0, 1.3, 23.0, RasterDatum::get_invalid());
// ARBITRARY - AT DATA - same as above // ARBITRARY - AT DATA - same as above
CHECK_INTERPOLATE(0, 0.06, 0.06, 100); CHECK_INTERPOLATE(0, 1.06, 1.06, 100);
CHECK_INTERPOLATE(0, 0.08, 0.05, 160); CHECK_INTERPOLATE(0, 1.08, 1.05, 160);
CHECK_INTERPOLATE(0, 0.01, 0.05, 20); CHECK_INTERPOLATE(0, 1.01, 1.05, 20);
// ARBITRARY - BETWEEN DATA // ARBITRARY - BETWEEN DATA
CHECK_INTERPOLATE(0, 0.054, 0.023, 54); CHECK_INTERPOLATE(0, 1.054, 1.023, 53);
CHECK_INTERPOLATE(0, 0.056, 0.028, 68); CHECK_INTERPOLATE(0, 1.056, 1.028, 68);
CHECK_INTERPOLATE(0, 0.05, 0.028, 56); CHECK_INTERPOLATE(0, 1.05, 1.028, 56);
int source_already_loaded_id = sources.LoadRasterSource( int source_already_loaded_id = sources.LoadRasterSource(
"../unit_tests/fixtures/raster_data.asc", 0, 0.09, 0, 0.09, 10, 10); "../unit_tests/fixtures/raster_data.asc", 1, 1.09, 1, 1.09, 10, 10);
BOOST_CHECK_EQUAL(source_already_loaded_id, 0); BOOST_CHECK_EQUAL(source_already_loaded_id, 0);
BOOST_CHECK_THROW(sources.GetRasterDataFromSource(1, normalize(0.02), normalize(0.02)), BOOST_CHECK_THROW(sources.GetRasterDataFromSource(1, normalize(1.02), normalize(1.02)),
util::exception); util::exception);
BOOST_CHECK_THROW( BOOST_CHECK_THROW(
sources.LoadRasterSource("../unit_tests/fixtures/nonexistent.asc", 0, 0.1, 0, 0.1, 7, 7), sources.LoadRasterSource("../unit_tests/fixtures/nonexistent.asc", 0, 1.1, 0, 1.1, 7, 7),
util::exception); util::exception);
} }

View File

@ -302,6 +302,13 @@ BOOST_AUTO_TEST_CASE(circleCenter)
c = Coordinate(FloatLongitude(-112.096419), FloatLatitude(41.147259)); c = Coordinate(FloatLongitude(-112.096419), FloatLatitude(41.147259));
result = coordinate_calculation::circleCenter(a, b, c); result = coordinate_calculation::circleCenter(a, b, c);
BOOST_CHECK(!result); BOOST_CHECK(!result);
// Out of bounds
a = Coordinate(FloatLongitude(-112.096234), FloatLatitude(41.147258));
b = Coordinate(FloatLongitude(-112.106606), FloatLatitude(41.147259));
c = Coordinate(FloatLongitude(-113.096419), FloatLatitude(41.147258));
result = coordinate_calculation::circleCenter(a, b, c);
BOOST_CHECK(!result);
} }
BOOST_AUTO_TEST_SUITE_END() BOOST_AUTO_TEST_SUITE_END()