Compare commits
4 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 8250cd0f10 | |||
| 631c9f2360 | |||
| d8741a39e3 | |||
| d33ff6a897 |
@@ -13,7 +13,6 @@ notifications:
|
|||||||
branches:
|
branches:
|
||||||
only:
|
only:
|
||||||
- master
|
- master
|
||||||
- "5.19"
|
|
||||||
# enable building tags
|
# enable building tags
|
||||||
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
- /^v\d+\.\d+(\.\d+)?(-\S*)?$/
|
||||||
|
|
||||||
|
|||||||
+3
-8
@@ -1,16 +1,11 @@
|
|||||||
# 5.19.0
|
# UNRELEASED
|
||||||
- Changes from 5.18.0:
|
- Changes from 5.18.0:
|
||||||
- Optimizations:
|
- Optimizations:
|
||||||
|
- CHANGED: Map matching is now almost twice as fast. [#5060](https://github.com/Project-OSRM/osrm-backend/pull/5060)
|
||||||
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
|
- CHANGED: Use Grisu2 for serializing floating point numbers. [#5188](https://github.com/Project-OSRM/osrm-backend/pull/5188)
|
||||||
- ADDED: Node bindings can return pre-rendered JSON buffer. [#5189](https://github.com/Project-OSRM/osrm-backend/pull/5189)
|
|
||||||
- Profiles:
|
|
||||||
- CHANGED: Bicycle profile now blacklists barriers instead of whitelisting them [#5076
|
|
||||||
](https://github.com/Project-OSRM/osrm-backend/pull/5076/)
|
|
||||||
- CHANGED: Foot profile now blacklists barriers instead of whitelisting them [#5077
|
|
||||||
](https://github.com/Project-OSRM/osrm-backend/pull/5077/)
|
|
||||||
- CHANGED: Support maxlength and maxweight in car profile [#5101](https://github.com/Project-OSRM/osrm-backend/pull/5101]
|
|
||||||
- Bugfixes:
|
- Bugfixes:
|
||||||
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
|
- FIXED: collapsing of ExitRoundabout instructions [#5114](https://github.com/Project-OSRM/osrm-backend/issues/5114)
|
||||||
|
- FIXED: negative distances in table plugin annotation [#5106](https://github.com/Project-OSRM/osrm-backend/issues/5106)
|
||||||
- Misc:
|
- Misc:
|
||||||
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
|
- CHANGED: Support up to 512 named shared memory regions [#5185](https://github.com/Project-OSRM/osrm-backend/pull/5185)
|
||||||
|
|
||||||
|
|||||||
@@ -297,29 +297,6 @@ Returns **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Refer
|
|||||||
2) `waypoint_index`: index of the point in the trip.
|
2) `waypoint_index`: index of the point in the trip.
|
||||||
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
**`trips`**: an array of [`Route`](#route) objects that assemble the trace.
|
||||||
|
|
||||||
## Plugin behaviour
|
|
||||||
|
|
||||||
All plugins support a second additional object that is available to configure some NodeJS specific behaviours.
|
|
||||||
|
|
||||||
- `plugin_config` **[Object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object)** Object literal containing parameters for the trip query.
|
|
||||||
- `plugin_config.format` **[String](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String)?** The format of the result object to various API calls. Valid options are `object` (default), which returns a standard Javascript object, as described above, and `json_buffer`, which will return a NodeJS **[Buffer](https://nodejs.org/api/buffer.html)** object, containing a JSON string. The latter has the advantage that it can be immediately serialized to disk/sent over the network, and the generation of the string is performed outside the main NodeJS event loop. This option is ignored by the `tile` plugin.
|
|
||||||
|
|
||||||
**Examples**
|
|
||||||
|
|
||||||
```javascript
|
|
||||||
var osrm = new OSRM('network.osrm');
|
|
||||||
var options = {
|
|
||||||
coordinates: [
|
|
||||||
[13.36761474609375, 52.51663871100423],
|
|
||||||
[13.374481201171875, 52.506191342034576]
|
|
||||||
]
|
|
||||||
};
|
|
||||||
osrm.route(options, { format: "json_buffer" }, function(err, response) {
|
|
||||||
if (err) throw err;
|
|
||||||
console.log(response.toString("utf-8"));
|
|
||||||
});
|
|
||||||
```
|
|
||||||
|
|
||||||
## Responses
|
## Responses
|
||||||
|
|
||||||
Responses
|
Responses
|
||||||
|
|||||||
@@ -72,8 +72,14 @@ struct ContractorConfig final : storage::IOConfig
|
|||||||
// The remaining vertices form the core of the hierarchy
|
// The remaining vertices form the core of the hierarchy
|
||||||
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
|
//(e.g. 0.8 contracts 80 percent of the hierarchy, leaving a core of 20%)
|
||||||
double core_factor;
|
double core_factor;
|
||||||
|
|
||||||
|
// Whether to store distances for CH edges in addition to duration/weight
|
||||||
|
// Defaults to false. Setting to true will require more storage/memory,
|
||||||
|
// but avoids the need for path unpacking to learn the distance of a CH
|
||||||
|
// route (useful for faster distance results in table queries)
|
||||||
|
bool cache_distances;
|
||||||
};
|
};
|
||||||
}
|
} // namespace contractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // EXTRACTOR_OPTIONS_HPP
|
#endif // EXTRACTOR_OPTIONS_HPP
|
||||||
|
|||||||
@@ -12,23 +12,26 @@ namespace contractor
|
|||||||
struct ContractorEdgeData
|
struct ContractorEdgeData
|
||||||
{
|
{
|
||||||
ContractorEdgeData()
|
ContractorEdgeData()
|
||||||
: weight(0), duration(0), id(0), originalEdges(0), shortcut(0), forward(0), backward(0)
|
: weight(0), duration(0), distance(0), id(0), originalEdges(0), shortcut(0), forward(0),
|
||||||
|
backward(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ContractorEdgeData(EdgeWeight weight,
|
ContractorEdgeData(EdgeWeight weight,
|
||||||
EdgeWeight duration,
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance,
|
||||||
unsigned original_edges,
|
unsigned original_edges,
|
||||||
unsigned id,
|
unsigned id,
|
||||||
bool shortcut,
|
bool shortcut,
|
||||||
bool forward,
|
bool forward,
|
||||||
bool backward)
|
bool backward)
|
||||||
: weight(weight), duration(duration), id(id),
|
: weight(weight), duration(duration), distance(distance), id(id),
|
||||||
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
originalEdges(std::min((1u << 29) - 1u, original_edges)), shortcut(shortcut),
|
||||||
forward(forward), backward(backward)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
|
EdgeDistance distance;
|
||||||
unsigned id;
|
unsigned id;
|
||||||
unsigned originalEdges : 29;
|
unsigned originalEdges : 29;
|
||||||
bool shortcut : 1;
|
bool shortcut : 1;
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
input_edge.target,
|
input_edge.target,
|
||||||
std::max(input_edge.data.weight, 1),
|
std::max(input_edge.data.weight, 1),
|
||||||
input_edge.data.duration,
|
input_edge.data.duration,
|
||||||
|
input_edge.data.distance,
|
||||||
1,
|
1,
|
||||||
input_edge.data.turn_id,
|
input_edge.data.turn_id,
|
||||||
false,
|
false,
|
||||||
@@ -51,6 +52,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
input_edge.source,
|
input_edge.source,
|
||||||
std::max(input_edge.data.weight, 1),
|
std::max(input_edge.data.weight, 1),
|
||||||
input_edge.data.duration,
|
input_edge.data.duration,
|
||||||
|
input_edge.data.distance,
|
||||||
1,
|
1,
|
||||||
input_edge.data.turn_id,
|
input_edge.data.turn_id,
|
||||||
false,
|
false,
|
||||||
@@ -82,6 +84,7 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
forward_edge.data.originalEdges = reverse_edge.data.originalEdges = 1;
|
||||||
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
forward_edge.data.weight = reverse_edge.data.weight = INVALID_EDGE_WEIGHT;
|
||||||
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
forward_edge.data.duration = reverse_edge.data.duration = MAXIMAL_EDGE_DURATION;
|
||||||
|
forward_edge.data.distance = reverse_edge.data.distance = MAXIMAL_EDGE_DISTANCE;
|
||||||
// remove parallel edges
|
// remove parallel edges
|
||||||
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
while (i < edges.size() && edges[i].source == source && edges[i].target == target)
|
||||||
{
|
{
|
||||||
@@ -90,12 +93,16 @@ ContractorGraph toContractorGraph(NodeID number_of_nodes, InputEdgeContainer inp
|
|||||||
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
forward_edge.data.weight = std::min(edges[i].data.weight, forward_edge.data.weight);
|
||||||
forward_edge.data.duration =
|
forward_edge.data.duration =
|
||||||
std::min(edges[i].data.duration, forward_edge.data.duration);
|
std::min(edges[i].data.duration, forward_edge.data.duration);
|
||||||
|
forward_edge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, forward_edge.data.distance);
|
||||||
}
|
}
|
||||||
if (edges[i].data.backward)
|
if (edges[i].data.backward)
|
||||||
{
|
{
|
||||||
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
reverse_edge.data.weight = std::min(edges[i].data.weight, reverse_edge.data.weight);
|
||||||
reverse_edge.data.duration =
|
reverse_edge.data.duration =
|
||||||
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
std::min(edges[i].data.duration, reverse_edge.data.duration);
|
||||||
|
reverse_edge.data.distance =
|
||||||
|
std::min(edges[i].data.distance, reverse_edge.data.distance);
|
||||||
}
|
}
|
||||||
++i;
|
++i;
|
||||||
}
|
}
|
||||||
@@ -151,6 +158,7 @@ template <class Edge, typename GraphT> inline std::vector<Edge> toEdges(GraphT g
|
|||||||
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
BOOST_ASSERT_MSG(SPECIAL_NODEID != new_edge.target, "Target id invalid");
|
||||||
new_edge.data.weight = data.weight;
|
new_edge.data.weight = data.weight;
|
||||||
new_edge.data.duration = data.duration;
|
new_edge.data.duration = data.duration;
|
||||||
|
new_edge.data.distance = data.distance;
|
||||||
new_edge.data.shortcut = data.shortcut;
|
new_edge.data.shortcut = data.shortcut;
|
||||||
new_edge.data.turn_id = data.id;
|
new_edge.data.turn_id = data.id;
|
||||||
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
BOOST_ASSERT_MSG(new_edge.data.turn_id != INT_MAX, // 2^31
|
||||||
|
|||||||
@@ -17,7 +17,8 @@ struct QueryEdge
|
|||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
explicit EdgeData()
|
explicit EdgeData()
|
||||||
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false)
|
: turn_id(0), shortcut(false), weight(0), duration(0), forward(false), backward(false),
|
||||||
|
distance(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -25,10 +26,11 @@ struct QueryEdge
|
|||||||
const bool shortcut,
|
const bool shortcut,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
|
: turn_id(turn_id), shortcut(shortcut), weight(weight), duration(duration),
|
||||||
forward(forward), backward(backward)
|
forward(forward), backward(backward), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,6 +42,7 @@ struct QueryEdge
|
|||||||
turn_id = other.id;
|
turn_id = other.id;
|
||||||
forward = other.forward;
|
forward = other.forward;
|
||||||
backward = other.backward;
|
backward = other.backward;
|
||||||
|
distance = other.distance;
|
||||||
}
|
}
|
||||||
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
|
// this ID is either the middle node of the shortcut, or the ID of the edge based node (node
|
||||||
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
|
// based edge) storing the appropriate data. If `shortcut` is set to true, we get the middle
|
||||||
@@ -50,6 +53,7 @@ struct QueryEdge
|
|||||||
EdgeWeight duration : 30;
|
EdgeWeight duration : 30;
|
||||||
std::uint32_t forward : 1;
|
std::uint32_t forward : 1;
|
||||||
std::uint32_t backward : 1;
|
std::uint32_t backward : 1;
|
||||||
|
EdgeDistance distance;
|
||||||
} data;
|
} data;
|
||||||
|
|
||||||
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
QueryEdge() : source(SPECIAL_NODEID), target(SPECIAL_NODEID) {}
|
||||||
@@ -69,10 +73,11 @@ struct QueryEdge
|
|||||||
return (source == right.source && target == right.target &&
|
return (source == right.source && target == right.target &&
|
||||||
data.weight == right.data.weight && data.duration == right.data.duration &&
|
data.weight == right.data.weight && data.duration == right.data.duration &&
|
||||||
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
|
data.shortcut == right.data.shortcut && data.forward == right.data.forward &&
|
||||||
data.backward == right.data.backward && data.turn_id == right.data.turn_id);
|
data.backward == right.data.backward && data.turn_id == right.data.turn_id &&
|
||||||
|
data.distance == right.data.distance);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace contractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // QUERYEDGE_HPP
|
#endif // QUERYEDGE_HPP
|
||||||
|
|||||||
@@ -449,6 +449,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
|
const auto reverse_durations = datafacade.GetUncompressedReverseDurations(geometry_id);
|
||||||
|
|
||||||
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
|
const auto forward_geometry = datafacade.GetUncompressedForwardGeometry(geometry_id);
|
||||||
|
const auto reverse_geometry = datafacade.GetUncompressedReverseGeometry(geometry_id);
|
||||||
|
|
||||||
const auto forward_weight_offset =
|
const auto forward_weight_offset =
|
||||||
std::accumulate(forward_weights.begin(),
|
std::accumulate(forward_weights.begin(),
|
||||||
@@ -479,19 +480,19 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
|
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position)),
|
||||||
point_on_segment);
|
point_on_segment);
|
||||||
|
|
||||||
const auto reverse_weight_offset =
|
const auto rev_segment_position = reverse_weights.size() - data.fwd_segment_position - 1;
|
||||||
std::accumulate(reverse_weights.begin(),
|
|
||||||
reverse_weights.end() - data.fwd_segment_position - 1,
|
const auto reverse_weight_offset = std::accumulate(
|
||||||
EdgeWeight{0});
|
reverse_weights.begin(), reverse_weights.begin() + rev_segment_position, EdgeWeight{0});
|
||||||
|
|
||||||
const auto reverse_duration_offset =
|
const auto reverse_duration_offset =
|
||||||
std::accumulate(reverse_durations.begin(),
|
std::accumulate(reverse_durations.begin(),
|
||||||
reverse_durations.end() - data.fwd_segment_position - 1,
|
reverse_durations.begin() + rev_segment_position,
|
||||||
EdgeDuration{0});
|
EdgeDuration{0});
|
||||||
|
|
||||||
EdgeDistance reverse_distance_offset = 0;
|
EdgeDistance reverse_distance_offset = 0;
|
||||||
for (auto current = forward_geometry.begin();
|
for (auto current = reverse_geometry.begin();
|
||||||
current < forward_geometry.end() - data.fwd_segment_position - 2;
|
current < reverse_geometry.begin() + rev_segment_position;
|
||||||
++current)
|
++current)
|
||||||
{
|
{
|
||||||
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
reverse_distance_offset += util::coordinate_calculation::fccApproximateDistance(
|
||||||
@@ -499,13 +500,11 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
datafacade.GetCoordinateOfNode(*std::next(current)));
|
datafacade.GetCoordinateOfNode(*std::next(current)));
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeWeight reverse_weight =
|
EdgeWeight reverse_weight = reverse_weights[rev_segment_position];
|
||||||
reverse_weights[reverse_weights.size() - data.fwd_segment_position - 1];
|
EdgeDuration reverse_duration = reverse_durations[rev_segment_position];
|
||||||
EdgeDuration reverse_duration =
|
|
||||||
reverse_durations[reverse_durations.size() - data.fwd_segment_position - 1];
|
|
||||||
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
|
EdgeDistance reverse_distance = util::coordinate_calculation::fccApproximateDistance(
|
||||||
point_on_segment,
|
point_on_segment,
|
||||||
datafacade.GetCoordinateOfNode(forward_geometry(data.fwd_segment_position + 1)));
|
datafacade.GetCoordinateOfNode(reverse_geometry(rev_segment_position)));
|
||||||
|
|
||||||
ratio = std::min(1.0, std::max(0.0, ratio));
|
ratio = std::min(1.0, std::max(0.0, ratio));
|
||||||
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
if (data.forward_segment_id.id != SPECIAL_SEGMENTID)
|
||||||
@@ -693,7 +692,7 @@ template <typename RTreeT, typename DataFacadeT> class GeospatialQuery
|
|||||||
const CoordinateList &coordinates;
|
const CoordinateList &coordinates;
|
||||||
DataFacadeT &datafacade;
|
DataFacadeT &datafacade;
|
||||||
};
|
};
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -34,6 +34,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|||||||
#include "util/coordinate.hpp"
|
#include "util/coordinate.hpp"
|
||||||
#include "util/typedefs.hpp"
|
#include "util/typedefs.hpp"
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
@@ -44,14 +46,15 @@ namespace engine
|
|||||||
struct PhantomNode
|
struct PhantomNode
|
||||||
{
|
{
|
||||||
PhantomNode()
|
PhantomNode()
|
||||||
: forward_segment_id{SPECIAL_SEGMENTID, false},
|
: forward_segment_id{SPECIAL_SEGMENTID, false}, reverse_segment_id{SPECIAL_SEGMENTID,
|
||||||
reverse_segment_id{SPECIAL_SEGMENTID, false}, forward_weight(INVALID_EDGE_WEIGHT),
|
false},
|
||||||
reverse_weight(INVALID_EDGE_WEIGHT), forward_weight_offset(0), reverse_weight_offset(0),
|
forward_weight(INVALID_EDGE_WEIGHT), reverse_weight(INVALID_EDGE_WEIGHT),
|
||||||
|
forward_weight_offset(0), reverse_weight_offset(0),
|
||||||
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
|
forward_distance(INVALID_EDGE_DISTANCE), reverse_distance(INVALID_EDGE_DISTANCE),
|
||||||
forward_distance_offset(0), reverse_distance_offset(0),
|
forward_distance_offset(0), reverse_distance_offset(0),
|
||||||
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
forward_duration(MAXIMAL_EDGE_DURATION), reverse_duration(MAXIMAL_EDGE_DURATION),
|
||||||
forward_duration_offset(0), reverse_duration_offset(0), fwd_segment_position(0),
|
forward_duration_offset(0), reverse_duration_offset(0),
|
||||||
is_valid_forward_source{false}, is_valid_forward_target{false},
|
fwd_segment_position(0), is_valid_forward_source{false}, is_valid_forward_target{false},
|
||||||
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
is_valid_reverse_source{false}, is_valid_reverse_target{false}, bearing(0)
|
||||||
|
|
||||||
{
|
{
|
||||||
@@ -109,8 +112,9 @@ struct PhantomNode
|
|||||||
|
|
||||||
bool IsValid(const unsigned number_of_nodes) const
|
bool IsValid(const unsigned number_of_nodes) const
|
||||||
{
|
{
|
||||||
return location.IsValid() && ((forward_segment_id.id < number_of_nodes) ||
|
return location.IsValid() &&
|
||||||
(reverse_segment_id.id < number_of_nodes)) &&
|
((forward_segment_id.id < number_of_nodes) ||
|
||||||
|
(reverse_segment_id.id < number_of_nodes)) &&
|
||||||
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
((forward_weight != INVALID_EDGE_WEIGHT) ||
|
||||||
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
(reverse_weight != INVALID_EDGE_WEIGHT)) &&
|
||||||
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
((forward_duration != MAXIMAL_EDGE_DURATION) ||
|
||||||
@@ -234,7 +238,7 @@ struct PhantomNodes
|
|||||||
PhantomNode source_phantom;
|
PhantomNode source_phantom;
|
||||||
PhantomNode target_phantom;
|
PhantomNode target_phantom;
|
||||||
};
|
};
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // PHANTOM_NODES_H
|
#endif // PHANTOM_NODES_H
|
||||||
|
|||||||
@@ -25,15 +25,17 @@ struct NodeBucket
|
|||||||
unsigned from_clique_arc : 1;
|
unsigned from_clique_arc : 1;
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeDuration duration;
|
EdgeDuration duration;
|
||||||
|
EdgeDistance distance;
|
||||||
|
|
||||||
NodeBucket(NodeID middle_node,
|
NodeBucket(NodeID middle_node,
|
||||||
NodeID parent_node,
|
NodeID parent_node,
|
||||||
bool from_clique_arc,
|
bool from_clique_arc,
|
||||||
unsigned column_index,
|
unsigned column_index,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration)
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance)
|
||||||
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
from_clique_arc(from_clique_arc), weight(weight), duration(duration)
|
from_clique_arc(from_clique_arc), weight(weight), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,9 +43,10 @@ struct NodeBucket
|
|||||||
NodeID parent_node,
|
NodeID parent_node,
|
||||||
unsigned column_index,
|
unsigned column_index,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration)
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance)
|
||||||
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
: middle_node(middle_node), parent_node(parent_node), column_index(column_index),
|
||||||
from_clique_arc(false), weight(weight), duration(duration)
|
from_clique_arc(false), weight(weight), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -44,42 +44,140 @@ bool needsLoopBackwards(const PhantomNode &source_phantom, const PhantomNode &ta
|
|||||||
bool needsLoopForward(const PhantomNodes &phantoms);
|
bool needsLoopForward(const PhantomNodes &phantoms);
|
||||||
bool needsLoopBackwards(const PhantomNodes &phantoms);
|
bool needsLoopBackwards(const PhantomNodes &phantoms);
|
||||||
|
|
||||||
template <typename Heap>
|
namespace detail
|
||||||
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
|
||||||
{
|
{
|
||||||
const auto &source = nodes.source_phantom;
|
template <typename Algorithm>
|
||||||
if (source.IsValidForwardSource())
|
void insertSourceInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
{
|
{
|
||||||
forward_heap.Insert(source.forward_segment_id.id,
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
-source.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
source.forward_segment_id.id);
|
{phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance()});
|
||||||
}
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
if (source.IsValidReverseSource())
|
|
||||||
{
|
{
|
||||||
forward_heap.Insert(source.reverse_segment_id.id,
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
-source.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
source.reverse_segment_id.id);
|
{phantom_node.reverse_segment_id.id,
|
||||||
}
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance()});
|
||||||
const auto &target = nodes.target_phantom;
|
|
||||||
if (target.IsValidForwardTarget())
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target.forward_segment_id.id,
|
|
||||||
target.GetForwardWeightPlusOffset(),
|
|
||||||
target.forward_segment_id.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (target.IsValidReverseTarget())
|
|
||||||
{
|
|
||||||
reverse_heap.Insert(target.reverse_segment_id.id,
|
|
||||||
target.GetReverseWeightPlusOffset(),
|
|
||||||
target.reverse_segment_id.id);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ManyToManyQueryHeap>
|
template <typename Algorithm>
|
||||||
void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
void insertTargetInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
{phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance()});
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
{phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance()});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Algorithm>
|
||||||
|
void insertSourceInHeap(typename SearchEngineData<Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseSource())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Algorithm>
|
||||||
|
void insertTargetInHeap(typename SearchEngineData<Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
if (phantom_node.IsValidForwardTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.forward_segment_id.id,
|
||||||
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
|
phantom_node.forward_segment_id.id);
|
||||||
|
}
|
||||||
|
if (phantom_node.IsValidReverseTarget())
|
||||||
|
{
|
||||||
|
heap.Insert(phantom_node.reverse_segment_id.id,
|
||||||
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
|
phantom_node.reverse_segment_id.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} // namespace detail
|
||||||
|
|
||||||
|
inline void insertTargetInHeap(typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertTargetInHeap<mld::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertTargetInHeap(typename SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertTargetInHeap<ch::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertTargetInHeap(typename SearchEngineData<mld::Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertTargetInHeap<mld::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertTargetInHeap(typename SearchEngineData<ch::Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertTargetInHeap<ch::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertSourceInHeap(typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertSourceInHeap<mld::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertSourceInHeap(typename SearchEngineData<ch::Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertSourceInHeap<ch::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertSourceInHeap(typename SearchEngineData<mld::Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertSourceInHeap<mld::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
inline void insertSourceInHeap(typename SearchEngineData<ch::Algorithm>::QueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
|
{
|
||||||
|
detail::insertSourceInHeap<ch::Algorithm>(heap, phantom_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Heap>
|
||||||
|
void insertNodesInHeaps(Heap &forward_heap, Heap &reverse_heap, const PhantomNodes &nodes)
|
||||||
|
{
|
||||||
|
insertSourceInHeap(forward_heap, nodes.source_phantom);
|
||||||
|
insertTargetInHeap(reverse_heap, nodes.target_phantom);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename Algorithm>
|
||||||
|
void insertSourceInHeap(typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &heap,
|
||||||
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
if (phantom_node.IsValidForwardSource())
|
if (phantom_node.IsValidForwardSource())
|
||||||
{
|
{
|
||||||
@@ -95,23 +193,6 @@ void insertSourceInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_no
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename ManyToManyQueryHeap>
|
|
||||||
void insertTargetInHeap(ManyToManyQueryHeap &heap, const PhantomNode &phantom_node)
|
|
||||||
{
|
|
||||||
if (phantom_node.IsValidForwardTarget())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.forward_segment_id.id,
|
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
|
||||||
{phantom_node.forward_segment_id.id, phantom_node.GetForwardDuration()});
|
|
||||||
}
|
|
||||||
if (phantom_node.IsValidReverseTarget())
|
|
||||||
{
|
|
||||||
heap.Insert(phantom_node.reverse_segment_id.id,
|
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
|
||||||
{phantom_node.reverse_segment_id.id, phantom_node.GetReverseDuration()});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename FacadeT>
|
template <typename FacadeT>
|
||||||
void annotatePath(const FacadeT &facade,
|
void annotatePath(const FacadeT &facade,
|
||||||
const PhantomNodes &phantom_node_pair,
|
const PhantomNodes &phantom_node_pair,
|
||||||
@@ -321,58 +402,10 @@ void annotatePath(const FacadeT &facade,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename Algorithm>
|
EdgeDistance adjustPathDistanceToPhantomNodes(const std::vector<NodeID> &path,
|
||||||
double getPathDistance(const DataFacade<Algorithm> &facade,
|
const PhantomNode &source_phantom,
|
||||||
const std::vector<PathData> unpacked_path,
|
const PhantomNode &target_phantom,
|
||||||
const PhantomNode &source_phantom,
|
const EdgeDistance distance);
|
||||||
const PhantomNode &target_phantom)
|
|
||||||
{
|
|
||||||
using util::coordinate_calculation::detail::DEGREE_TO_RAD;
|
|
||||||
using util::coordinate_calculation::detail::EARTH_RADIUS;
|
|
||||||
|
|
||||||
double distance = 0;
|
|
||||||
double prev_lat =
|
|
||||||
static_cast<double>(util::toFloating(source_phantom.location.lat)) * DEGREE_TO_RAD;
|
|
||||||
double prev_lon =
|
|
||||||
static_cast<double>(util::toFloating(source_phantom.location.lon)) * DEGREE_TO_RAD;
|
|
||||||
double prev_cos = std::cos(prev_lat);
|
|
||||||
for (const auto &p : unpacked_path)
|
|
||||||
{
|
|
||||||
const auto current_coordinate = facade.GetCoordinateOfNode(p.turn_via_node);
|
|
||||||
|
|
||||||
const double current_lat =
|
|
||||||
static_cast<double>(util::toFloating(current_coordinate.lat)) * DEGREE_TO_RAD;
|
|
||||||
const double current_lon =
|
|
||||||
static_cast<double>(util::toFloating(current_coordinate.lon)) * DEGREE_TO_RAD;
|
|
||||||
const double current_cos = std::cos(current_lat);
|
|
||||||
|
|
||||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
|
||||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
|
||||||
|
|
||||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
|
||||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
|
||||||
distance += EARTH_RADIUS * charv;
|
|
||||||
|
|
||||||
prev_lat = current_lat;
|
|
||||||
prev_lon = current_lon;
|
|
||||||
prev_cos = current_cos;
|
|
||||||
}
|
|
||||||
|
|
||||||
const double current_lat =
|
|
||||||
static_cast<double>(util::toFloating(target_phantom.location.lat)) * DEGREE_TO_RAD;
|
|
||||||
const double current_lon =
|
|
||||||
static_cast<double>(util::toFloating(target_phantom.location.lon)) * DEGREE_TO_RAD;
|
|
||||||
const double current_cos = std::cos(current_lat);
|
|
||||||
|
|
||||||
const double sin_dlon = std::sin((prev_lon - current_lon) / 2.0);
|
|
||||||
const double sin_dlat = std::sin((prev_lat - current_lat) / 2.0);
|
|
||||||
|
|
||||||
const double aharv = sin_dlat * sin_dlat + prev_cos * current_cos * sin_dlon * sin_dlon;
|
|
||||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
|
||||||
distance += EARTH_RADIUS * charv;
|
|
||||||
|
|
||||||
return distance;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename AlgorithmT>
|
template <typename AlgorithmT>
|
||||||
InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
|
InternalRouteResult extractRoute(const DataFacade<AlgorithmT> &facade,
|
||||||
|
|||||||
@@ -186,9 +186,10 @@ void routingStep(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <bool UseDuration>
|
template <bool UseDuration>
|
||||||
EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
std::tuple<EdgeWeight,EdgeDistance> getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
||||||
{
|
{
|
||||||
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
EdgeWeight loop_weight = UseDuration ? MAXIMAL_EDGE_DURATION : INVALID_EDGE_WEIGHT;
|
||||||
|
EdgeDistance loop_distance = MAXIMAL_EDGE_DISTANCE;
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
{
|
{
|
||||||
const auto &data = facade.GetEdgeData(edge);
|
const auto &data = facade.GetEdgeData(edge);
|
||||||
@@ -198,11 +199,15 @@ EdgeWeight getLoopWeight(const DataFacade<Algorithm> &facade, NodeID node)
|
|||||||
if (to == node)
|
if (to == node)
|
||||||
{
|
{
|
||||||
const auto value = UseDuration ? data.duration : data.weight;
|
const auto value = UseDuration ? data.duration : data.weight;
|
||||||
loop_weight = std::min(loop_weight, value);
|
if (value < loop_weight)
|
||||||
|
{
|
||||||
|
loop_weight = value;
|
||||||
|
loop_distance = data.distance;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return loop_weight;
|
return std::make_tuple(loop_weight, loop_distance);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -97,7 +97,6 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
const std::vector<std::size_t> &phantom_indices)
|
const std::vector<std::size_t> &phantom_indices)
|
||||||
{
|
{
|
||||||
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
|
auto min_level = [&partition, node](const PhantomNode &phantom_node) {
|
||||||
|
|
||||||
const auto &forward_segment = phantom_node.forward_segment_id;
|
const auto &forward_segment = phantom_node.forward_segment_id;
|
||||||
const auto forward_level =
|
const auto forward_level =
|
||||||
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
|
forward_segment.enabled ? partition.GetHighestDifferentLevel(node, forward_segment.id)
|
||||||
@@ -120,7 +119,7 @@ inline LevelID getNodeQueryLevel(const MultiLevelPartition &partition,
|
|||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
// Heaps only record for each node its predecessor ("parent") on the shortest path.
|
// Heaps only record for each node its predecessor ("parent") on the shortest path.
|
||||||
// For re-constructing the actual path we need to trace back all parent "pointers".
|
// For re-constructing the actual path we need to trace back all parent "pointers".
|
||||||
@@ -391,21 +390,27 @@ UnpackedPath search(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
EdgeWeight weight_upper_bound,
|
EdgeWeight weight_upper_bound,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
if (forward_heap.Empty() || reverse_heap.Empty())
|
if (forward_heap.Empty() && reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
|
return std::make_tuple(INVALID_EDGE_WEIGHT, std::vector<NodeID>(), std::vector<EdgeID>());
|
||||||
}
|
}
|
||||||
|
|
||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
|
|
||||||
BOOST_ASSERT(!forward_heap.Empty() && forward_heap.MinKey() < INVALID_EDGE_WEIGHT);
|
BOOST_ASSERT(forward_heap.Empty() || forward_heap.MinKey() < INVALID_EDGE_WEIGHT);
|
||||||
BOOST_ASSERT(!reverse_heap.Empty() && reverse_heap.MinKey() < INVALID_EDGE_WEIGHT);
|
BOOST_ASSERT(reverse_heap.Empty() || reverse_heap.MinKey() < INVALID_EDGE_WEIGHT);
|
||||||
|
|
||||||
// run two-Target Dijkstra routing step.
|
// run two-Target Dijkstra routing step.
|
||||||
NodeID middle = SPECIAL_NODEID;
|
NodeID middle = SPECIAL_NODEID;
|
||||||
EdgeWeight weight = weight_upper_bound;
|
EdgeWeight weight = weight_upper_bound;
|
||||||
EdgeWeight forward_heap_min = forward_heap.MinKey();
|
|
||||||
EdgeWeight reverse_heap_min = reverse_heap.MinKey();
|
EdgeWeight forward_heap_min = 0;
|
||||||
|
if (!forward_heap.Empty())
|
||||||
|
forward_heap_min = forward_heap.MinKey();
|
||||||
|
EdgeWeight reverse_heap_min = 0;
|
||||||
|
if (!reverse_heap.Empty())
|
||||||
|
reverse_heap_min = reverse_heap.MinKey();
|
||||||
|
|
||||||
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
while (forward_heap.Size() + reverse_heap.Size() > 0 &&
|
||||||
forward_heap_min + reverse_heap_min < weight)
|
forward_heap_min + reverse_heap_min < weight)
|
||||||
{
|
{
|
||||||
@@ -657,11 +662,7 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
EdgeWeight weight_upper_bound = INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
|
||||||
reverse_heap.Clear();
|
|
||||||
|
|
||||||
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
const PhantomNodes phantom_nodes{source_phantom, target_phantom};
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, phantom_nodes);
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> unpacked_nodes;
|
std::vector<NodeID> unpacked_nodes;
|
||||||
@@ -680,11 +681,22 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PathData> unpacked_path;
|
EdgeDistance distance = 0;
|
||||||
|
|
||||||
annotatePath(facade, phantom_nodes, unpacked_nodes, unpacked_edges, unpacked_path);
|
if (!unpacked_nodes.empty())
|
||||||
|
{
|
||||||
|
distance = std::accumulate(unpacked_nodes.begin(),
|
||||||
|
std::prev(unpacked_nodes.end()),
|
||||||
|
EdgeDistance{0},
|
||||||
|
[&](const EdgeDistance distance, const auto node_id) {
|
||||||
|
return distance + computeEdgeDistance(facade, node_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
distance = adjustPathDistanceToPhantomNodes(
|
||||||
|
unpacked_nodes, phantom_nodes.source_phantom, phantom_nodes.target_phantom, distance);
|
||||||
|
|
||||||
|
return distance;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace mld
|
} // namespace mld
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ struct HeapData
|
|||||||
struct ManyToManyHeapData : HeapData
|
struct ManyToManyHeapData : HeapData
|
||||||
{
|
{
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
ManyToManyHeapData(NodeID p, EdgeWeight duration) : HeapData(p), duration(duration) {}
|
EdgeDistance distance;
|
||||||
|
ManyToManyHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
|
||||||
|
: HeapData(p), duration(duration), distance(distance)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
template <> struct SearchEngineData<routing_algorithms::ch::Algorithm>
|
||||||
@@ -75,12 +79,16 @@ struct MultiLayerDijkstraHeapData
|
|||||||
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
|
struct ManyToManyMultiLayerDijkstraHeapData : MultiLayerDijkstraHeapData
|
||||||
{
|
{
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration)
|
EdgeDistance distance;
|
||||||
: MultiLayerDijkstraHeapData(p), duration(duration)
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p, EdgeWeight duration, EdgeDistance distance)
|
||||||
|
: MultiLayerDijkstraHeapData(p), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
ManyToManyMultiLayerDijkstraHeapData(NodeID p, bool from, EdgeWeight duration)
|
ManyToManyMultiLayerDijkstraHeapData(NodeID p,
|
||||||
: MultiLayerDijkstraHeapData(p, from), duration(duration)
|
bool from,
|
||||||
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance)
|
||||||
|
: MultiLayerDijkstraHeapData(p, from), duration(duration), distance(distance)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -112,7 +120,7 @@ template <> struct SearchEngineData<routing_algorithms::mld::Algorithm>
|
|||||||
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes,
|
void InitializeOrClearManyToManyThreadLocalStorage(unsigned number_of_nodes,
|
||||||
unsigned number_of_boundary_nodes);
|
unsigned number_of_boundary_nodes);
|
||||||
};
|
};
|
||||||
}
|
} // namespace engine
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // SEARCH_ENGINE_DATA_HPP
|
#endif // SEARCH_ENGINE_DATA_HPP
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ class CompressedEdgeContainer
|
|||||||
std::unordered_map<EdgeID, unsigned> m_reverse_edge_id_to_zipped_index_map;
|
std::unordered_map<EdgeID, unsigned> m_reverse_edge_id_to_zipped_index_map;
|
||||||
std::unique_ptr<SegmentDataContainer> segment_data;
|
std::unique_ptr<SegmentDataContainer> segment_data;
|
||||||
};
|
};
|
||||||
}
|
} // namespace extractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // GEOMETRY_COMPRESSOR_HPP_
|
#endif // GEOMETRY_COMPRESSOR_HPP_
|
||||||
|
|||||||
@@ -15,20 +15,25 @@ struct EdgeBasedEdge
|
|||||||
public:
|
public:
|
||||||
struct EdgeData
|
struct EdgeData
|
||||||
{
|
{
|
||||||
EdgeData() : turn_id(0), weight(0), duration(0), forward(false), backward(false) {}
|
EdgeData()
|
||||||
|
: turn_id(0), weight(0), distance(0), duration(0), forward(false), backward(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
EdgeData(const NodeID turn_id,
|
EdgeData(const NodeID turn_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
|
const EdgeDistance distance,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: turn_id(turn_id), weight(weight), duration(duration), forward(forward),
|
: turn_id(turn_id), weight(weight), distance(distance), duration(duration),
|
||||||
backward(backward)
|
forward(forward), backward(backward)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeID turn_id; // ID of the edge based node (node based edge)
|
NodeID turn_id; // ID of the edge based node (node based edge)
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
|
EdgeDistance distance;
|
||||||
EdgeWeight duration : 30;
|
EdgeWeight duration : 30;
|
||||||
std::uint32_t forward : 1;
|
std::uint32_t forward : 1;
|
||||||
std::uint32_t backward : 1;
|
std::uint32_t backward : 1;
|
||||||
@@ -43,6 +48,7 @@ struct EdgeBasedEdge
|
|||||||
const NodeID edge_id,
|
const NodeID edge_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward);
|
const bool backward);
|
||||||
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
|
EdgeBasedEdge(const NodeID source, const NodeID target, const EdgeBasedEdge::EdgeData &data);
|
||||||
@@ -53,7 +59,7 @@ struct EdgeBasedEdge
|
|||||||
NodeID target;
|
NodeID target;
|
||||||
EdgeData data;
|
EdgeData data;
|
||||||
};
|
};
|
||||||
static_assert(sizeof(extractor::EdgeBasedEdge) == 20,
|
static_assert(sizeof(extractor::EdgeBasedEdge) == 24,
|
||||||
"Size of extractor::EdgeBasedEdge type is "
|
"Size of extractor::EdgeBasedEdge type is "
|
||||||
"bigger than expected. This will influence "
|
"bigger than expected. This will influence "
|
||||||
"memory consumption.");
|
"memory consumption.");
|
||||||
@@ -67,9 +73,10 @@ inline EdgeBasedEdge::EdgeBasedEdge(const NodeID source,
|
|||||||
const NodeID turn_id,
|
const NodeID turn_id,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeWeight duration,
|
const EdgeWeight duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
const bool forward,
|
const bool forward,
|
||||||
const bool backward)
|
const bool backward)
|
||||||
: source(source), target(target), data{turn_id, weight, duration, forward, backward}
|
: source(source), target(target), data{turn_id, weight, distance, duration, forward, backward}
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -89,7 +96,7 @@ inline bool EdgeBasedEdge::operator<(const EdgeBasedEdge &other) const
|
|||||||
return std::tie(source, target, data.weight, unidirectional) <
|
return std::tie(source, target, data.weight, unidirectional) <
|
||||||
std::tie(other.source, other.target, other.data.weight, other_is_unidirectional);
|
std::tie(other.source, other.target, other.data.weight, other_is_unidirectional);
|
||||||
}
|
}
|
||||||
} // ns extractor
|
} // namespace extractor
|
||||||
} // ns osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif /* EDGE_BASED_EDGE_HPP */
|
#endif /* EDGE_BASED_EDGE_HPP */
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ struct ByEdgeOrByMeterValue
|
|||||||
using value_type = float;
|
using value_type = float;
|
||||||
value_type value;
|
value_type value;
|
||||||
};
|
};
|
||||||
}
|
} // namespace detail
|
||||||
|
|
||||||
struct InternalExtractorEdge
|
struct InternalExtractorEdge
|
||||||
{
|
{
|
||||||
@@ -63,7 +63,7 @@ struct InternalExtractorEdge
|
|||||||
WeightData weight_data,
|
WeightData weight_data,
|
||||||
DurationData duration_data,
|
DurationData duration_data,
|
||||||
util::Coordinate source_coordinate)
|
util::Coordinate source_coordinate)
|
||||||
: result(source, target, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
|
: result(source, target, 0, 0, 0, {}, -1, {}), weight_data(std::move(weight_data)),
|
||||||
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
|
duration_data(std::move(duration_data)), source_coordinate(std::move(source_coordinate))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -113,7 +113,7 @@ struct InternalExtractorEdge
|
|||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace extractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // INTERNAL_EXTRACTOR_EDGE_HPP
|
#endif // INTERNAL_EXTRACTOR_EDGE_HPP
|
||||||
|
|||||||
@@ -97,6 +97,7 @@ struct NodeBasedEdge
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags);
|
NodeBasedEdgeClassification flags);
|
||||||
@@ -107,6 +108,7 @@ struct NodeBasedEdge
|
|||||||
NodeID target; // 32 4
|
NodeID target; // 32 4
|
||||||
EdgeWeight weight; // 32 4
|
EdgeWeight weight; // 32 4
|
||||||
EdgeDuration duration; // 32 4
|
EdgeDuration duration; // 32 4
|
||||||
|
EdgeDistance distance; // 32 4
|
||||||
GeometryID geometry_id; // 32 4
|
GeometryID geometry_id; // 32 4
|
||||||
AnnotationID annotation_data; // 32 4
|
AnnotationID annotation_data; // 32 4
|
||||||
NodeBasedEdgeClassification flags; // 32 4
|
NodeBasedEdgeClassification flags; // 32 4
|
||||||
@@ -120,6 +122,7 @@ struct NodeBasedEdgeWithOSM : NodeBasedEdge
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags);
|
NodeBasedEdgeClassification flags);
|
||||||
@@ -137,7 +140,8 @@ inline NodeBasedEdgeClassification::NodeBasedEdgeClassification()
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline NodeBasedEdge::NodeBasedEdge()
|
inline NodeBasedEdge::NodeBasedEdge()
|
||||||
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), annotation_data(-1)
|
: source(SPECIAL_NODEID), target(SPECIAL_NODEID), weight(0), duration(0), distance(0),
|
||||||
|
annotation_data(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,11 +149,12 @@ inline NodeBasedEdge::NodeBasedEdge(NodeID source,
|
|||||||
NodeID target,
|
NodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags)
|
NodeBasedEdgeClassification flags)
|
||||||
: source(source), target(target), weight(weight), duration(duration), geometry_id(geometry_id),
|
: source(source), target(target), weight(weight), duration(duration), distance(distance),
|
||||||
annotation_data(annotation_data), flags(flags)
|
geometry_id(geometry_id), annotation_data(annotation_data), flags(flags)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,11 +180,18 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM(OSMNodeID source,
|
|||||||
OSMNodeID target,
|
OSMNodeID target,
|
||||||
EdgeWeight weight,
|
EdgeWeight weight,
|
||||||
EdgeDuration duration,
|
EdgeDuration duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
AnnotationID annotation_data,
|
AnnotationID annotation_data,
|
||||||
NodeBasedEdgeClassification flags)
|
NodeBasedEdgeClassification flags)
|
||||||
: NodeBasedEdge(
|
: NodeBasedEdge(SPECIAL_NODEID,
|
||||||
SPECIAL_NODEID, SPECIAL_NODEID, weight, duration, geometry_id, annotation_data, flags),
|
SPECIAL_NODEID,
|
||||||
|
weight,
|
||||||
|
duration,
|
||||||
|
distance,
|
||||||
|
geometry_id,
|
||||||
|
annotation_data,
|
||||||
|
flags),
|
||||||
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
osm_source_id(std::move(source)), osm_target_id(std::move(target))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -189,12 +201,12 @@ inline NodeBasedEdgeWithOSM::NodeBasedEdgeWithOSM()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
static_assert(sizeof(extractor::NodeBasedEdge) == 28,
|
static_assert(sizeof(extractor::NodeBasedEdge) == 32,
|
||||||
"Size of extractor::NodeBasedEdge type is "
|
"Size of extractor::NodeBasedEdge type is "
|
||||||
"bigger than expected. This will influence "
|
"bigger than expected. This will influence "
|
||||||
"memory consumption.");
|
"memory consumption.");
|
||||||
|
|
||||||
} // ns extractor
|
} // namespace extractor
|
||||||
} // ns osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif /* NODE_BASED_EDGE_HPP */
|
#endif /* NODE_BASED_EDGE_HPP */
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#define OSRM_BINDINGS_NODE_SUPPORT_HPP
|
#define OSRM_BINDINGS_NODE_SUPPORT_HPP
|
||||||
|
|
||||||
#include "nodejs/json_v8_renderer.hpp"
|
#include "nodejs/json_v8_renderer.hpp"
|
||||||
#include "util/json_renderer.hpp"
|
|
||||||
|
|
||||||
#include "osrm/approach.hpp"
|
#include "osrm/approach.hpp"
|
||||||
#include "osrm/bearing.hpp"
|
#include "osrm/bearing.hpp"
|
||||||
@@ -25,7 +24,6 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
#include <sstream>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -44,13 +42,6 @@ using match_parameters_ptr = std::unique_ptr<osrm::MatchParameters>;
|
|||||||
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
|
using nearest_parameters_ptr = std::unique_ptr<osrm::NearestParameters>;
|
||||||
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
|
using table_parameters_ptr = std::unique_ptr<osrm::TableParameters>;
|
||||||
|
|
||||||
struct PluginParameters
|
|
||||||
{
|
|
||||||
bool renderJSONToBuffer = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
using ObjectOrString = typename mapbox::util::variant<osrm::json::Object, std::string>;
|
|
||||||
|
|
||||||
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
|
template <typename ResultT> inline v8::Local<v8::Value> render(const ResultT &result);
|
||||||
|
|
||||||
template <> v8::Local<v8::Value> inline render(const std::string &result)
|
template <> v8::Local<v8::Value> inline render(const std::string &result)
|
||||||
@@ -58,21 +49,11 @@ template <> v8::Local<v8::Value> inline render(const std::string &result)
|
|||||||
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
|
return Nan::CopyBuffer(result.data(), result.size()).ToLocalChecked();
|
||||||
}
|
}
|
||||||
|
|
||||||
template <> v8::Local<v8::Value> inline render(const ObjectOrString &result)
|
template <> v8::Local<v8::Value> inline render(const osrm::json::Object &result)
|
||||||
{
|
{
|
||||||
if (result.is<osrm::json::Object>())
|
v8::Local<v8::Value> value;
|
||||||
{
|
renderToV8(value, result);
|
||||||
// Convert osrm::json object tree into matching v8 object tree
|
return value;
|
||||||
v8::Local<v8::Value> value;
|
|
||||||
renderToV8(value, result.get<osrm::json::Object>());
|
|
||||||
return value;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Return the string object as a node Buffer
|
|
||||||
return Nan::CopyBuffer(result.get<std::string>().data(), result.get<std::string>().size())
|
|
||||||
.ToLocalChecked();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
|
inline void ParseResult(const osrm::Status &result_status, osrm::json::Object &result)
|
||||||
@@ -833,50 +814,6 @@ inline bool parseCommonParameters(const v8::Local<v8::Object> &obj, ParamType &p
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline PluginParameters
|
|
||||||
argumentsToPluginParameters(const Nan::FunctionCallbackInfo<v8::Value> &args)
|
|
||||||
{
|
|
||||||
if (args.Length() < 3 || !args[1]->IsObject())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
v8::Local<v8::Object> obj = Nan::To<v8::Object>(args[1]).ToLocalChecked();
|
|
||||||
if (obj->Has(Nan::New("format").ToLocalChecked()))
|
|
||||||
{
|
|
||||||
|
|
||||||
v8::Local<v8::Value> format = obj->Get(Nan::New("format").ToLocalChecked());
|
|
||||||
if (format.IsEmpty())
|
|
||||||
{
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!format->IsString())
|
|
||||||
{
|
|
||||||
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
const Nan::Utf8String format_utf8str(format);
|
|
||||||
std::string format_str{*format_utf8str, *format_utf8str + format_utf8str.length()};
|
|
||||||
|
|
||||||
if (format_str == "object")
|
|
||||||
{
|
|
||||||
return {false};
|
|
||||||
}
|
|
||||||
else if (format_str == "json_buffer")
|
|
||||||
{
|
|
||||||
return {true};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Nan::ThrowError("format must be a string: \"object\" or \"json_buffer\"");
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return {};
|
|
||||||
}
|
|
||||||
|
|
||||||
inline route_parameters_ptr
|
inline route_parameters_ptr
|
||||||
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
argumentsToRouteParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
||||||
bool requires_multiple_coordinates)
|
bool requires_multiple_coordinates)
|
||||||
@@ -1420,6 +1357,6 @@ argumentsToMatchParameter(const Nan::FunctionCallbackInfo<v8::Value> &args,
|
|||||||
return params;
|
return params;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace node_osrm
|
} // ns node_osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -14,6 +14,8 @@
|
|||||||
#include <tbb/parallel_for.h>
|
#include <tbb/parallel_for.h>
|
||||||
#include <tbb/parallel_reduce.h>
|
#include <tbb/parallel_reduce.h>
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -43,6 +45,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
|
|||||||
edge.data.turn_id,
|
edge.data.turn_id,
|
||||||
std::max(edge.data.weight, 1),
|
std::max(edge.data.weight, 1),
|
||||||
edge.data.duration,
|
edge.data.duration,
|
||||||
|
edge.data.distance,
|
||||||
edge.data.forward,
|
edge.data.forward,
|
||||||
edge.data.backward);
|
edge.data.backward);
|
||||||
|
|
||||||
@@ -51,6 +54,7 @@ splitBidirectionalEdges(const std::vector<extractor::EdgeBasedEdge> &edges)
|
|||||||
edge.data.turn_id,
|
edge.data.turn_id,
|
||||||
std::max(edge.data.weight, 1),
|
std::max(edge.data.weight, 1),
|
||||||
edge.data.duration,
|
edge.data.duration,
|
||||||
|
edge.data.distance,
|
||||||
edge.data.backward,
|
edge.data.backward,
|
||||||
edge.data.forward);
|
edge.data.forward);
|
||||||
}
|
}
|
||||||
@@ -196,7 +200,7 @@ inline DynamicEdgeBasedGraph LoadEdgeBasedGraph(const boost::filesystem::path &p
|
|||||||
return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied), checksum);
|
return DynamicEdgeBasedGraph(number_of_edge_based_nodes, std::move(tidied), checksum);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // ns partition
|
} // namespace partitioner
|
||||||
} // ns osrm
|
} // namespace osrm
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -23,9 +23,6 @@ namespace detail
|
|||||||
{
|
{
|
||||||
const constexpr double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
|
const constexpr double DEGREE_TO_RAD = 0.017453292519943295769236907684886;
|
||||||
const constexpr double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
|
const constexpr double RAD_TO_DEGREE = 1. / DEGREE_TO_RAD;
|
||||||
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
|
||||||
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
|
||||||
const constexpr long double EARTH_RADIUS = 6372797.560856;
|
|
||||||
|
|
||||||
inline double degToRad(const double degree)
|
inline double degToRad(const double degree)
|
||||||
{
|
{
|
||||||
|
|||||||
+31
-11
@@ -1,9 +1,11 @@
|
|||||||
#ifndef OSRM_UTIL_DEBUG_HPP_
|
#ifndef OSRM_UTIL_DEBUG_HPP_
|
||||||
#define OSRM_UTIL_DEBUG_HPP_
|
#define OSRM_UTIL_DEBUG_HPP_
|
||||||
|
|
||||||
|
#include "extractor/edge_based_edge.hpp"
|
||||||
#include "extractor/node_data_container.hpp"
|
#include "extractor/node_data_container.hpp"
|
||||||
#include "extractor/query_node.hpp"
|
#include "extractor/query_node.hpp"
|
||||||
#include "guidance/intersection.hpp"
|
#include "guidance/intersection.hpp"
|
||||||
|
#include "guidance/turn_instruction.hpp"
|
||||||
#include "guidance/turn_lane_data.hpp"
|
#include "guidance/turn_lane_data.hpp"
|
||||||
#include "engine/guidance/route_step.hpp"
|
#include "engine/guidance/route_step.hpp"
|
||||||
#include "util/node_based_graph.hpp"
|
#include "util/node_based_graph.hpp"
|
||||||
@@ -25,7 +27,7 @@ inline std::ostream &operator<<(std::ostream &out, const Coordinate &coordinate)
|
|||||||
<< toFloating(coordinate.lat) << "}";
|
<< toFloating(coordinate.lat) << "}";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace util
|
||||||
|
|
||||||
namespace engine
|
namespace engine
|
||||||
{
|
{
|
||||||
@@ -60,8 +62,8 @@ inline std::ostream &operator<<(std::ostream &out, const RouteStep &step)
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace guidance
|
||||||
}
|
} // namespace engine
|
||||||
|
|
||||||
namespace guidance
|
namespace guidance
|
||||||
{
|
{
|
||||||
@@ -74,7 +76,7 @@ inline std::ostream &operator<<(std::ostream &out, const ConnectedRoad &road)
|
|||||||
<< static_cast<std::int32_t>(road.lane_data_id) << "}";
|
<< static_cast<std::int32_t>(road.lane_data_id) << "}";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace guidance
|
||||||
|
|
||||||
namespace extractor
|
namespace extractor
|
||||||
{
|
{
|
||||||
@@ -93,7 +95,7 @@ inline std::ostream &operator<<(std::ostream &out, const IntersectionViewData &v
|
|||||||
<< " angle: " << view.angle << " bearing: " << view.perceived_bearing << "}";
|
<< " angle: " << view.angle << " bearing: " << view.perceived_bearing << "}";
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace intersection
|
||||||
|
|
||||||
namespace TurnLaneType
|
namespace TurnLaneType
|
||||||
{
|
{
|
||||||
@@ -123,9 +125,9 @@ inline std::ostream &operator<<(std::ostream &out, const Mask lane_type)
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace TurnLaneType
|
||||||
}
|
} // namespace extractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
namespace std
|
namespace std
|
||||||
{
|
{
|
||||||
@@ -145,7 +147,7 @@ inline std::ostream &operator<<(std::ostream &out,
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace std
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -184,8 +186,26 @@ inline std::ostream &operator<<(std::ostream &out, const LaneDataVector &turn_la
|
|||||||
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
}
|
} // namespace lanes
|
||||||
}
|
} // namespace guidance
|
||||||
|
|
||||||
|
namespace extractor
|
||||||
|
{
|
||||||
|
inline std::ostream &operator<<(std::ostream &out, const EdgeBasedEdge &edge)
|
||||||
|
{
|
||||||
|
out << " EdgeBasedEdge {";
|
||||||
|
out << " source " << edge.source << ", target: " << edge.target;
|
||||||
|
out << " EdgeBasedEdgeData data {";
|
||||||
|
out << " turn_id: " << edge.data.turn_id << ", weight: " << edge.data.weight;
|
||||||
|
out << " distance: " << edge.data.distance << ", duration: " << edge.data.duration;
|
||||||
|
out << " forward: " << (edge.data.forward == 0 ? "false" : "true")
|
||||||
|
<< ", backward: " << (edge.data.backward == 0 ? "false" : "true");
|
||||||
|
out << " }";
|
||||||
|
out << "}";
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} // namespace extractor
|
||||||
|
} // namespace osrm
|
||||||
|
|
||||||
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
|
#endif /*OSRM_ENGINE_GUIDANCE_DEBUG_HPP_*/
|
||||||
|
|||||||
@@ -20,24 +20,27 @@ namespace util
|
|||||||
struct NodeBasedEdgeData
|
struct NodeBasedEdgeData
|
||||||
{
|
{
|
||||||
NodeBasedEdgeData()
|
NodeBasedEdgeData()
|
||||||
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT), geometry_id({0, false}),
|
: weight(INVALID_EDGE_WEIGHT), duration(INVALID_EDGE_WEIGHT),
|
||||||
reversed(false), annotation_data(-1)
|
distance(INVALID_EDGE_DISTANCE), geometry_id({0, false}), reversed(false),
|
||||||
|
annotation_data(-1)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
NodeBasedEdgeData(EdgeWeight weight,
|
NodeBasedEdgeData(EdgeWeight weight,
|
||||||
EdgeWeight duration,
|
EdgeWeight duration,
|
||||||
|
EdgeDistance distance,
|
||||||
GeometryID geometry_id,
|
GeometryID geometry_id,
|
||||||
bool reversed,
|
bool reversed,
|
||||||
extractor::NodeBasedEdgeClassification flags,
|
extractor::NodeBasedEdgeClassification flags,
|
||||||
AnnotationID annotation_data)
|
AnnotationID annotation_data)
|
||||||
: weight(weight), duration(duration), geometry_id(geometry_id), reversed(reversed),
|
: weight(weight), duration(duration), distance(distance), geometry_id(geometry_id),
|
||||||
flags(flags), annotation_data(annotation_data)
|
reversed(reversed), flags(flags), annotation_data(annotation_data)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
EdgeWeight weight;
|
EdgeWeight weight;
|
||||||
EdgeWeight duration;
|
EdgeWeight duration;
|
||||||
|
EdgeDistance distance;
|
||||||
GeometryID geometry_id;
|
GeometryID geometry_id;
|
||||||
bool reversed : 1;
|
bool reversed : 1;
|
||||||
extractor::NodeBasedEdgeClassification flags;
|
extractor::NodeBasedEdgeClassification flags;
|
||||||
@@ -80,18 +83,20 @@ NodeBasedDynamicGraphFromEdges(NodeID number_of_nodes,
|
|||||||
const extractor::NodeBasedEdge &input_edge) {
|
const extractor::NodeBasedEdge &input_edge) {
|
||||||
output_edge.data.weight = input_edge.weight;
|
output_edge.data.weight = input_edge.weight;
|
||||||
output_edge.data.duration = input_edge.duration;
|
output_edge.data.duration = input_edge.duration;
|
||||||
|
output_edge.data.distance = input_edge.distance;
|
||||||
output_edge.data.flags = input_edge.flags;
|
output_edge.data.flags = input_edge.flags;
|
||||||
output_edge.data.annotation_data = input_edge.annotation_data;
|
output_edge.data.annotation_data = input_edge.annotation_data;
|
||||||
|
|
||||||
BOOST_ASSERT(output_edge.data.weight > 0);
|
BOOST_ASSERT(output_edge.data.weight > 0);
|
||||||
BOOST_ASSERT(output_edge.data.duration > 0);
|
BOOST_ASSERT(output_edge.data.duration > 0);
|
||||||
|
BOOST_ASSERT(output_edge.data.distance > 0);
|
||||||
});
|
});
|
||||||
|
|
||||||
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
tbb::parallel_sort(edges_list.begin(), edges_list.end());
|
||||||
|
|
||||||
return NodeBasedDynamicGraph(number_of_nodes, edges_list);
|
return NodeBasedDynamicGraph(number_of_nodes, edges_list);
|
||||||
}
|
}
|
||||||
}
|
} // namespace util
|
||||||
}
|
} // namespace osrm
|
||||||
|
|
||||||
#endif // NODE_BASED_GRAPH_HPP
|
#endif // NODE_BASED_GRAPH_HPP
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ struct osm_way_id
|
|||||||
struct duplicated_node
|
struct duplicated_node
|
||||||
{
|
{
|
||||||
};
|
};
|
||||||
}
|
} // namespace tag
|
||||||
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
|
using OSMNodeID = osrm::Alias<std::uint64_t, tag::osm_node_id>;
|
||||||
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
|
static_assert(std::is_pod<OSMNodeID>(), "OSMNodeID is not a valid alias");
|
||||||
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
|
using OSMWayID = osrm::Alias<std::uint64_t, tag::osm_way_id>;
|
||||||
@@ -113,6 +113,7 @@ static const SegmentWeight MAX_SEGMENT_WEIGHT = INVALID_SEGMENT_WEIGHT - 1;
|
|||||||
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
|
static const SegmentDuration MAX_SEGMENT_DURATION = INVALID_SEGMENT_DURATION - 1;
|
||||||
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
static const EdgeWeight INVALID_EDGE_WEIGHT = std::numeric_limits<EdgeWeight>::max();
|
||||||
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
|
static const EdgeDuration MAXIMAL_EDGE_DURATION = std::numeric_limits<EdgeDuration>::max();
|
||||||
|
static const EdgeDistance MAXIMAL_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
static const TurnPenalty INVALID_TURN_PENALTY = std::numeric_limits<TurnPenalty>::max();
|
||||||
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
static const EdgeDistance INVALID_EDGE_DISTANCE = std::numeric_limits<EdgeDistance>::max();
|
||||||
|
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "osrm",
|
"name": "osrm",
|
||||||
"version": "5.19.0",
|
"version": "5.20.0-alpha.1",
|
||||||
"private": false,
|
"private": false,
|
||||||
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
"description": "The Open Source Routing Machine is a high performance routing engine written in C++14 designed to run on OpenStreetMap data.",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
|
|||||||
@@ -120,9 +120,6 @@ function setup()
|
|||||||
|
|
||||||
-- classes to support for exclude flags
|
-- classes to support for exclude flags
|
||||||
excludable = Sequence {
|
excludable = Sequence {
|
||||||
Set {'toll'},
|
|
||||||
Set {'motorway'},
|
|
||||||
Set {'ferry'}
|
|
||||||
},
|
},
|
||||||
|
|
||||||
avoid = Set {
|
avoid = Set {
|
||||||
|
|||||||
@@ -102,6 +102,7 @@ int Contractor::Run()
|
|||||||
QueryGraph query_graph;
|
QueryGraph query_graph;
|
||||||
std::vector<std::vector<bool>> edge_filters;
|
std::vector<std::vector<bool>> edge_filters;
|
||||||
std::vector<std::vector<bool>> cores;
|
std::vector<std::vector<bool>> cores;
|
||||||
|
|
||||||
std::tie(query_graph, edge_filters) = contractExcludableGraph(
|
std::tie(query_graph, edge_filters) = contractExcludableGraph(
|
||||||
toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)),
|
toContractorGraph(number_of_edge_based_nodes, std::move(edge_based_edge_list)),
|
||||||
std::move(node_weights),
|
std::move(node_weights),
|
||||||
|
|||||||
@@ -215,6 +215,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
target,
|
target,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@@ -225,6 +226,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
source,
|
source,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@@ -280,6 +282,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
target,
|
target,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@@ -290,6 +293,7 @@ void ContractNode(ContractorThreadData *data,
|
|||||||
source,
|
source,
|
||||||
path_weight,
|
path_weight,
|
||||||
in_data.duration + out_data.duration,
|
in_data.duration + out_data.duration,
|
||||||
|
in_data.distance + out_data.distance,
|
||||||
out_data.originalEdges + in_data.originalEdges,
|
out_data.originalEdges + in_data.originalEdges,
|
||||||
node,
|
node,
|
||||||
SHORTCUT_ARC,
|
SHORTCUT_ARC,
|
||||||
@@ -556,7 +560,7 @@ bool IsNodeIndependent(const util::XORFastHash<> &hash,
|
|||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
std::vector<bool> contractGraph(ContractorGraph &graph,
|
std::vector<bool> contractGraph(ContractorGraph &graph,
|
||||||
std::vector<bool> node_is_uncontracted_,
|
std::vector<bool> node_is_uncontracted_,
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ void alternativeRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// check whether there is a loop present at the node
|
// check whether there is a loop present at the node
|
||||||
const auto loop_weight = getLoopWeight<false>(facade, node);
|
const auto loop_weight = std::get<0>(getLoopWeight<false>(facade, node));
|
||||||
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
const EdgeWeight new_weight_with_loop = new_weight + loop_weight;
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
if (loop_weight != INVALID_EDGE_WEIGHT &&
|
||||||
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
new_weight_with_loop <= *upper_bound_to_shortest_path_weight)
|
||||||
@@ -558,7 +558,7 @@ bool viaNodeCandidatePassesTTest(SearchEngineData<Algorithm> &engine_working_dat
|
|||||||
}
|
}
|
||||||
return (upper_bound <= t_test_path_weight);
|
return (upper_bound <= t_test_path_weight);
|
||||||
}
|
}
|
||||||
} // anon. namespace
|
} // namespace
|
||||||
|
|
||||||
InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engine_working_data,
|
||||||
const DataFacade<Algorithm> &facade,
|
const DataFacade<Algorithm> &facade,
|
||||||
@@ -853,4 +853,4 @@ InternalManyRoutesResult alternativePathSearch(SearchEngineData<Algorithm> &engi
|
|||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm}
|
} // namespace osrm
|
||||||
|
|||||||
@@ -21,18 +21,21 @@ namespace ch
|
|||||||
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
|
inline bool addLoopWeight(const DataFacade<ch::Algorithm> &facade,
|
||||||
const NodeID node,
|
const NodeID node,
|
||||||
EdgeWeight &weight,
|
EdgeWeight &weight,
|
||||||
EdgeDuration &duration)
|
EdgeDuration &duration,
|
||||||
|
EdgeDistance &distance)
|
||||||
{ // Special case for CH when contractor creates a loop edge node->node
|
{ // Special case for CH when contractor creates a loop edge node->node
|
||||||
BOOST_ASSERT(weight < 0);
|
BOOST_ASSERT(weight < 0);
|
||||||
|
|
||||||
const auto loop_weight = ch::getLoopWeight<false>(facade, node);
|
const auto loop_weight = ch::getLoopWeight<false>(facade, node);
|
||||||
if (loop_weight != INVALID_EDGE_WEIGHT)
|
if (std::get<0>(loop_weight) != INVALID_EDGE_WEIGHT)
|
||||||
{
|
{
|
||||||
const auto new_weight_with_loop = weight + loop_weight;
|
const auto new_weight_with_loop = weight + std::get<0>(loop_weight);
|
||||||
if (new_weight_with_loop >= 0)
|
if (new_weight_with_loop >= 0)
|
||||||
{
|
{
|
||||||
weight = new_weight_with_loop;
|
weight = new_weight_with_loop;
|
||||||
duration += ch::getLoopWeight<true>(facade, node);
|
auto result = ch::getLoopWeight<true>(facade, node);
|
||||||
|
duration += std::get<0>(result);
|
||||||
|
distance += std::get<1>(result);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -46,6 +49,7 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeDuration duration,
|
const EdgeDuration duration,
|
||||||
|
const EdgeDistance distance,
|
||||||
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
const PhantomNode &)
|
const PhantomNode &)
|
||||||
{
|
{
|
||||||
@@ -63,21 +67,23 @@ void relaxOutgoingEdges(const DataFacade<Algorithm> &facade,
|
|||||||
const auto edge_weight = data.weight;
|
const auto edge_weight = data.weight;
|
||||||
|
|
||||||
const auto edge_duration = data.duration;
|
const auto edge_duration = data.duration;
|
||||||
|
const auto edge_distance = data.distance;
|
||||||
|
|
||||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||||
const auto to_weight = weight + edge_weight;
|
const auto to_weight = weight + edge_weight;
|
||||||
const auto to_duration = duration + edge_duration;
|
const auto to_duration = duration + edge_duration;
|
||||||
|
const auto to_distance = distance + edge_distance;
|
||||||
|
|
||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, to_duration});
|
query_heap.Insert(to, to_weight, {node, to_duration, to_distance});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration) <
|
else if (std::tie(to_weight, to_duration) <
|
||||||
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
|
std::tie(query_heap.GetKey(to), query_heap.GetData(to).duration))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, to_duration};
|
query_heap.GetData(to) = {node, to_duration, to_distance};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -91,12 +97,14 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const std::vector<NodeBucket> &search_space_with_buckets,
|
const std::vector<NodeBucket> &search_space_with_buckets,
|
||||||
std::vector<EdgeWeight> &weights_table,
|
std::vector<EdgeWeight> &weights_table,
|
||||||
std::vector<EdgeDuration> &durations_table,
|
std::vector<EdgeDuration> &durations_table,
|
||||||
|
std::vector<EdgeDistance> &distances_table,
|
||||||
std::vector<NodeID> &middle_nodes_table,
|
std::vector<NodeID> &middle_nodes_table,
|
||||||
const PhantomNode &phantom_node)
|
const PhantomNode &phantom_node)
|
||||||
{
|
{
|
||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
const auto source_weight = query_heap.GetKey(node);
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto source_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto source_distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
@@ -109,20 +117,24 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto column_index = current_bucket.column_index;
|
const auto column_index = current_bucket.column_index;
|
||||||
const auto target_weight = current_bucket.weight;
|
const auto target_weight = current_bucket.weight;
|
||||||
const auto target_duration = current_bucket.duration;
|
const auto target_duration = current_bucket.duration;
|
||||||
|
const auto target_distance = current_bucket.distance;
|
||||||
|
|
||||||
auto ¤t_weight = weights_table[row_index * number_of_targets + column_index];
|
auto ¤t_weight = weights_table[row_index * number_of_targets + column_index];
|
||||||
auto ¤t_duration = durations_table[row_index * number_of_targets + column_index];
|
auto ¤t_duration = durations_table[row_index * number_of_targets + column_index];
|
||||||
|
auto ¤t_distance = distances_table[row_index * number_of_targets + column_index];
|
||||||
|
|
||||||
// Check if new weight is better
|
// Check if new weight is better
|
||||||
auto new_weight = source_weight + target_weight;
|
auto new_weight = source_weight + target_weight;
|
||||||
auto new_duration = source_duration + target_duration;
|
auto new_duration = source_duration + target_duration;
|
||||||
|
auto new_distance = source_distance + target_distance;
|
||||||
|
|
||||||
if (new_weight < 0)
|
if (new_weight < 0)
|
||||||
{
|
{
|
||||||
if (addLoopWeight(facade, node, new_weight, new_duration))
|
if (addLoopWeight(facade, node, new_weight, new_duration, new_distance))
|
||||||
{
|
{
|
||||||
current_weight = std::min(current_weight, new_weight);
|
current_weight = std::min(current_weight, new_weight);
|
||||||
current_duration = std::min(current_duration, new_duration);
|
current_duration = std::min(current_duration, new_duration);
|
||||||
|
current_distance = std::min(current_distance, new_distance);
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -130,12 +142,13 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
{
|
{
|
||||||
current_weight = new_weight;
|
current_weight = new_weight;
|
||||||
current_duration = new_duration;
|
current_duration = new_duration;
|
||||||
|
current_distance = new_distance;
|
||||||
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
middle_nodes_table[row_index * number_of_targets + column_index] = node;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<FORWARD_DIRECTION>(
|
relaxOutgoingEdges<FORWARD_DIRECTION>(
|
||||||
facade, node, source_weight, source_duration, query_heap, phantom_node);
|
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
||||||
@@ -147,14 +160,15 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
const auto target_weight = query_heap.GetKey(node);
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto target_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto target_distance = query_heap.GetData(node).distance;
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
const auto parent = query_heap.GetData(node).parent;
|
||||||
|
|
||||||
// Store settled nodes in search space bucket
|
// Store settled nodes in search space bucket
|
||||||
search_space_with_buckets.emplace_back(
|
search_space_with_buckets.emplace_back(
|
||||||
node, parent, column_index, target_weight, target_duration);
|
node, parent, column_index, target_weight, target_duration, target_distance);
|
||||||
|
|
||||||
relaxOutgoingEdges<REVERSE_DIRECTION>(
|
relaxOutgoingEdges<REVERSE_DIRECTION>(
|
||||||
facade, node, target_weight, target_duration, query_heap, phantom_node);
|
facade, node, target_weight, target_duration, target_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
@@ -235,79 +249,17 @@ void calculateDistances(typename SearchEngineData<ch::Algorithm>::ManyToManyQuer
|
|||||||
needsLoopBackwards(source_phantom, target_phantom)))
|
needsLoopBackwards(source_phantom, target_phantom)))
|
||||||
{
|
{
|
||||||
auto weight = ch::getLoopWeight<false>(facade, packed_leg.front());
|
auto weight = ch::getLoopWeight<false>(facade, packed_leg.front());
|
||||||
if (weight != INVALID_EDGE_WEIGHT)
|
if (std::get<0>(weight) != INVALID_EDGE_WEIGHT)
|
||||||
packed_leg.push_back(packed_leg.front());
|
packed_leg.push_back(packed_leg.front());
|
||||||
}
|
}
|
||||||
if (!packed_leg.empty())
|
if (!packed_leg.empty())
|
||||||
{
|
{
|
||||||
auto annotation =
|
EdgeDistance annotation =
|
||||||
ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end());
|
ch::calculateEBGNodeAnnotations(facade, packed_leg.begin(), packed_leg.end());
|
||||||
|
annotation = adjustPathDistanceToPhantomNodes(
|
||||||
|
packed_leg, source_phantom, target_phantom, annotation);
|
||||||
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = annotation;
|
distances_table[row_index * number_of_targets + column_index] = annotation;
|
||||||
|
|
||||||
// check the direction of travel to figure out how to calculate the offset to/from
|
|
||||||
// the source/target
|
|
||||||
if (source_phantom.forward_segment_id.id == packed_leg.front())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// -->s <-- subtract offset to start at source
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = source_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] -= offset;
|
|
||||||
}
|
|
||||||
else if (source_phantom.reverse_segment_id.id == packed_leg.front())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// s<------- <-- subtract offset to start at source
|
|
||||||
// ... <-- want this distance
|
|
||||||
// entry 0---1---2---3 <-- 3 is exit node
|
|
||||||
EdgeDistance offset = source_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] -= offset;
|
|
||||||
}
|
|
||||||
if (target_phantom.forward_segment_id.id == packed_leg.back())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// ++>t <-- add offset to get to target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = target_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] += offset;
|
|
||||||
}
|
|
||||||
else if (target_phantom.reverse_segment_id.id == packed_leg.back())
|
|
||||||
{
|
|
||||||
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
|
||||||
// <++t <-- add offset to get from target
|
|
||||||
// ................ <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset = target_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] += offset;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// there is no shortcut to unpack. source and target are on the same EBG Node.
|
|
||||||
// if the offset of the target is greater than the offset of the source, subtract it
|
|
||||||
if (target_phantom.GetForwardDistance() > source_phantom.GetForwardDistance())
|
|
||||||
{
|
|
||||||
// --------->t <-- offsets
|
|
||||||
// ->s <-- subtract source offset from target offset
|
|
||||||
// ......... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset =
|
|
||||||
target_phantom.GetForwardDistance() - source_phantom.GetForwardDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = offset;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// s<--- <-- offsets
|
|
||||||
// t<--------- <-- subtract source offset from target offset
|
|
||||||
// ...... <-- want this distance as result
|
|
||||||
// entry 0---1---2---3--- <-- 3 is exit node
|
|
||||||
EdgeDistance offset =
|
|
||||||
target_phantom.GetReverseDistance() - source_phantom.GetReverseDistance();
|
|
||||||
distances_table[row_index * number_of_targets + column_index] = offset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
packed_leg.clear();
|
packed_leg.clear();
|
||||||
}
|
}
|
||||||
@@ -331,7 +283,7 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
|
|
||||||
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights_table(number_of_entries, INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeDuration> durations_table(number_of_entries, MAXIMAL_EDGE_DURATION);
|
||||||
std::vector<EdgeDistance> distances_table;
|
std::vector<EdgeDistance> distances_table(number_of_entries, MAXIMAL_EDGE_DISTANCE);
|
||||||
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
std::vector<NodeID> middle_nodes_table(number_of_entries, SPECIAL_NODEID);
|
||||||
|
|
||||||
std::vector<NodeBucket> search_space_with_buckets;
|
std::vector<NodeBucket> search_space_with_buckets;
|
||||||
@@ -380,6 +332,7 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
search_space_with_buckets,
|
search_space_with_buckets,
|
||||||
weights_table,
|
weights_table,
|
||||||
durations_table,
|
durations_table,
|
||||||
|
distances_table,
|
||||||
middle_nodes_table,
|
middle_nodes_table,
|
||||||
source_phantom);
|
source_phantom);
|
||||||
}
|
}
|
||||||
@@ -387,17 +340,21 @@ manyToManySearch(SearchEngineData<ch::Algorithm> &engine_working_data,
|
|||||||
if (calculate_distance)
|
if (calculate_distance)
|
||||||
{
|
{
|
||||||
distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
|
distances_table.resize(number_of_entries, INVALID_EDGE_DISTANCE);
|
||||||
calculateDistances(query_heap,
|
// TODO: this is a hack to work around stuff
|
||||||
facade,
|
if (number_of_entries == 0)
|
||||||
phantom_nodes,
|
{
|
||||||
target_indices,
|
calculateDistances(query_heap,
|
||||||
row_index,
|
facade,
|
||||||
source_index,
|
phantom_nodes,
|
||||||
source_phantom,
|
target_indices,
|
||||||
number_of_targets,
|
row_index,
|
||||||
search_space_with_buckets,
|
source_index,
|
||||||
distances_table,
|
source_phantom,
|
||||||
middle_nodes_table);
|
number_of_targets,
|
||||||
|
search_space_with_buckets,
|
||||||
|
distances_table,
|
||||||
|
middle_nodes_table);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const NodeID node,
|
const NodeID node,
|
||||||
const EdgeWeight weight,
|
const EdgeWeight weight,
|
||||||
const EdgeDuration duration,
|
const EdgeDuration duration,
|
||||||
|
const EdgeDistance /* distance TODO use this */,
|
||||||
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
typename SearchEngineData<mld::Algorithm>::ManyToManyQueryHeap &query_heap,
|
||||||
Args... args)
|
Args... args)
|
||||||
{
|
{
|
||||||
@@ -77,14 +78,14 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration});
|
query_heap.Insert(to, to_weight, {node, true, to_duration, 0});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(query_heap.GetKey(to),
|
||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration};
|
query_heap.GetData(to) = {node, true, to_duration, 0};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -109,14 +110,14 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
const auto to_duration = duration + shortcut_durations.front();
|
const auto to_duration = duration + shortcut_durations.front();
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, true, to_duration});
|
query_heap.Insert(to, to_weight, {node, true, to_duration, 0});
|
||||||
}
|
}
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, node) <
|
||||||
std::tie(query_heap.GetKey(to),
|
std::tie(query_heap.GetKey(to),
|
||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, true, to_duration};
|
query_heap.GetData(to) = {node, true, to_duration, 0};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -153,7 +154,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
// New Node discovered -> Add to Heap + Node Info Storage
|
// New Node discovered -> Add to Heap + Node Info Storage
|
||||||
if (!query_heap.WasInserted(to))
|
if (!query_heap.WasInserted(to))
|
||||||
{
|
{
|
||||||
query_heap.Insert(to, to_weight, {node, false, to_duration});
|
query_heap.Insert(to, to_weight, {node, false, to_duration, 0});
|
||||||
}
|
}
|
||||||
// Found a shorter Path -> Update weight and set new parent
|
// Found a shorter Path -> Update weight and set new parent
|
||||||
else if (std::tie(to_weight, to_duration, node) <
|
else if (std::tie(to_weight, to_duration, node) <
|
||||||
@@ -161,7 +162,7 @@ void relaxOutgoingEdges(const DataFacade<mld::Algorithm> &facade,
|
|||||||
query_heap.GetData(to).duration,
|
query_heap.GetData(to).duration,
|
||||||
query_heap.GetData(to).parent))
|
query_heap.GetData(to).parent))
|
||||||
{
|
{
|
||||||
query_heap.GetData(to) = {node, false, to_duration};
|
query_heap.GetData(to) = {node, false, to_duration, 0};
|
||||||
query_heap.DecreaseKey(to, to_weight);
|
query_heap.DecreaseKey(to, to_weight);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -178,15 +179,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const std::vector<PhantomNode> &phantom_nodes,
|
const std::vector<PhantomNode> &phantom_nodes,
|
||||||
std::size_t phantom_index,
|
std::size_t phantom_index,
|
||||||
const std::vector<std::size_t> &phantom_indices,
|
const std::vector<std::size_t> &phantom_indices,
|
||||||
const bool calculate_distance)
|
const bool /* calculate_distance */)
|
||||||
{
|
{
|
||||||
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
|
std::vector<EdgeWeight> weights(phantom_indices.size(), INVALID_EDGE_WEIGHT);
|
||||||
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
|
std::vector<EdgeDuration> durations(phantom_indices.size(), MAXIMAL_EDGE_DURATION);
|
||||||
std::vector<EdgeDistance> distances_table;
|
std::vector<EdgeDistance> distances_table(phantom_indices.size(), MAXIMAL_EDGE_DISTANCE);
|
||||||
std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID);
|
std::vector<NodeID> middle_nodes_table(phantom_indices.size(), SPECIAL_NODEID);
|
||||||
|
|
||||||
// Collect destination (source) nodes into a map
|
// Collect destination (source) nodes into a map
|
||||||
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration>>
|
std::unordered_multimap<NodeID, std::tuple<std::size_t, EdgeWeight, EdgeDuration, EdgeDistance>>
|
||||||
target_nodes_index;
|
target_nodes_index;
|
||||||
target_nodes_index.reserve(phantom_indices.size());
|
target_nodes_index.reserve(phantom_indices.size());
|
||||||
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
|
for (std::size_t index = 0; index < phantom_indices.size(); ++index)
|
||||||
@@ -201,13 +202,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{phantom_node.forward_segment_id.id,
|
{phantom_node.forward_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
phantom_node.GetForwardDuration())});
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance())});
|
||||||
if (phantom_node.IsValidReverseTarget())
|
if (phantom_node.IsValidReverseTarget())
|
||||||
target_nodes_index.insert(
|
target_nodes_index.insert(
|
||||||
{phantom_node.reverse_segment_id.id,
|
{phantom_node.reverse_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
phantom_node.GetReverseDuration())});
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance())});
|
||||||
}
|
}
|
||||||
else if (DIRECTION == REVERSE_DIRECTION)
|
else if (DIRECTION == REVERSE_DIRECTION)
|
||||||
{
|
{
|
||||||
@@ -216,13 +219,15 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{phantom_node.forward_segment_id.id,
|
{phantom_node.forward_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
-phantom_node.GetForwardDuration())});
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance())});
|
||||||
if (phantom_node.IsValidReverseSource())
|
if (phantom_node.IsValidReverseSource())
|
||||||
target_nodes_index.insert(
|
target_nodes_index.insert(
|
||||||
{phantom_node.reverse_segment_id.id,
|
{phantom_node.reverse_segment_id.id,
|
||||||
std::make_tuple(index,
|
std::make_tuple(index,
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
-phantom_node.GetReverseDuration())});
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance())});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -232,44 +237,50 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
auto &query_heap = *(engine_working_data.many_to_many_heap);
|
||||||
|
|
||||||
// Check if node is in the destinations list and update weights/durations
|
// Check if node is in the destinations list and update weights/durations
|
||||||
auto update_values = [&](NodeID node, EdgeWeight weight, EdgeDuration duration) {
|
auto update_values =
|
||||||
auto candidates = target_nodes_index.equal_range(node);
|
[&](NodeID node, EdgeWeight weight, EdgeDuration duration, EdgeDistance distance) {
|
||||||
for (auto it = candidates.first; it != candidates.second;)
|
auto candidates = target_nodes_index.equal_range(node);
|
||||||
{
|
for (auto it = candidates.first; it != candidates.second;)
|
||||||
std::size_t index;
|
|
||||||
EdgeWeight target_weight;
|
|
||||||
EdgeDuration target_duration;
|
|
||||||
std::tie(index, target_weight, target_duration) = it->second;
|
|
||||||
|
|
||||||
const auto path_weight = weight + target_weight;
|
|
||||||
if (path_weight >= 0)
|
|
||||||
{
|
{
|
||||||
const auto path_duration = duration + target_duration;
|
std::size_t index;
|
||||||
|
EdgeWeight target_weight;
|
||||||
|
EdgeDuration target_duration;
|
||||||
|
EdgeDuration target_distance;
|
||||||
|
std::tie(index, target_weight, target_duration, target_distance) = it->second;
|
||||||
|
|
||||||
if (std::tie(path_weight, path_duration) <
|
const auto path_weight = weight + target_weight;
|
||||||
std::tie(weights[index], durations[index]))
|
if (path_weight >= 0)
|
||||||
{
|
{
|
||||||
weights[index] = path_weight;
|
const auto path_duration = duration + target_duration;
|
||||||
durations[index] = path_duration;
|
const auto path_distance = distance + target_distance;
|
||||||
middle_nodes_table[index] = node;
|
|
||||||
|
if (std::tie(path_weight, path_duration) <
|
||||||
|
std::tie(weights[index], durations[index]))
|
||||||
|
{
|
||||||
|
weights[index] = path_weight;
|
||||||
|
durations[index] = path_duration;
|
||||||
|
distances_table[index] = path_distance;
|
||||||
|
middle_nodes_table[index] = node;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove node from destinations list
|
||||||
|
it = target_nodes_index.erase(it);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
++it;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove node from destinations list
|
|
||||||
it = target_nodes_index.erase(it);
|
|
||||||
}
|
}
|
||||||
else
|
};
|
||||||
{
|
|
||||||
++it;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
auto insert_node = [&](NodeID node, EdgeWeight initial_weight, EdgeDuration initial_duration) {
|
|
||||||
|
|
||||||
|
auto insert_node = [&](NodeID node,
|
||||||
|
EdgeWeight initial_weight,
|
||||||
|
EdgeDuration initial_duration,
|
||||||
|
EdgeDistance initial_distance) {
|
||||||
// Update single node paths
|
// Update single node paths
|
||||||
update_values(node, initial_weight, initial_duration);
|
update_values(node, initial_weight, initial_duration, initial_distance);
|
||||||
|
|
||||||
query_heap.Insert(node, initial_weight, {node, initial_duration});
|
query_heap.Insert(node, initial_weight, {node, initial_duration, initial_distance});
|
||||||
|
|
||||||
// Place adjacent nodes into heap
|
// Place adjacent nodes into heap
|
||||||
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
for (auto edge : facade.GetAdjacentEdgeRange(node))
|
||||||
@@ -292,8 +303,9 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
facade.GetWeightPenaltyForEdgeID(turn_id);
|
facade.GetWeightPenaltyForEdgeID(turn_id);
|
||||||
const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) +
|
const auto edge_duration = initial_duration + facade.GetNodeDuration(node_id) +
|
||||||
facade.GetDurationPenaltyForEdgeID(turn_id);
|
facade.GetDurationPenaltyForEdgeID(turn_id);
|
||||||
|
const auto edge_distance = initial_distance;
|
||||||
|
|
||||||
query_heap.Insert(to, edge_weight, {node, edge_duration});
|
query_heap.Insert(to, edge_weight, {node, edge_duration, edge_distance});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -307,14 +319,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
insert_node(phantom_node.forward_segment_id.id,
|
insert_node(phantom_node.forward_segment_id.id,
|
||||||
-phantom_node.GetForwardWeightPlusOffset(),
|
-phantom_node.GetForwardWeightPlusOffset(),
|
||||||
-phantom_node.GetForwardDuration());
|
-phantom_node.GetForwardDuration(),
|
||||||
|
-phantom_node.GetForwardDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom_node.IsValidReverseSource())
|
if (phantom_node.IsValidReverseSource())
|
||||||
{
|
{
|
||||||
insert_node(phantom_node.reverse_segment_id.id,
|
insert_node(phantom_node.reverse_segment_id.id,
|
||||||
-phantom_node.GetReverseWeightPlusOffset(),
|
-phantom_node.GetReverseWeightPlusOffset(),
|
||||||
-phantom_node.GetReverseDuration());
|
-phantom_node.GetReverseDuration(),
|
||||||
|
-phantom_node.GetReverseDistance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (DIRECTION == REVERSE_DIRECTION)
|
else if (DIRECTION == REVERSE_DIRECTION)
|
||||||
@@ -323,14 +337,16 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
insert_node(phantom_node.forward_segment_id.id,
|
insert_node(phantom_node.forward_segment_id.id,
|
||||||
phantom_node.GetForwardWeightPlusOffset(),
|
phantom_node.GetForwardWeightPlusOffset(),
|
||||||
phantom_node.GetForwardDuration());
|
phantom_node.GetForwardDuration(),
|
||||||
|
phantom_node.GetForwardDistance());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (phantom_node.IsValidReverseTarget())
|
if (phantom_node.IsValidReverseTarget())
|
||||||
{
|
{
|
||||||
insert_node(phantom_node.reverse_segment_id.id,
|
insert_node(phantom_node.reverse_segment_id.id,
|
||||||
phantom_node.GetReverseWeightPlusOffset(),
|
phantom_node.GetReverseWeightPlusOffset(),
|
||||||
phantom_node.GetReverseDuration());
|
phantom_node.GetReverseDuration(),
|
||||||
|
phantom_node.GetReverseDistance());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -341,22 +357,26 @@ oneToManySearch(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto weight = query_heap.GetKey(node);
|
const auto weight = query_heap.GetKey(node);
|
||||||
const auto duration = query_heap.GetData(node).duration;
|
const auto duration = query_heap.GetData(node).duration;
|
||||||
|
const auto distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Update values
|
// Update values
|
||||||
update_values(node, weight, duration);
|
update_values(node, weight, duration, distance);
|
||||||
|
|
||||||
// Relax outgoing edges
|
// Relax outgoing edges
|
||||||
relaxOutgoingEdges<DIRECTION>(facade,
|
relaxOutgoingEdges<DIRECTION>(facade,
|
||||||
node,
|
node,
|
||||||
weight,
|
weight,
|
||||||
duration,
|
duration,
|
||||||
|
distance,
|
||||||
query_heap,
|
query_heap,
|
||||||
phantom_nodes,
|
phantom_nodes,
|
||||||
phantom_index,
|
phantom_index,
|
||||||
phantom_indices);
|
phantom_indices);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (calculate_distance)
|
// TODO: re-enable this if we need to fallback
|
||||||
|
// if (calculate_distance)
|
||||||
|
if (false)
|
||||||
{
|
{
|
||||||
// Initialize unpacking heaps
|
// Initialize unpacking heaps
|
||||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||||
@@ -497,6 +517,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto source_weight = query_heap.GetKey(node);
|
const auto source_weight = query_heap.GetKey(node);
|
||||||
const auto source_duration = query_heap.GetData(node).duration;
|
const auto source_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto source_distance = query_heap.GetData(node).distance;
|
||||||
|
|
||||||
// Check if each encountered node has an entry
|
// Check if each encountered node has an entry
|
||||||
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
const auto &bucket_list = std::equal_range(search_space_with_buckets.begin(),
|
||||||
@@ -533,7 +554,7 @@ void forwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
}
|
}
|
||||||
|
|
||||||
relaxOutgoingEdges<DIRECTION>(
|
relaxOutgoingEdges<DIRECTION>(
|
||||||
facade, node, source_weight, source_duration, query_heap, phantom_node);
|
facade, node, source_weight, source_duration, source_distance, query_heap, phantom_node);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
@@ -546,6 +567,7 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto node = query_heap.DeleteMin();
|
const auto node = query_heap.DeleteMin();
|
||||||
const auto target_weight = query_heap.GetKey(node);
|
const auto target_weight = query_heap.GetKey(node);
|
||||||
const auto target_duration = query_heap.GetData(node).duration;
|
const auto target_duration = query_heap.GetData(node).duration;
|
||||||
|
const auto target_distance = query_heap.GetData(node).distance;
|
||||||
const auto parent = query_heap.GetData(node).parent;
|
const auto parent = query_heap.GetData(node).parent;
|
||||||
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
|
const auto from_clique_arc = query_heap.GetData(node).from_clique_arc;
|
||||||
|
|
||||||
@@ -556,8 +578,14 @@ void backwardRoutingStep(const DataFacade<Algorithm> &facade,
|
|||||||
const auto &partition = facade.GetMultiLevelPartition();
|
const auto &partition = facade.GetMultiLevelPartition();
|
||||||
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
const auto maximal_level = partition.GetNumberOfLevels() - 1;
|
||||||
|
|
||||||
relaxOutgoingEdges<!DIRECTION>(
|
relaxOutgoingEdges<!DIRECTION>(facade,
|
||||||
facade, node, target_weight, target_duration, query_heap, phantom_node, maximal_level);
|
node,
|
||||||
|
target_weight,
|
||||||
|
target_duration,
|
||||||
|
target_distance,
|
||||||
|
query_heap,
|
||||||
|
phantom_node,
|
||||||
|
maximal_level);
|
||||||
}
|
}
|
||||||
|
|
||||||
template <bool DIRECTION>
|
template <bool DIRECTION>
|
||||||
|
|||||||
@@ -227,6 +227,9 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
{
|
{
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
forward_heap.Clear();
|
||||||
|
const auto &source_phantom = prev_unbroken_timestamps_list[s].phantom_node;
|
||||||
|
insertSourceInHeap(forward_heap, source_phantom);
|
||||||
|
|
||||||
for (const auto s_prime : util::irange<std::size_t>(0UL, current_viterbi.size()))
|
for (const auto s_prime : util::irange<std::size_t>(0UL, current_viterbi.size()))
|
||||||
{
|
{
|
||||||
@@ -237,14 +240,19 @@ SubMatchingList mapMatching(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
double network_distance =
|
reverse_heap.Clear();
|
||||||
getNetworkDistance(engine_working_data,
|
const auto &target_phantom = current_timestamps_list[s_prime].phantom_node;
|
||||||
facade,
|
insertTargetInHeap(reverse_heap, target_phantom);
|
||||||
forward_heap,
|
|
||||||
reverse_heap,
|
double network_distance = getNetworkDistance(engine_working_data,
|
||||||
prev_unbroken_timestamps_list[s].phantom_node,
|
facade,
|
||||||
current_timestamps_list[s_prime].phantom_node,
|
forward_heap,
|
||||||
weight_upper_bound);
|
reverse_heap,
|
||||||
|
source_phantom,
|
||||||
|
target_phantom,
|
||||||
|
weight_upper_bound);
|
||||||
|
|
||||||
|
network_distance = std::round(network_distance * 10) / 10;
|
||||||
|
|
||||||
// get distance diff between loc1/2 and locs/s_prime
|
// get distance diff between loc1/2 and locs/s_prime
|
||||||
const auto d_t = std::abs(network_distance - haversine_distance);
|
const auto d_t = std::abs(network_distance - haversine_distance);
|
||||||
|
|||||||
@@ -33,6 +33,79 @@ bool needsLoopBackwards(const PhantomNodes &phantoms)
|
|||||||
return needsLoopBackwards(phantoms.source_phantom, phantoms.target_phantom);
|
return needsLoopBackwards(phantoms.source_phantom, phantoms.target_phantom);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
EdgeDistance adjustPathDistanceToPhantomNodes(const std::vector<NodeID> &path,
|
||||||
|
const PhantomNode &source_phantom,
|
||||||
|
const PhantomNode &target_phantom,
|
||||||
|
const EdgeDistance uncorrected_distance)
|
||||||
|
{
|
||||||
|
EdgeDistance distance = uncorrected_distance;
|
||||||
|
if (!path.empty())
|
||||||
|
{
|
||||||
|
|
||||||
|
// check the direction of travel to figure out how to calculate the offset to/from
|
||||||
|
// the source/target
|
||||||
|
if (source_phantom.forward_segment_id.id == path.front())
|
||||||
|
{
|
||||||
|
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
||||||
|
// -->s <-- subtract offset to start at source
|
||||||
|
// ......... <-- want this distance as result
|
||||||
|
// entry 0---1---2---3--- <-- 3 is exit node
|
||||||
|
distance -= source_phantom.GetForwardDistance();
|
||||||
|
}
|
||||||
|
else if (source_phantom.reverse_segment_id.id == path.front())
|
||||||
|
{
|
||||||
|
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
||||||
|
// s<------- <-- subtract offset to start at source
|
||||||
|
// ... <-- want this distance
|
||||||
|
// entry 0---1---2---3 <-- 3 is exit node
|
||||||
|
distance -= source_phantom.GetReverseDistance();
|
||||||
|
}
|
||||||
|
if (target_phantom.forward_segment_id.id == path.back())
|
||||||
|
{
|
||||||
|
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
||||||
|
// ++>t <-- add offset to get to target
|
||||||
|
// ................ <-- want this distance as result
|
||||||
|
// entry 0---1---2---3--- <-- 3 is exit node
|
||||||
|
distance += target_phantom.GetForwardDistance();
|
||||||
|
}
|
||||||
|
else if (target_phantom.reverse_segment_id.id == path.back())
|
||||||
|
{
|
||||||
|
// ............ <-- calculateEGBAnnotation returns distance from 0 to 3
|
||||||
|
// <++t <-- add offset to get from target
|
||||||
|
// ................ <-- want this distance as result
|
||||||
|
// entry 0---1---2---3--- <-- 3 is exit node
|
||||||
|
distance += target_phantom.GetReverseDistance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// there is no shortcut to unpack. source and target are on the same EBG Node.
|
||||||
|
// if the offset of the target is greater than the offset of the source, subtract it
|
||||||
|
if (target_phantom.GetForwardDistance() > source_phantom.GetForwardDistance())
|
||||||
|
{
|
||||||
|
// --------->t <-- offsets
|
||||||
|
// ->s <-- subtract source offset from target offset
|
||||||
|
// ......... <-- want this distance as result
|
||||||
|
// entry 0---1---2---3--- <-- 3 is exit node
|
||||||
|
distance = target_phantom.GetForwardDistance() - source_phantom.GetForwardDistance();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// s<--- <-- offsets
|
||||||
|
// t<--------- <-- subtract source offset from target offset
|
||||||
|
// ...... <-- want this distance as result
|
||||||
|
// entry 0---1---2---3--- <-- 3 is exit node
|
||||||
|
distance = target_phantom.GetReverseDistance() - source_phantom.GetReverseDistance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
BOOST_ASSERT_MSG(distance >= 0 || distance > -1.0f,
|
||||||
|
"Distance correction generated negative number");
|
||||||
|
// guard against underflow errors caused by rounding
|
||||||
|
distance = std::max(EdgeDistance{0}, distance);
|
||||||
|
return distance;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace routing_algorithms
|
} // namespace routing_algorithms
|
||||||
} // namespace engine
|
} // namespace engine
|
||||||
} // namespace osrm
|
} // namespace osrm
|
||||||
|
|||||||
@@ -100,7 +100,7 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
|
|||||||
const PhantomNodes & /*phantom_nodes*/,
|
const PhantomNodes & /*phantom_nodes*/,
|
||||||
const EdgeWeight weight_upper_bound)
|
const EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
if (forward_heap.Empty() || reverse_heap.Empty())
|
if (forward_heap.Empty() && reverse_heap.Empty())
|
||||||
{
|
{
|
||||||
weight = INVALID_EDGE_WEIGHT;
|
weight = INVALID_EDGE_WEIGHT;
|
||||||
return;
|
return;
|
||||||
@@ -110,10 +110,14 @@ void search(SearchEngineData<Algorithm> & /*engine_working_data*/,
|
|||||||
weight = weight_upper_bound;
|
weight = weight_upper_bound;
|
||||||
|
|
||||||
// get offset to account for offsets on phantom nodes on compressed edges
|
// get offset to account for offsets on phantom nodes on compressed edges
|
||||||
const auto min_edge_offset = std::min(0, forward_heap.MinKey());
|
EdgeWeight min_edge_offset = 0;
|
||||||
BOOST_ASSERT(min_edge_offset <= 0);
|
if (forward_heap.Size() > 0)
|
||||||
|
{
|
||||||
|
min_edge_offset = std::min(min_edge_offset, forward_heap.MinKey());
|
||||||
|
BOOST_ASSERT(min_edge_offset <= 0);
|
||||||
|
}
|
||||||
// we only every insert negative offsets for nodes in the forward heap
|
// we only every insert negative offsets for nodes in the forward heap
|
||||||
BOOST_ASSERT(reverse_heap.MinKey() >= 0);
|
BOOST_ASSERT(reverse_heap.Empty() || reverse_heap.MinKey() >= 0);
|
||||||
|
|
||||||
// run two-Target Dijkstra routing step.
|
// run two-Target Dijkstra routing step.
|
||||||
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
while (0 < (forward_heap.Size() + reverse_heap.Size()))
|
||||||
@@ -176,11 +180,6 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
const PhantomNode &target_phantom,
|
const PhantomNode &target_phantom,
|
||||||
EdgeWeight weight_upper_bound)
|
EdgeWeight weight_upper_bound)
|
||||||
{
|
{
|
||||||
forward_heap.Clear();
|
|
||||||
reverse_heap.Clear();
|
|
||||||
|
|
||||||
insertNodesInHeaps(forward_heap, reverse_heap, {source_phantom, target_phantom});
|
|
||||||
|
|
||||||
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
EdgeWeight weight = INVALID_EDGE_WEIGHT;
|
||||||
std::vector<NodeID> packed_path;
|
std::vector<NodeID> packed_path;
|
||||||
search(engine_working_data,
|
search(engine_working_data,
|
||||||
@@ -199,14 +198,31 @@ double getNetworkDistance(SearchEngineData<Algorithm> &engine_working_data,
|
|||||||
return std::numeric_limits<double>::max();
|
return std::numeric_limits<double>::max();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<PathData> unpacked_path;
|
EdgeDistance distance = 0;
|
||||||
unpackPath(facade,
|
|
||||||
packed_path.begin(),
|
|
||||||
packed_path.end(),
|
|
||||||
{source_phantom, target_phantom},
|
|
||||||
unpacked_path);
|
|
||||||
|
|
||||||
return getPathDistance(facade, unpacked_path, source_phantom, target_phantom);
|
std::vector<NodeID> unpacked_nodes;
|
||||||
|
unpacked_nodes.reserve(packed_path.size());
|
||||||
|
if (!packed_path.empty())
|
||||||
|
{
|
||||||
|
unpacked_nodes.push_back(packed_path.front());
|
||||||
|
unpackPath(
|
||||||
|
facade, packed_path.begin(), packed_path.end(), [&](const auto &edge, const auto &) {
|
||||||
|
BOOST_ASSERT(edge.first == unpacked_nodes.back());
|
||||||
|
unpacked_nodes.push_back(edge.second);
|
||||||
|
});
|
||||||
|
|
||||||
|
distance = std::accumulate(unpacked_nodes.begin(),
|
||||||
|
std::prev(unpacked_nodes.end()),
|
||||||
|
EdgeDistance{0},
|
||||||
|
[&](const EdgeDistance distance, const auto node_id) {
|
||||||
|
return distance + computeEdgeDistance(facade, node_id);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
distance =
|
||||||
|
adjustPathDistanceToPhantomNodes(unpacked_nodes, source_phantom, target_phantom, distance);
|
||||||
|
|
||||||
|
return distance;
|
||||||
}
|
}
|
||||||
} // namespace ch
|
} // namespace ch
|
||||||
|
|
||||||
|
|||||||
@@ -396,5 +396,5 @@ std::unique_ptr<SegmentDataContainer> CompressedEdgeContainer::ToSegmentData()
|
|||||||
|
|
||||||
return std::move(segment_data);
|
return std::move(segment_data);
|
||||||
}
|
}
|
||||||
}
|
} // namespace extractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ template <> struct hash<std::pair<NodeID, NodeID>>
|
|||||||
return seed;
|
return seed;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
} // namespace std
|
||||||
|
|
||||||
// Buffer size of turn_indexes_write_buffer to reduce number of write(v) syscals
|
// Buffer size of turn_indexes_write_buffer to reduce number of write(v) syscals
|
||||||
const constexpr int TURN_INDEX_WRITE_BUFFER_SIZE = 1000;
|
const constexpr int TURN_INDEX_WRITE_BUFFER_SIZE = 1000;
|
||||||
@@ -555,22 +555,21 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
&scripting_environment,
|
&scripting_environment,
|
||||||
weight_multiplier,
|
weight_multiplier,
|
||||||
&conditional_restriction_map](
|
&conditional_restriction_map](
|
||||||
// what nodes will be used? In most cases this will be the id
|
// what nodes will be used? In most cases this will be the id
|
||||||
// stored in the edge_data. In case of duplicated nodes (e.g.
|
// stored in the edge_data. In case of duplicated nodes (e.g.
|
||||||
// due to via-way restrictions), one/both of these might
|
// due to via-way restrictions), one/both of these might
|
||||||
// refer to a newly added edge based node
|
// refer to a newly added edge based node
|
||||||
const auto edge_based_node_from,
|
const auto edge_based_node_from,
|
||||||
const auto edge_based_node_to,
|
const auto edge_based_node_to,
|
||||||
// the situation of the turn
|
// the situation of the turn
|
||||||
const auto node_along_road_entering,
|
const auto node_along_road_entering,
|
||||||
const auto node_based_edge_from,
|
const auto node_based_edge_from,
|
||||||
const auto intersection_node,
|
const auto intersection_node,
|
||||||
const auto node_based_edge_to,
|
const auto node_based_edge_to,
|
||||||
const auto &turn_angle,
|
const auto &turn_angle,
|
||||||
const auto &road_legs_on_the_right,
|
const auto &road_legs_on_the_right,
|
||||||
const auto &road_legs_on_the_left,
|
const auto &road_legs_on_the_left,
|
||||||
const auto &edge_geometries) {
|
const auto &edge_geometries) {
|
||||||
|
|
||||||
const auto node_restricted =
|
const auto node_restricted =
|
||||||
isRestricted(node_along_road_entering,
|
isRestricted(node_along_road_entering,
|
||||||
intersection_node,
|
intersection_node,
|
||||||
@@ -652,16 +651,17 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
// auto turn_id = m_edge_based_edge_list.size();
|
// auto turn_id = m_edge_based_edge_list.size();
|
||||||
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
auto weight = boost::numeric_cast<EdgeWeight>(edge_data1.weight + weight_penalty);
|
||||||
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
|
auto duration = boost::numeric_cast<EdgeWeight>(edge_data1.duration + duration_penalty);
|
||||||
|
auto distance = boost::numeric_cast<EdgeDistance>(edge_data1.distance);
|
||||||
|
|
||||||
EdgeBasedEdge edge_based_edge = {
|
EdgeBasedEdge edge_based_edge = {edge_based_node_from,
|
||||||
edge_based_node_from,
|
edge_based_node_to,
|
||||||
edge_based_node_to,
|
SPECIAL_NODEID, // This will be updated once the main
|
||||||
SPECIAL_NODEID, // This will be updated once the main loop
|
// loop completes!
|
||||||
// completes!
|
weight,
|
||||||
weight,
|
duration,
|
||||||
duration,
|
distance,
|
||||||
true,
|
true,
|
||||||
false};
|
false};
|
||||||
|
|
||||||
// We write out the mapping between the edge-expanded edges and the original nodes.
|
// We write out the mapping between the edge-expanded edges and the original nodes.
|
||||||
// Since each edge represents a possible maneuver, external programs can use this to
|
// Since each edge represents a possible maneuver, external programs can use this to
|
||||||
@@ -693,7 +693,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
//
|
//
|
||||||
tbb::filter_t<tbb::blocked_range<NodeID>, EdgesPipelineBufferPtr> processor_stage(
|
tbb::filter_t<tbb::blocked_range<NodeID>, EdgesPipelineBufferPtr> processor_stage(
|
||||||
tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) {
|
tbb::filter::parallel, [&](const tbb::blocked_range<NodeID> &intersection_node_range) {
|
||||||
|
|
||||||
auto buffer = std::make_shared<EdgesPipelineBuffer>();
|
auto buffer = std::make_shared<EdgesPipelineBuffer>();
|
||||||
buffer->nodes_processed = intersection_node_range.size();
|
buffer->nodes_processed = intersection_node_range.size();
|
||||||
|
|
||||||
@@ -891,7 +890,7 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
// TODO: this loop is not optimized - once we have a few
|
// TODO: this loop is not optimized - once we have a few
|
||||||
// overrides available, we should index this for faster
|
// overrides available, we should index this for faster
|
||||||
// lookups
|
// lookups
|
||||||
for (auto & override : unresolved_maneuver_overrides)
|
for (auto &override : unresolved_maneuver_overrides)
|
||||||
{
|
{
|
||||||
for (auto &turn : override.turn_sequence)
|
for (auto &turn : override.turn_sequence)
|
||||||
{
|
{
|
||||||
@@ -1032,7 +1031,6 @@ void EdgeBasedGraphFactory::GenerateEdgeExpandedEdges(
|
|||||||
std::vector<EdgeWithData> delayed_data;
|
std::vector<EdgeWithData> delayed_data;
|
||||||
tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage(
|
tbb::filter_t<EdgesPipelineBufferPtr, void> output_stage(
|
||||||
tbb::filter::serial_in_order, [&](auto buffer) {
|
tbb::filter::serial_in_order, [&](auto buffer) {
|
||||||
|
|
||||||
routing_progress.PrintAddition(buffer->nodes_processed);
|
routing_progress.PrintAddition(buffer->nodes_processed);
|
||||||
|
|
||||||
m_connectivity_checksum = buffer->checksum.update_checksum(m_connectivity_checksum);
|
m_connectivity_checksum = buffer->checksum.update_checksum(m_connectivity_checksum);
|
||||||
|
|||||||
@@ -99,7 +99,7 @@ inline NodeID mapExternalToInternalNodeID(Iter first, Iter last, const OSMNodeID
|
|||||||
return (it == last || value < *it) ? SPECIAL_NODEID
|
return (it == last || value < *it) ? SPECIAL_NODEID
|
||||||
: static_cast<NodeID>(std::distance(first, it));
|
: static_cast<NodeID>(std::distance(first, it));
|
||||||
}
|
}
|
||||||
}
|
} // namespace
|
||||||
|
|
||||||
namespace osrm
|
namespace osrm
|
||||||
{
|
{
|
||||||
@@ -277,8 +277,8 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
{
|
{
|
||||||
if (edge_iterator->result.osm_source_id < node_iterator->node_id)
|
if (edge_iterator->result.osm_source_id < node_iterator->node_id)
|
||||||
{
|
{
|
||||||
util::Log(logDEBUG) << "Found invalid node reference "
|
util::Log(logDEBUG)
|
||||||
<< edge_iterator->result.source;
|
<< "Found invalid node reference " << edge_iterator->result.source;
|
||||||
edge_iterator->result.source = SPECIAL_NODEID;
|
edge_iterator->result.source = SPECIAL_NODEID;
|
||||||
++edge_iterator;
|
++edge_iterator;
|
||||||
continue;
|
continue;
|
||||||
@@ -387,12 +387,16 @@ void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environm
|
|||||||
const auto weight = edge_iterator->weight_data(distance);
|
const auto weight = edge_iterator->weight_data(distance);
|
||||||
const auto duration = edge_iterator->duration_data(distance);
|
const auto duration = edge_iterator->duration_data(distance);
|
||||||
|
|
||||||
|
const auto accurate_distance =
|
||||||
|
util::coordinate_calculation::fccApproximateDistance(source_coord, target_coord);
|
||||||
|
|
||||||
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
||||||
scripting_environment.ProcessSegment(segment);
|
scripting_environment.ProcessSegment(segment);
|
||||||
|
|
||||||
auto &edge = edge_iterator->result;
|
auto &edge = edge_iterator->result;
|
||||||
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
||||||
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
||||||
|
edge.distance = accurate_distance;
|
||||||
|
|
||||||
// assign new node id
|
// assign new node id
|
||||||
const auto node_id = mapExternalToInternalNodeID(
|
const auto node_id = mapExternalToInternalNodeID(
|
||||||
@@ -740,7 +744,6 @@ void ExtractionContainers::PrepareManeuverOverrides()
|
|||||||
**/
|
**/
|
||||||
auto const find_turn_from_way_tofrom_nodes = [&](auto const &from_segment,
|
auto const find_turn_from_way_tofrom_nodes = [&](auto const &from_segment,
|
||||||
auto const &to_segment) {
|
auto const &to_segment) {
|
||||||
|
|
||||||
if (from_segment.first_segment_source_id == to_segment.first_segment_source_id)
|
if (from_segment.first_segment_source_id == to_segment.first_segment_source_id)
|
||||||
{
|
{
|
||||||
return NodeBasedTurn{osm_node_to_internal_nbn(from_segment.first_segment_target_id),
|
return NodeBasedTurn{osm_node_to_internal_nbn(from_segment.first_segment_target_id),
|
||||||
@@ -857,7 +860,6 @@ void ExtractionContainers::PrepareManeuverOverrides()
|
|||||||
// Later, the UnresolvedManeuverOverride will be converted into a final ManeuverOverride
|
// Later, the UnresolvedManeuverOverride will be converted into a final ManeuverOverride
|
||||||
// once the edge-based-node IDs are generated by the edge-based-graph-factory
|
// once the edge-based-node IDs are generated by the edge-based-graph-factory
|
||||||
const auto transform = [&](const auto &external, auto &internal) {
|
const auto transform = [&](const auto &external, auto &internal) {
|
||||||
|
|
||||||
// Create a stub override
|
// Create a stub override
|
||||||
auto maneuver_override =
|
auto maneuver_override =
|
||||||
UnresolvedManeuverOverride{{},
|
UnresolvedManeuverOverride{{},
|
||||||
@@ -1036,8 +1038,9 @@ void ExtractionContainers::PrepareRestrictions()
|
|||||||
// translate the turn from one segment onto another into a node restriction (the ways can
|
// translate the turn from one segment onto another into a node restriction (the ways can
|
||||||
// only
|
// only
|
||||||
// be connected at a single location)
|
// be connected at a single location)
|
||||||
auto const get_node_restriction_from_OSM_ids = [&](
|
auto const get_node_restriction_from_OSM_ids = [&](auto const from_id,
|
||||||
auto const from_id, auto const to_id, const OSMNodeID via_node) {
|
auto const to_id,
|
||||||
|
const OSMNodeID via_node) {
|
||||||
auto const from_segment_itr = referenced_ways.find(from_id);
|
auto const from_segment_itr = referenced_ways.find(from_id);
|
||||||
if (from_segment_itr->second.way_id != from_id)
|
if (from_segment_itr->second.way_id != from_id)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -75,7 +75,7 @@ void ExtractorCallbacks::ProcessRestriction(const InputConditionalTurnRestrictio
|
|||||||
// util::Log() << restriction.toString();
|
// util::Log() << restriction.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ExtractorCallbacks::ProcessManeuverOverride(const InputManeuverOverride & override)
|
void ExtractorCallbacks::ProcessManeuverOverride(const InputManeuverOverride &override)
|
||||||
{
|
{
|
||||||
external_memory.external_maneuver_overrides_list.push_back(override);
|
external_memory.external_maneuver_overrides_list.push_back(override);
|
||||||
}
|
}
|
||||||
@@ -415,6 +415,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
0, // weight
|
0, // weight
|
||||||
0, // duration
|
0, // duration
|
||||||
|
0, // distance
|
||||||
{}, // geometry id
|
{}, // geometry id
|
||||||
static_cast<AnnotationID>(annotation_data_id),
|
static_cast<AnnotationID>(annotation_data_id),
|
||||||
{true,
|
{true,
|
||||||
@@ -450,6 +451,7 @@ void ExtractorCallbacks::ProcessWay(const osmium::Way &input_way, const Extracti
|
|||||||
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
OSMNodeID{static_cast<std::uint64_t>(last_node.ref())},
|
||||||
0, // weight
|
0, // weight
|
||||||
0, // duration
|
0, // duration
|
||||||
|
0, // distance
|
||||||
{}, // geometry id
|
{}, // geometry id
|
||||||
static_cast<AnnotationID>(annotation_data_id),
|
static_cast<AnnotationID>(annotation_data_id),
|
||||||
{false,
|
{false,
|
||||||
|
|||||||
@@ -185,17 +185,18 @@ void GraphCompressor::Compress(
|
|||||||
* just
|
* just
|
||||||
* like a barrier.
|
* like a barrier.
|
||||||
*/
|
*/
|
||||||
const auto selectAnnotation = [&node_data_container](
|
const auto selectAnnotation =
|
||||||
const AnnotationID front_annotation, const AnnotationID back_annotation) {
|
[&node_data_container](const AnnotationID front_annotation,
|
||||||
// A lane has tags: u - (front) - v - (back) - w
|
const AnnotationID back_annotation) {
|
||||||
// During contraction, we keep only one of the tags. Usually the one closer
|
// A lane has tags: u - (front) - v - (back) - w
|
||||||
// to the intersection is preferred. If its empty, however, we keep the
|
// During contraction, we keep only one of the tags. Usually the one closer
|
||||||
// non-empty one
|
// to the intersection is preferred. If its empty, however, we keep the
|
||||||
if (node_data_container[back_annotation].lane_description_id ==
|
// non-empty one
|
||||||
INVALID_LANE_DESCRIPTIONID)
|
if (node_data_container[back_annotation].lane_description_id ==
|
||||||
return front_annotation;
|
INVALID_LANE_DESCRIPTIONID)
|
||||||
return back_annotation;
|
return front_annotation;
|
||||||
};
|
return back_annotation;
|
||||||
|
};
|
||||||
|
|
||||||
graph.GetEdgeData(forward_e1).annotation_data = selectAnnotation(
|
graph.GetEdgeData(forward_e1).annotation_data = selectAnnotation(
|
||||||
fwd_edge_data1.annotation_data, fwd_edge_data2.annotation_data);
|
fwd_edge_data1.annotation_data, fwd_edge_data2.annotation_data);
|
||||||
@@ -259,6 +260,8 @@ void GraphCompressor::Compress(
|
|||||||
const auto forward_weight2 = fwd_edge_data2.weight;
|
const auto forward_weight2 = fwd_edge_data2.weight;
|
||||||
const auto forward_duration1 = fwd_edge_data1.duration;
|
const auto forward_duration1 = fwd_edge_data1.duration;
|
||||||
const auto forward_duration2 = fwd_edge_data2.duration;
|
const auto forward_duration2 = fwd_edge_data2.duration;
|
||||||
|
// const auto forward_distance1 = fwd_edge_data1.distance;
|
||||||
|
const auto forward_distance2 = fwd_edge_data2.distance;
|
||||||
|
|
||||||
BOOST_ASSERT(0 != forward_weight1);
|
BOOST_ASSERT(0 != forward_weight1);
|
||||||
BOOST_ASSERT(0 != forward_weight2);
|
BOOST_ASSERT(0 != forward_weight2);
|
||||||
@@ -267,6 +270,8 @@ void GraphCompressor::Compress(
|
|||||||
const auto reverse_weight2 = rev_edge_data2.weight;
|
const auto reverse_weight2 = rev_edge_data2.weight;
|
||||||
const auto reverse_duration1 = rev_edge_data1.duration;
|
const auto reverse_duration1 = rev_edge_data1.duration;
|
||||||
const auto reverse_duration2 = rev_edge_data2.duration;
|
const auto reverse_duration2 = rev_edge_data2.duration;
|
||||||
|
// const auto reverse_distance1 = rev_edge_data1.distance;
|
||||||
|
const auto reverse_distance2 = rev_edge_data2.distance;
|
||||||
|
|
||||||
BOOST_ASSERT(0 != reverse_weight1);
|
BOOST_ASSERT(0 != reverse_weight1);
|
||||||
BOOST_ASSERT(0 != reverse_weight2);
|
BOOST_ASSERT(0 != reverse_weight2);
|
||||||
@@ -279,6 +284,10 @@ void GraphCompressor::Compress(
|
|||||||
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
graph.GetEdgeData(forward_e1).duration += forward_duration2;
|
||||||
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
graph.GetEdgeData(reverse_e1).duration += reverse_duration2;
|
||||||
|
|
||||||
|
// add duration of e2's to e1
|
||||||
|
graph.GetEdgeData(forward_e1).distance += forward_distance2;
|
||||||
|
graph.GetEdgeData(reverse_e1).distance += reverse_distance2;
|
||||||
|
|
||||||
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
|
if (node_weight_penalty != INVALID_EDGE_WEIGHT &&
|
||||||
node_duration_penalty != MAXIMAL_EDGE_DURATION)
|
node_duration_penalty != MAXIMAL_EDGE_DURATION)
|
||||||
{
|
{
|
||||||
@@ -286,6 +295,7 @@ void GraphCompressor::Compress(
|
|||||||
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
|
graph.GetEdgeData(reverse_e1).weight += node_weight_penalty;
|
||||||
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
|
graph.GetEdgeData(forward_e1).duration += node_duration_penalty;
|
||||||
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
|
graph.GetEdgeData(reverse_e1).duration += node_duration_penalty;
|
||||||
|
// Note: no penalties for distances
|
||||||
}
|
}
|
||||||
|
|
||||||
// extend e1's to targets of e2's
|
// extend e1's to targets of e2's
|
||||||
@@ -359,5 +369,5 @@ void GraphCompressor::PrintStatistics(unsigned original_number_of_nodes,
|
|||||||
util::Log() << "Node compression ratio: " << new_node_count / (double)original_number_of_nodes;
|
util::Log() << "Node compression ratio: " << new_node_count / (double)original_number_of_nodes;
|
||||||
util::Log() << "Edge compression ratio: " << new_edge_count / (double)original_number_of_edges;
|
util::Log() << "Edge compression ratio: " << new_edge_count / (double)original_number_of_edges;
|
||||||
}
|
}
|
||||||
}
|
} // namespace extractor
|
||||||
}
|
} // namespace osrm
|
||||||
|
|||||||
+11
-92
@@ -9,15 +9,12 @@
|
|||||||
#include "osrm/trip_parameters.hpp"
|
#include "osrm/trip_parameters.hpp"
|
||||||
|
|
||||||
#include <exception>
|
#include <exception>
|
||||||
#include <sstream>
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
#include "nodejs/node_osrm.hpp"
|
#include "nodejs/node_osrm.hpp"
|
||||||
#include "nodejs/node_osrm_support.hpp"
|
#include "nodejs/node_osrm_support.hpp"
|
||||||
|
|
||||||
#include "util/json_renderer.hpp"
|
|
||||||
|
|
||||||
namespace node_osrm
|
namespace node_osrm
|
||||||
{
|
{
|
||||||
|
|
||||||
@@ -125,8 +122,6 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|||||||
if (!params)
|
if (!params)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto pluginParams = argumentsToPluginParameters(info);
|
|
||||||
|
|
||||||
BOOST_ASSERT(params->IsValid());
|
BOOST_ASSERT(params->IsValid());
|
||||||
|
|
||||||
if (!info[info.Length() - 1]->IsFunction())
|
if (!info[info.Length() - 1]->IsFunction())
|
||||||
@@ -142,89 +137,9 @@ inline void async(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|||||||
Worker(std::shared_ptr<osrm::OSRM> osrm_,
|
Worker(std::shared_ptr<osrm::OSRM> osrm_,
|
||||||
ParamPtr params_,
|
ParamPtr params_,
|
||||||
ServiceMemFn service,
|
ServiceMemFn service,
|
||||||
Nan::Callback *callback,
|
Nan::Callback *callback)
|
||||||
PluginParameters pluginParams_)
|
|
||||||
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
|
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
|
||||||
params{std::move(params_)}, pluginParams{std::move(pluginParams_)}
|
params{std::move(params_)}
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void Execute() override try
|
|
||||||
{
|
|
||||||
osrm::json::Object r;
|
|
||||||
const auto status = ((*osrm).*(service))(*params, r);
|
|
||||||
ParseResult(status, r);
|
|
||||||
if (pluginParams.renderJSONToBuffer)
|
|
||||||
{
|
|
||||||
std::ostringstream buf;
|
|
||||||
osrm::util::json::render(buf, r);
|
|
||||||
result = buf.str();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
result = r;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (const std::exception &e)
|
|
||||||
{
|
|
||||||
SetErrorMessage(e.what());
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandleOKCallback() override
|
|
||||||
{
|
|
||||||
Nan::HandleScope scope;
|
|
||||||
|
|
||||||
const constexpr auto argc = 2u;
|
|
||||||
v8::Local<v8::Value> argv[argc] = {Nan::Null(), render(result)};
|
|
||||||
|
|
||||||
callback->Call(argc, argv);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Keeps the OSRM object alive even after shutdown until we're done with callback
|
|
||||||
std::shared_ptr<osrm::OSRM> osrm;
|
|
||||||
ServiceMemFn service;
|
|
||||||
const ParamPtr params;
|
|
||||||
const PluginParameters pluginParams;
|
|
||||||
|
|
||||||
ObjectOrString result;
|
|
||||||
};
|
|
||||||
|
|
||||||
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
|
|
||||||
Nan::AsyncQueueWorker(
|
|
||||||
new Worker{self->this_, std::move(params), service, callback, std::move(pluginParams)});
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename ParameterParser, typename ServiceMemFn>
|
|
||||||
inline void asyncForTiles(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|
||||||
ParameterParser argsToParams,
|
|
||||||
ServiceMemFn service,
|
|
||||||
bool requires_multiple_coordinates)
|
|
||||||
{
|
|
||||||
auto params = argsToParams(info, requires_multiple_coordinates);
|
|
||||||
if (!params)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto pluginParams = argumentsToPluginParameters(info);
|
|
||||||
|
|
||||||
BOOST_ASSERT(params->IsValid());
|
|
||||||
|
|
||||||
if (!info[info.Length() - 1]->IsFunction())
|
|
||||||
return Nan::ThrowTypeError("last argument must be a callback function");
|
|
||||||
|
|
||||||
auto *const self = Nan::ObjectWrap::Unwrap<Engine>(info.Holder());
|
|
||||||
using ParamPtr = decltype(params);
|
|
||||||
|
|
||||||
struct Worker final : Nan::AsyncWorker
|
|
||||||
{
|
|
||||||
using Base = Nan::AsyncWorker;
|
|
||||||
|
|
||||||
Worker(std::shared_ptr<osrm::OSRM> osrm_,
|
|
||||||
ParamPtr params_,
|
|
||||||
ServiceMemFn service,
|
|
||||||
Nan::Callback *callback,
|
|
||||||
PluginParameters pluginParams_)
|
|
||||||
: Base(callback), osrm{std::move(osrm_)}, service{std::move(service)},
|
|
||||||
params{std::move(params_)}, pluginParams{std::move(pluginParams_)}
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -252,14 +167,18 @@ inline void asyncForTiles(const Nan::FunctionCallbackInfo<v8::Value> &info,
|
|||||||
std::shared_ptr<osrm::OSRM> osrm;
|
std::shared_ptr<osrm::OSRM> osrm;
|
||||||
ServiceMemFn service;
|
ServiceMemFn service;
|
||||||
const ParamPtr params;
|
const ParamPtr params;
|
||||||
const PluginParameters pluginParams;
|
|
||||||
|
|
||||||
std::string result;
|
// All services return json::Object .. except for Tile!
|
||||||
|
using ObjectOrString =
|
||||||
|
typename std::conditional<std::is_same<ParamPtr, tile_parameters_ptr>::value,
|
||||||
|
std::string,
|
||||||
|
osrm::json::Object>::type;
|
||||||
|
|
||||||
|
ObjectOrString result;
|
||||||
};
|
};
|
||||||
|
|
||||||
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
|
auto *callback = new Nan::Callback{info[info.Length() - 1].As<v8::Function>()};
|
||||||
Nan::AsyncQueueWorker(
|
Nan::AsyncQueueWorker(new Worker{self->this_, std::move(params), service, callback});
|
||||||
new Worker{self->this_, std::move(params), service, callback, std::move(pluginParams)});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
@@ -422,7 +341,7 @@ NAN_METHOD(Engine::table) //
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
NAN_METHOD(Engine::tile)
|
NAN_METHOD(Engine::tile)
|
||||||
{
|
{
|
||||||
asyncForTiles(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/});
|
async(info, &argumentsToTileParameters, &osrm::OSRM::Tile, {/*unused*/});
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format off
|
// clang-format off
|
||||||
|
|||||||
@@ -81,7 +81,8 @@ return_code parseArguments(int argc,
|
|||||||
"time-zone-file",
|
"time-zone-file",
|
||||||
boost::program_options::value<std::string>(&contractor_config.updater_config.tz_file_path),
|
boost::program_options::value<std::string>(&contractor_config.updater_config.tz_file_path),
|
||||||
"Required for conditional turn restriction parsing, provide a geojson file containing "
|
"Required for conditional turn restriction parsing, provide a geojson file containing "
|
||||||
"time zone boundaries");
|
"time zone boundaries")("cache-distances",boost::program_options::bool_switch(&contractor_config.cache_distances)->default_value(false),
|
||||||
|
"Store distances for CH edges, avoiding the need for query-time re-calculation.");
|
||||||
|
|
||||||
// hidden options, will be allowed on command line, but will not be shown to the user
|
// hidden options, will be allowed on command line, but will not be shown to the user
|
||||||
boost::program_options::options_description hidden_options("Hidden options");
|
boost::program_options::options_description hidden_options("Hidden options");
|
||||||
|
|||||||
+13
-9
@@ -70,8 +70,8 @@ std::istream &operator>>(std::istream &in, EngineConfig::Algorithm &algorithm)
|
|||||||
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
|
throw util::RuntimeError(token, ErrorCode::UnknownAlgorithm, SOURCE_REF);
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
} // namespace engine
|
}
|
||||||
} // namespace osrm
|
}
|
||||||
|
|
||||||
// generate boost::program_options object for the routing part
|
// generate boost::program_options object for the routing part
|
||||||
inline unsigned generateServerProgramOptions(const int argc,
|
inline unsigned generateServerProgramOptions(const int argc,
|
||||||
@@ -273,12 +273,10 @@ int main(int argc, const char *argv[]) try
|
|||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
int sig = 0;
|
int sig = 0;
|
||||||
sigset_t wait_mask;
|
sigset_t new_mask;
|
||||||
sigemptyset(&wait_mask);
|
sigset_t old_mask;
|
||||||
sigaddset(&wait_mask, SIGINT);
|
sigfillset(&new_mask);
|
||||||
sigaddset(&wait_mask, SIGQUIT);
|
pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask);
|
||||||
sigaddset(&wait_mask, SIGTERM);
|
|
||||||
pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr); // only block necessary signals
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
auto service_handler = std::make_unique<server::ServiceHandler>(config);
|
auto service_handler = std::make_unique<server::ServiceHandler>(config);
|
||||||
@@ -300,13 +298,19 @@ int main(int argc, const char *argv[]) try
|
|||||||
std::thread server_thread(std::move(server_task));
|
std::thread server_thread(std::move(server_task));
|
||||||
|
|
||||||
#ifndef _WIN32
|
#ifndef _WIN32
|
||||||
|
sigset_t wait_mask;
|
||||||
|
pthread_sigmask(SIG_SETMASK, &old_mask, nullptr);
|
||||||
|
sigemptyset(&wait_mask);
|
||||||
|
sigaddset(&wait_mask, SIGINT);
|
||||||
|
sigaddset(&wait_mask, SIGQUIT);
|
||||||
|
sigaddset(&wait_mask, SIGTERM);
|
||||||
|
pthread_sigmask(SIG_BLOCK, &wait_mask, nullptr);
|
||||||
util::Log() << "running and waiting for requests";
|
util::Log() << "running and waiting for requests";
|
||||||
if (std::getenv("SIGNAL_PARENT_WHEN_READY"))
|
if (std::getenv("SIGNAL_PARENT_WHEN_READY"))
|
||||||
{
|
{
|
||||||
kill(getppid(), SIGUSR1);
|
kill(getppid(), SIGUSR1);
|
||||||
}
|
}
|
||||||
sigwait(&wait_mask, &sig);
|
sigwait(&wait_mask, &sig);
|
||||||
util::Log() << "received signal " << sig;
|
|
||||||
#else
|
#else
|
||||||
// Set console control handler to allow server to be stopped.
|
// Set console control handler to allow server to be stopped.
|
||||||
console_ctrl_function = std::bind(&server::Server::Stop, routing_server);
|
console_ctrl_function = std::bind(&server::Server::Stop, routing_server);
|
||||||
|
|||||||
@@ -22,6 +22,11 @@ namespace coordinate_calculation
|
|||||||
|
|
||||||
namespace
|
namespace
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// earth radius varies between 6,356.750-6,378.135 km (3,949.901-3,963.189mi)
|
||||||
|
// The IUGG value for the equatorial radius is 6378.137 km (3963.19 miles)
|
||||||
|
const constexpr double EARTH_RADIUS = 6372797.560856;
|
||||||
|
|
||||||
class CheapRulerContainer
|
class CheapRulerContainer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@@ -112,7 +117,7 @@ double haversineDistance(const Coordinate coordinate_1, const Coordinate coordin
|
|||||||
const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) +
|
const double aharv = std::pow(std::sin(dlat / 2.0), 2.0) +
|
||||||
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2);
|
std::cos(dlat1) * std::cos(dlat2) * std::pow(std::sin(dlong / 2.), 2);
|
||||||
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
const double charv = 2. * std::atan2(std::sqrt(aharv), std::sqrt(1.0 - aharv));
|
||||||
return detail::EARTH_RADIUS * charv;
|
return EARTH_RADIUS * charv;
|
||||||
}
|
}
|
||||||
|
|
||||||
double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coordinate_2)
|
||||||
@@ -133,7 +138,7 @@ double greatCircleDistance(const Coordinate coordinate_1, const Coordinate coord
|
|||||||
|
|
||||||
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
|
const double x_value = (float_lon2 - float_lon1) * std::cos((float_lat1 + float_lat2) / 2.0);
|
||||||
const double y_value = float_lat2 - float_lat1;
|
const double y_value = float_lat2 - float_lat1;
|
||||||
return std::hypot(x_value, y_value) * detail::EARTH_RADIUS;
|
return std::hypot(x_value, y_value) * EARTH_RADIUS;
|
||||||
}
|
}
|
||||||
|
|
||||||
double perpendicularDistance(const Coordinate segment_source,
|
double perpendicularDistance(const Coordinate segment_source,
|
||||||
|
|||||||
@@ -25,28 +25,6 @@ test('match: match in Monaco', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('match: match in Monaco returning a buffer', function(assert) {
|
|
||||||
assert.plan(6);
|
|
||||||
var osrm = new OSRM(data_path);
|
|
||||||
var options = {
|
|
||||||
coordinates: three_test_coordinates,
|
|
||||||
timestamps: [1424684612, 1424684616, 1424684620]
|
|
||||||
};
|
|
||||||
osrm.match(options, { format: 'json_buffer' }, function(err, response) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.ok(response instanceof Buffer);
|
|
||||||
response = JSON.parse(response);
|
|
||||||
assert.equal(response.matchings.length, 1);
|
|
||||||
assert.ok(response.matchings.every(function(m) {
|
|
||||||
return !!m.distance && !!m.duration && Array.isArray(m.legs) && !!m.geometry && m.confidence > 0;
|
|
||||||
}))
|
|
||||||
assert.equal(response.tracepoints.length, 3);
|
|
||||||
assert.ok(response.tracepoints.every(function(t) {
|
|
||||||
return !!t.hint && !isNaN(t.matchings_index) && !isNaN(t.waypoint_index) && !!t.name;
|
|
||||||
}));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('match: match in Monaco without timestamps', function(assert) {
|
test('match: match in Monaco without timestamps', function(assert) {
|
||||||
assert.plan(3);
|
assert.plan(3);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
@@ -247,16 +225,6 @@ test('match: throws on invalid tidy param', function(assert) {
|
|||||||
/tidy must be of type Boolean/);
|
/tidy must be of type Boolean/);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('match: throws on invalid config param', function(assert) {
|
|
||||||
assert.plan(1);
|
|
||||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
|
||||||
var options = {
|
|
||||||
coordinates: three_test_coordinates,
|
|
||||||
};
|
|
||||||
assert.throws(function() { osrm.match(options, { format: 'invalid' }, function(err, response) {}) },
|
|
||||||
/format must be a string:/);
|
|
||||||
});
|
|
||||||
|
|
||||||
test('match: match in Monaco without motorways', function(assert) {
|
test('match: match in Monaco without motorways', function(assert) {
|
||||||
assert.plan(3);
|
assert.plan(3);
|
||||||
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
var osrm = new OSRM({path: mld_data_path, algorithm: 'MLD'});
|
||||||
|
|||||||
+1
-20
@@ -19,21 +19,6 @@ test('nearest', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('nearest', function(assert) {
|
|
||||||
assert.plan(5);
|
|
||||||
var osrm = new OSRM(data_path);
|
|
||||||
osrm.nearest({
|
|
||||||
coordinates: [three_test_coordinates[0]]
|
|
||||||
}, { format: 'json_buffer' }, function(err, result) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.ok(result instanceof Buffer);
|
|
||||||
result = JSON.parse(result);
|
|
||||||
assert.equal(result.waypoints.length, 1);
|
|
||||||
assert.equal(result.waypoints[0].location.length, 2);
|
|
||||||
assert.ok(result.waypoints[0].hasOwnProperty('name'));
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('nearest: can ask for multiple nearest pts', function(assert) {
|
test('nearest: can ask for multiple nearest pts', function(assert) {
|
||||||
assert.plan(2);
|
assert.plan(2);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
@@ -47,7 +32,7 @@ test('nearest: can ask for multiple nearest pts', function(assert) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('nearest: throws on invalid args', function(assert) {
|
test('nearest: throws on invalid args', function(assert) {
|
||||||
assert.plan(7);
|
assert.plan(6);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
var options = {};
|
var options = {};
|
||||||
assert.throws(function() { osrm.nearest(options); },
|
assert.throws(function() { osrm.nearest(options); },
|
||||||
@@ -67,10 +52,6 @@ test('nearest: throws on invalid args', function(assert) {
|
|||||||
options.number = 0;
|
options.number = 0;
|
||||||
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
|
assert.throws(function() { osrm.nearest(options, function(err, res) {}); },
|
||||||
/Number must be an integer greater than or equal to 1/);
|
/Number must be an integer greater than or equal to 1/);
|
||||||
|
|
||||||
options.number = 1;
|
|
||||||
assert.throws(function() { osrm.nearest(options, { format: 'invalid' }, function(err, res) {}); },
|
|
||||||
/format must be a string:/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('nearest: nearest in Monaco without motorways', function(assert) {
|
test('nearest: nearest in Monaco without motorways', function(assert) {
|
||||||
|
|||||||
+1
-17
@@ -43,22 +43,8 @@ test('route: routes Monaco on CoreCH', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('route: routes Monaco and returns a JSON buffer', function(assert) {
|
|
||||||
assert.plan(6);
|
|
||||||
var osrm = new OSRM({path: monaco_corech_path, algorithm: 'CoreCH'});
|
|
||||||
osrm.route({coordinates: [[13.43864,52.51993],[13.415852,52.513191]]}, { format: 'json_buffer'}, function(err, result) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.ok(result instanceof Buffer);
|
|
||||||
const route = JSON.parse(result);
|
|
||||||
assert.ok(route.waypoints);
|
|
||||||
assert.ok(route.routes);
|
|
||||||
assert.ok(route.routes.length);
|
|
||||||
assert.ok(route.routes[0].geometry);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('route: throws with too few or invalid args', function(assert) {
|
test('route: throws with too few or invalid args', function(assert) {
|
||||||
assert.plan(4);
|
assert.plan(3);
|
||||||
var osrm = new OSRM(monaco_path);
|
var osrm = new OSRM(monaco_path);
|
||||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}) },
|
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}) },
|
||||||
/Two arguments required/);
|
/Two arguments required/);
|
||||||
@@ -66,8 +52,6 @@ test('route: throws with too few or invalid args', function(assert) {
|
|||||||
/First arg must be an object/);
|
/First arg must be an object/);
|
||||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, true)},
|
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, true)},
|
||||||
/last argument must be a callback function/);
|
/last argument must be a callback function/);
|
||||||
assert.throws(function() { osrm.route({coordinates: two_test_coordinates}, { format: 'invalid' }, function(err, route) {})},
|
|
||||||
/format must be a string:/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('route: provides no alternatives by default, but when requested it may (not guaranteed)', function(assert) {
|
test('route: provides no alternatives by default, but when requested it may (not guaranteed)', function(assert) {
|
||||||
|
|||||||
+1
-18
@@ -48,20 +48,6 @@ test('table: test annotations paramater combination', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('table: returns buffer', function(assert) {
|
|
||||||
assert.plan(3);
|
|
||||||
var osrm = new OSRM(data_path);
|
|
||||||
var options = {
|
|
||||||
coordinates: [three_test_coordinates[0], three_test_coordinates[1]],
|
|
||||||
};
|
|
||||||
osrm.table(options, { format: 'json_buffer' }, function(err, table) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.ok(table instanceof Buffer);
|
|
||||||
table = JSON.parse(table);
|
|
||||||
assert.ok(table['durations'], 'distances table result should exist');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
var tables = ['distances', 'durations'];
|
var tables = ['distances', 'durations'];
|
||||||
|
|
||||||
tables.forEach(function(annotation) {
|
tables.forEach(function(annotation) {
|
||||||
@@ -130,7 +116,7 @@ tables.forEach(function(annotation) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('table: ' + annotation + ' throws on invalid arguments', function(assert) {
|
test('table: ' + annotation + ' throws on invalid arguments', function(assert) {
|
||||||
assert.plan(15);
|
assert.plan(14);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
var options = {annotations: [annotation.slice(0,-1)]};
|
var options = {annotations: [annotation.slice(0,-1)]};
|
||||||
assert.throws(function() { osrm.table(options); },
|
assert.throws(function() { osrm.table(options); },
|
||||||
@@ -149,9 +135,6 @@ tables.forEach(function(annotation) {
|
|||||||
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
/Coordinates must be an array of \(lon\/lat\) pairs/);
|
||||||
|
|
||||||
options.coordinates = two_test_coordinates;
|
options.coordinates = two_test_coordinates;
|
||||||
assert.throws(function() { osrm.table(options, { format: 'invalid' }, function(err, response) {}) },
|
|
||||||
/format must be a string:/);
|
|
||||||
|
|
||||||
options.sources = true;
|
options.sources = true;
|
||||||
assert.throws(function() { osrm.table(options, function(err, response) {}) },
|
assert.throws(function() { osrm.table(options, function(err, response) {}) },
|
||||||
/Sources must be an array of indices \(or undefined\)/);
|
/Sources must be an array of indices \(or undefined\)/);
|
||||||
|
|||||||
+1
-16
@@ -17,19 +17,6 @@ test('trip: trip in Monaco', function(assert) {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
test('trip: trip in Monaco as a buffer', function(assert) {
|
|
||||||
assert.plan(3);
|
|
||||||
var osrm = new OSRM(data_path);
|
|
||||||
osrm.trip({coordinates: two_test_coordinates}, { format: 'json_buffer' }, function(err, trip) {
|
|
||||||
assert.ifError(err);
|
|
||||||
assert.ok(trip instanceof Buffer);
|
|
||||||
trip = JSON.parse(trip);
|
|
||||||
for (t = 0; t < trip.trips.length; t++) {
|
|
||||||
assert.ok(trip.trips[t].geometry);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
test('trip: trip with many locations in Monaco', function(assert) {
|
test('trip: trip with many locations in Monaco', function(assert) {
|
||||||
assert.plan(2);
|
assert.plan(2);
|
||||||
|
|
||||||
@@ -46,14 +33,12 @@ test('trip: trip with many locations in Monaco', function(assert) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
test('trip: throws with too few or invalid args', function(assert) {
|
test('trip: throws with too few or invalid args', function(assert) {
|
||||||
assert.plan(3);
|
assert.plan(2);
|
||||||
var osrm = new OSRM(data_path);
|
var osrm = new OSRM(data_path);
|
||||||
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}) },
|
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}) },
|
||||||
/Two arguments required/);
|
/Two arguments required/);
|
||||||
assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
|
assert.throws(function() { osrm.trip(null, function(err, trip) {}) },
|
||||||
/First arg must be an object/);
|
/First arg must be an object/);
|
||||||
assert.throws(function() { osrm.trip({coordinates: two_test_coordinates}, { format: 'invalid' }, function(err, trip) {}) },
|
|
||||||
/format must be a string:/);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
test('trip: throws with bad params', function(assert) {
|
test('trip: throws with bad params', function(assert) {
|
||||||
|
|||||||
Reference in New Issue
Block a user