Merge pull request #1030 from DennisOSRM/features/json-generator
Distance tables and JSON generator
This commit is contained in:
commit
2822382797
142
Algorithms/ExtractRouteNames.h
Normal file
142
Algorithms/ExtractRouteNames.h
Normal file
@ -0,0 +1,142 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef EXTRACT_ROUTE_NAMES_H
|
||||
#define EXTRACT_ROUTE_NAMES_H
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <algorithm>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
struct RouteNames
|
||||
{
|
||||
std::string shortest_path_name_1;
|
||||
std::string shortest_path_name_2;
|
||||
std::string alternative_path_name_1;
|
||||
std::string alternative_path_name_2;
|
||||
};
|
||||
|
||||
// construct routes names
|
||||
template <class DataFacadeT, class SegmentT> struct ExtractRouteNames
|
||||
{
|
||||
RouteNames operator()(std::vector<SegmentT> &shortest_path_segments,
|
||||
std::vector<SegmentT> &alternative_path_segments,
|
||||
const DataFacadeT *facade)
|
||||
{
|
||||
RouteNames route_names;
|
||||
|
||||
SegmentT shortest_segment_1, shortest_segment_2;
|
||||
SegmentT alternative_segment_1, alternative_segment_2;
|
||||
|
||||
auto length_comperator = [](SegmentT a, SegmentT b)
|
||||
{ return a.length > b.length; };
|
||||
auto name_id_comperator = [](SegmentT a, SegmentT b)
|
||||
{ return a.name_id < b.name_id; };
|
||||
|
||||
if (shortest_path_segments.empty())
|
||||
{
|
||||
return route_names;
|
||||
}
|
||||
|
||||
std::sort(shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||
shortest_segment_1 = shortest_path_segments[0];
|
||||
if (!alternative_path_segments.empty())
|
||||
{
|
||||
std::sort(alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
length_comperator);
|
||||
alternative_segment_1 = alternative_path_segments[0];
|
||||
}
|
||||
std::vector<SegmentT> shortest_path_set_difference(shortest_path_segments.size());
|
||||
std::vector<SegmentT> alternative_path_set_difference(alternative_path_segments.size());
|
||||
std::set_difference(shortest_path_segments.begin(),
|
||||
shortest_path_segments.end(),
|
||||
alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
shortest_path_set_difference.begin(),
|
||||
name_id_comperator);
|
||||
int size_of_difference = shortest_path_set_difference.size();
|
||||
if (size_of_difference)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < size_of_difference &&
|
||||
shortest_path_set_difference[i].name_id == shortest_path_segments[0].name_id)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (i < size_of_difference)
|
||||
{
|
||||
shortest_segment_2 = shortest_path_set_difference[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::set_difference(alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
shortest_path_segments.begin(),
|
||||
shortest_path_segments.end(),
|
||||
alternative_path_set_difference.begin(),
|
||||
name_id_comperator);
|
||||
size_of_difference = alternative_path_set_difference.size();
|
||||
if (size_of_difference)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < size_of_difference &&
|
||||
alternative_path_set_difference[i].name_id ==
|
||||
alternative_path_segments[0].name_id)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (i < size_of_difference)
|
||||
{
|
||||
alternative_segment_2 = alternative_path_set_difference[i];
|
||||
}
|
||||
}
|
||||
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||
{
|
||||
std::swap(shortest_segment_1, shortest_segment_2);
|
||||
}
|
||||
if (alternative_segment_1.position > alternative_segment_2.position)
|
||||
{
|
||||
std::swap(alternative_segment_1, alternative_segment_2);
|
||||
}
|
||||
route_names.shortest_path_name_1 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||
route_names.shortest_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
|
||||
|
||||
route_names.alternative_path_name_1 =
|
||||
facade->GetEscapedNameForNameID(alternative_segment_1.name_id);
|
||||
route_names.alternative_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
||||
|
||||
return route_names;
|
||||
}
|
||||
};
|
||||
|
||||
#endif // EXTRACT_ROUTE_NAMES_H
|
@ -26,6 +26,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "PolylineCompressor.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
//TODO: return vector of start indices for each leg
|
||||
|
||||
void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std::string &output)
|
||||
const
|
||||
@ -39,9 +42,9 @@ void PolylineCompressor::encodeVectorSignedNumber(std::vector<int> &numbers, std
|
||||
numbers[i] = ~(numbers[i]);
|
||||
}
|
||||
}
|
||||
for (unsigned i = 0; i < end; ++i)
|
||||
for (const int number: numbers)
|
||||
{
|
||||
encodeNumber(numbers[i], output);
|
||||
encodeNumber(number, output);
|
||||
}
|
||||
}
|
||||
|
||||
@ -66,37 +69,36 @@ void PolylineCompressor::encodeNumber(int number_to_encode, std::string &output)
|
||||
}
|
||||
}
|
||||
|
||||
void PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline,
|
||||
std::string &output) const
|
||||
JSON::String PolylineCompressor::printEncodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
std::string output;
|
||||
std::vector<int> delta_numbers;
|
||||
output += "\"";
|
||||
if (!polyline.empty())
|
||||
{
|
||||
FixedPointCoordinate last_coordinate = polyline[0].location;
|
||||
delta_numbers.emplace_back(last_coordinate.lat);
|
||||
delta_numbers.emplace_back(last_coordinate.lon);
|
||||
for (unsigned i = 1; i < polyline.size(); ++i)
|
||||
for (const auto & segment : polyline)
|
||||
{
|
||||
if (polyline[i].necessary)
|
||||
if (segment.necessary)
|
||||
{
|
||||
int lat_diff = polyline[i].location.lat - last_coordinate.lat;
|
||||
int lon_diff = polyline[i].location.lon - last_coordinate.lon;
|
||||
int lat_diff = segment.location.lat - last_coordinate.lat;
|
||||
int lon_diff = segment.location.lon - last_coordinate.lon;
|
||||
delta_numbers.emplace_back(lat_diff);
|
||||
delta_numbers.emplace_back(lon_diff);
|
||||
last_coordinate = polyline[i].location;
|
||||
last_coordinate = segment.location;
|
||||
}
|
||||
}
|
||||
encodeVectorSignedNumber(delta_numbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
JSON::String return_value(output);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
|
||||
std::string &output) const
|
||||
JSON::String PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const
|
||||
{
|
||||
std::string output;
|
||||
std::vector<int> delta_numbers(2 * polyline.size());
|
||||
output += "\"";
|
||||
if (!polyline.empty())
|
||||
{
|
||||
delta_numbers[0] = polyline[0].lat;
|
||||
@ -110,53 +112,40 @@ void PolylineCompressor::printEncodedString(const std::vector<FixedPointCoordina
|
||||
}
|
||||
encodeVectorSignedNumber(delta_numbers, output);
|
||||
}
|
||||
output += "\"";
|
||||
JSON::String return_value(output);
|
||||
return return_value;
|
||||
}
|
||||
|
||||
void PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
|
||||
std::string &output) const
|
||||
|
||||
JSON::Array PolylineCompressor::printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const
|
||||
{
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for (unsigned i = 0; i < polyline.size(); i++)
|
||||
JSON::Array json_geometry_array;
|
||||
for( const auto & coordinate : polyline)
|
||||
{
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lat, tmp);
|
||||
output += "[";
|
||||
std::string tmp, output;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||
output += (tmp + ",");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||
output += tmp;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if (i < polyline.size() - 1)
|
||||
{
|
||||
output += ",";
|
||||
}
|
||||
json_geometry_array.values.push_back(output);
|
||||
}
|
||||
output += "]";
|
||||
return json_geometry_array;
|
||||
}
|
||||
|
||||
void PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline,
|
||||
std::string &output) const
|
||||
JSON::Array PolylineCompressor::printUnencodedString(const std::vector<SegmentInformation> &polyline) const
|
||||
{
|
||||
output += "[";
|
||||
std::string tmp;
|
||||
for (unsigned i = 0; i < polyline.size(); i++)
|
||||
JSON::Array json_geometry_array;
|
||||
for( const auto & segment : polyline)
|
||||
{
|
||||
if (!polyline[i].necessary)
|
||||
if (segment.necessary)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lat, tmp);
|
||||
output += "[";
|
||||
output += tmp;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(polyline[i].location.lon, tmp);
|
||||
output += ", ";
|
||||
output += tmp;
|
||||
output += "]";
|
||||
if (i < polyline.size() - 1)
|
||||
{
|
||||
output += ",";
|
||||
std::string tmp, output;
|
||||
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lat, tmp);
|
||||
output += (tmp + ",");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(segment.location.lon, tmp);
|
||||
output += tmp;
|
||||
json_geometry_array.values.push_back(output);
|
||||
}
|
||||
}
|
||||
output += "]";
|
||||
return json_geometry_array;
|
||||
}
|
||||
|
@ -28,8 +28,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef POLYLINECOMPRESSOR_H_
|
||||
#define POLYLINECOMPRESSOR_H_
|
||||
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
@ -42,17 +42,13 @@ class PolylineCompressor
|
||||
void encodeNumber(int number_to_encode, std::string &output) const;
|
||||
|
||||
public:
|
||||
void printEncodedString(const std::vector<SegmentInformation> &polyline,
|
||||
std::string &output) const;
|
||||
JSON::String printEncodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
|
||||
void printEncodedString(const std::vector<FixedPointCoordinate> &polyline,
|
||||
std::string &output) const;
|
||||
JSON::String printEncodedString(const std::vector<FixedPointCoordinate> &polyline) const;
|
||||
|
||||
void printUnencodedString(const std::vector<FixedPointCoordinate> &polyline,
|
||||
std::string &output) const;
|
||||
JSON::Array printUnencodedString(const std::vector<FixedPointCoordinate> &polyline) const;
|
||||
|
||||
void printUnencodedString(const std::vector<SegmentInformation> &polyline,
|
||||
std::string &output) const;
|
||||
JSON::Array printUnencodedString(const std::vector<SegmentInformation> &polyline) const;
|
||||
};
|
||||
|
||||
#endif /* POLYLINECOMPRESSOR_H_ */
|
||||
|
@ -38,6 +38,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StdHashExtensions.h"
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
@ -60,17 +61,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include <unordered_set>
|
||||
#include <vector>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<std::pair<NodeID, NodeID>>
|
||||
{
|
||||
size_t operator()(const std::pair<NodeID, NodeID> &pair) const
|
||||
{
|
||||
return std::hash<int>()(pair.first) ^ std::hash<int>()(pair.second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class TarjanSCC
|
||||
{
|
||||
private:
|
||||
@ -339,14 +329,17 @@ class TarjanSCC
|
||||
<< " many components, marking small components";
|
||||
|
||||
// TODO/C++11: prime candidate for lambda function
|
||||
unsigned size_one_counter = 0;
|
||||
for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
|
||||
{
|
||||
if (1 == component_size_vector[i])
|
||||
{
|
||||
++size_one_counter;
|
||||
}
|
||||
}
|
||||
// unsigned size_one_counter = 0;
|
||||
// for (unsigned i = 0, end = component_size_vector.size(); i < end; ++i)
|
||||
// {
|
||||
// if (1 == component_size_vector[i])
|
||||
// {
|
||||
// ++size_one_counter;
|
||||
// }
|
||||
// }
|
||||
unsigned size_one_counter = std::count_if(component_size_vector.begin(),
|
||||
component_size_vector.end(),
|
||||
[] (unsigned value) { return 1 == value;});
|
||||
|
||||
SimpleLogger().Write() << "identified " << size_one_counter << " SCCs of size 1";
|
||||
|
||||
|
@ -305,6 +305,12 @@ void EdgeBasedGraphFactory::CompressGeometry()
|
||||
continue;
|
||||
}
|
||||
|
||||
// check if v is a via node for a turn restriction, i.e. a 'directed' barrier node
|
||||
if (m_restriction_map->IsNodeAViaNode(v))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const bool reverse_edge_order =
|
||||
!(m_node_based_graph->GetEdgeData(m_node_based_graph->BeginEdges(v)).forward);
|
||||
const EdgeID forward_e2 = m_node_based_graph->BeginEdges(v) + reverse_edge_order;
|
||||
@ -722,7 +728,7 @@ TurnInstruction EdgeBasedGraphFactory::AnalyzeTurn(const NodeID u,
|
||||
if (data1.roundabout && data2.roundabout)
|
||||
{
|
||||
// Is a turn possible? If yes, we stay on the roundabout!
|
||||
if (1 == m_node_based_graph->GetOutDegree(v))
|
||||
if (1 == m_node_based_graph->GetDirectedOutDegree(v))
|
||||
{
|
||||
// No turn possible.
|
||||
return TurnInstruction::NoTurn;
|
||||
|
@ -1,331 +1,380 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset()
|
||||
{
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const
|
||||
{
|
||||
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::isValid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// 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 double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2)
|
||||
{
|
||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const double RAD = 0.017453292519943295769236907684886;
|
||||
const double float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const double float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const double float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const double float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const double x = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.);
|
||||
const double y = (float_lat2 - float_lat1);
|
||||
const double earth_radius = 6372797.560856;
|
||||
return sqrt(x * x + y * y) * earth_radius;
|
||||
}
|
||||
|
||||
// Yuck! Code duplication. This function is also in EgdeBasedNode.h
|
||||
double FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
||||
const FixedPointCoordinate &segA,
|
||||
const FixedPointCoordinate &segB)
|
||||
{
|
||||
const double x = lat2y(point.lat / COORDINATE_PRECISION);
|
||||
const double y = point.lon / COORDINATE_PRECISION;
|
||||
const double a = lat2y(segA.lat / COORDINATE_PRECISION);
|
||||
const double b = segA.lon / COORDINATE_PRECISION;
|
||||
const double c = lat2y(segB.lat / COORDINATE_PRECISION);
|
||||
const double d = segB.lon / COORDINATE_PRECISION;
|
||||
double p, q, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
double r = (p - nY * a) / c;
|
||||
if (std::isnan(r))
|
||||
{
|
||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
||||
}
|
||||
else if (std::abs(r) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
r = 0.;
|
||||
}
|
||||
else if (std::abs(r - 1.) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
r = 1.;
|
||||
}
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT(!std::isnan(r));
|
||||
if (r <= 0.)
|
||||
{ // point is "left" of edge
|
||||
nearest_location.lat = segA.lat;
|
||||
nearest_location.lon = segA.lon;
|
||||
}
|
||||
else if (r >= 1.)
|
||||
{ // point is "right" of edge
|
||||
nearest_location.lat = segB.lat;
|
||||
nearest_location.lon = segB.lon;
|
||||
}
|
||||
else
|
||||
{ // point lies in between
|
||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.isValid());
|
||||
const double approximated_distance =
|
||||
FixedPointCoordinate::ApproximateDistance(point, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximated_distance);
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
||||
const FixedPointCoordinate &coord_b,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
double &r)
|
||||
{
|
||||
BOOST_ASSERT(query_location.isValid());
|
||||
|
||||
const double x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const double y = query_location.lon / COORDINATE_PRECISION;
|
||||
const double a = lat2y(coord_a.lat / COORDINATE_PRECISION);
|
||||
const double b = coord_a.lon / COORDINATE_PRECISION;
|
||||
const double c = lat2y(coord_b.lat / COORDINATE_PRECISION);
|
||||
const double d = coord_b.lon / COORDINATE_PRECISION;
|
||||
double p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
const double m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
r = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(r))
|
||||
{
|
||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||
}
|
||||
else if (std::abs(r) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
r = 0.;
|
||||
}
|
||||
else if (std::abs(r - 1.) <= std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
r = 1.;
|
||||
}
|
||||
BOOST_ASSERT(!std::isnan(r));
|
||||
if (r <= 0.)
|
||||
{
|
||||
nearest_location.lat = coord_a.lat;
|
||||
nearest_location.lon = coord_a.lon;
|
||||
}
|
||||
else if (r >= 1.)
|
||||
{
|
||||
nearest_location.lat = coord_b.lat;
|
||||
nearest_location.lon = coord_b.lon;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.isValid());
|
||||
|
||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||
// const double approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const double approximated_distance =
|
||||
FixedPointCoordinate::ApproximateDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximated_distance);
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include <osrm/Coordinate.h>
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../Util/TrigonometryTables.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <bitset>
|
||||
#endif
|
||||
#include <iostream>
|
||||
#include <limits>
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate()
|
||||
: lat(std::numeric_limits<int>::min()), lon(std::numeric_limits<int>::min())
|
||||
{
|
||||
}
|
||||
|
||||
FixedPointCoordinate::FixedPointCoordinate(int lat, int lon) : lat(lat), lon(lon)
|
||||
{
|
||||
#ifndef NDEBUG
|
||||
if (0 != (std::abs(lat) >> 30))
|
||||
{
|
||||
std::bitset<32> y(lat);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lat: " << lat << ", bits: " << y;
|
||||
}
|
||||
if (0 != (std::abs(lon) >> 30))
|
||||
{
|
||||
std::bitset<32> x(lon);
|
||||
SimpleLogger().Write(logDEBUG) << "broken lon: " << lon << ", bits: " << x;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Reset()
|
||||
{
|
||||
lat = std::numeric_limits<int>::min();
|
||||
lon = std::numeric_limits<int>::min();
|
||||
}
|
||||
bool FixedPointCoordinate::isSet() const
|
||||
{
|
||||
return (std::numeric_limits<int>::min() != lat) && (std::numeric_limits<int>::min() != lon);
|
||||
}
|
||||
bool FixedPointCoordinate::isValid() const
|
||||
{
|
||||
if (lat > 90 * COORDINATE_PRECISION || lat < -90 * COORDINATE_PRECISION ||
|
||||
lon > 180 * COORDINATE_PRECISION || lon < -180 * COORDINATE_PRECISION)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
bool FixedPointCoordinate::operator==(const FixedPointCoordinate &other) const
|
||||
{
|
||||
return lat == other.lat && lon == other.lon;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
double RAD = 0.017453292519943295769236907684886;
|
||||
double lt1 = lat1 / COORDINATE_PRECISION;
|
||||
double ln1 = lon1 / COORDINATE_PRECISION;
|
||||
double lt2 = lat2 / COORDINATE_PRECISION;
|
||||
double ln2 = lon2 / COORDINATE_PRECISION;
|
||||
double dlat1 = lt1 * (RAD);
|
||||
|
||||
double dlong1 = ln1 * (RAD);
|
||||
double dlat2 = lt2 * (RAD);
|
||||
double dlong2 = ln2 * (RAD);
|
||||
|
||||
double dLong = dlong1 - dlong2;
|
||||
double dLat = dlat1 - dlat2;
|
||||
|
||||
double aHarv = pow(sin(dLat / 2.0), 2.0) + cos(dlat1) * cos(dlat2) * pow(sin(dLong / 2.), 2);
|
||||
double cHarv = 2. * atan2(sqrt(aHarv), sqrt(1.0 - aHarv));
|
||||
// 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 double earth = 6372797.560856;
|
||||
return earth * cHarv;
|
||||
}
|
||||
|
||||
double FixedPointCoordinate::ApproximateDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2)
|
||||
{
|
||||
return ApproximateDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2)
|
||||
{
|
||||
return ApproximateEuclideanDistance(c1.lat, c1.lon, c2.lat, c2.lon);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ApproximateEuclideanDistance(const int lat1,
|
||||
const int lon1,
|
||||
const int lat2,
|
||||
const int lon2)
|
||||
{
|
||||
BOOST_ASSERT(lat1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon1 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lat2 != std::numeric_limits<int>::min());
|
||||
BOOST_ASSERT(lon2 != std::numeric_limits<int>::min());
|
||||
|
||||
const float RAD = 0.017453292519943295769236907684886;
|
||||
const float float_lat1 = (lat1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon1 = (lon1 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lat2 = (lat2 / COORDINATE_PRECISION) * RAD;
|
||||
const float float_lon2 = (lon2 / COORDINATE_PRECISION) * RAD;
|
||||
|
||||
const float x = (float_lon2 - float_lon1) * cos((float_lat1 + float_lat2) / 2.);
|
||||
const float y = (float_lat2 - float_lat1);
|
||||
const float earth_radius = 6372797.560856;
|
||||
return sqrt(x * x + y * y) * earth_radius;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
||||
const FixedPointCoordinate &segA,
|
||||
const FixedPointCoordinate &segB)
|
||||
{
|
||||
const float x = lat2y(point.lat / COORDINATE_PRECISION);
|
||||
const float y = point.lon / COORDINATE_PRECISION;
|
||||
const float a = lat2y(segA.lat / COORDINATE_PRECISION);
|
||||
const float b = segA.lon / COORDINATE_PRECISION;
|
||||
const float c = lat2y(segB.lat / COORDINATE_PRECISION);
|
||||
const float d = segB.lon / COORDINATE_PRECISION;
|
||||
float p, q, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
float r = (p - nY * a) / c;
|
||||
if (std::isnan(r))
|
||||
{
|
||||
r = ((segB.lat == point.lat) && (segB.lon == point.lon)) ? 1. : 0.;
|
||||
}
|
||||
else if (std::abs(r) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
r = 0.;
|
||||
}
|
||||
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
r = 1.;
|
||||
}
|
||||
FixedPointCoordinate nearest_location;
|
||||
BOOST_ASSERT(!std::isnan(r));
|
||||
if (r <= 0.)
|
||||
{ // point is "left" of edge
|
||||
nearest_location.lat = segA.lat;
|
||||
nearest_location.lon = segA.lon;
|
||||
}
|
||||
else if (r >= 1.)
|
||||
{ // point is "right" of edge
|
||||
nearest_location.lat = segB.lat;
|
||||
nearest_location.lon = segB.lon;
|
||||
}
|
||||
else
|
||||
{ // point lies in between
|
||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.isValid());
|
||||
const float approximated_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(point, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximated_distance);
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
||||
const FixedPointCoordinate &coord_b,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
float &r)
|
||||
{
|
||||
BOOST_ASSERT(query_location.isValid());
|
||||
|
||||
const float x = lat2y(query_location.lat / COORDINATE_PRECISION);
|
||||
const float y = query_location.lon / COORDINATE_PRECISION;
|
||||
const float a = lat2y(coord_a.lat / COORDINATE_PRECISION);
|
||||
const float b = coord_a.lon / COORDINATE_PRECISION;
|
||||
const float c = lat2y(coord_b.lat / COORDINATE_PRECISION);
|
||||
const float d = coord_b.lon / COORDINATE_PRECISION;
|
||||
float p, q /*,mX*/, nY;
|
||||
if (std::abs(a - c) > std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
const float m = (d - b) / (c - a); // slope
|
||||
// Projection of (x,y) on line joining (a,b) and (c,d)
|
||||
p = ((x + (m * y)) + (m * m * a - m * b)) / (1. + m * m);
|
||||
q = b + m * (p - a);
|
||||
}
|
||||
else
|
||||
{
|
||||
p = c;
|
||||
q = y;
|
||||
}
|
||||
nY = (d * p - c * q) / (a * d - b * c);
|
||||
|
||||
// discretize the result to coordinate precision. it's a hack!
|
||||
if (std::abs(nY) < (1. / COORDINATE_PRECISION))
|
||||
{
|
||||
nY = 0.;
|
||||
}
|
||||
|
||||
r = (p - nY * a) / c; // These values are actually n/m+n and m/m+n , we need
|
||||
// not calculate the explicit values of m an n as we
|
||||
// are just interested in the ratio
|
||||
if (std::isnan(r))
|
||||
{
|
||||
r = ((coord_b.lat == query_location.lat) && (coord_b.lon == query_location.lon)) ? 1. : 0.;
|
||||
}
|
||||
else if (std::abs(r) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
r = 0.;
|
||||
}
|
||||
else if (std::abs(r - 1.) <= std::numeric_limits<float>::epsilon())
|
||||
{
|
||||
r = 1.;
|
||||
}
|
||||
BOOST_ASSERT(!std::isnan(r));
|
||||
if (r <= 0.)
|
||||
{
|
||||
nearest_location = coord_a;
|
||||
}
|
||||
else if (r >= 1.)
|
||||
{
|
||||
nearest_location = coord_b;
|
||||
}
|
||||
else
|
||||
{
|
||||
// point lies in between
|
||||
nearest_location.lat = y2lat(p) * COORDINATE_PRECISION;
|
||||
nearest_location.lon = q * COORDINATE_PRECISION;
|
||||
}
|
||||
BOOST_ASSERT(nearest_location.isValid());
|
||||
|
||||
// TODO: Replace with euclidean approximation when k-NN search is done
|
||||
// const float approximated_distance = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float approximated_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(query_location, nearest_location);
|
||||
BOOST_ASSERT(0. <= approximated_distance);
|
||||
return approximated_distance;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalLatLonToString(const int value, std::string &output)
|
||||
{
|
||||
char buffer[12];
|
||||
buffer[11] = 0; // zero termination
|
||||
output = printInt<11, 6>(buffer, value);
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::convertInternalCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output)
|
||||
{
|
||||
std::string tmp;
|
||||
tmp.reserve(23);
|
||||
convertInternalLatLonToString(coord.lat, tmp);
|
||||
output = tmp;
|
||||
output += ",";
|
||||
convertInternalLatLonToString(coord.lon, tmp);
|
||||
output += tmp;
|
||||
}
|
||||
|
||||
void FixedPointCoordinate::Output(std::ostream &out) const
|
||||
{
|
||||
out << "(" << lat / COORDINATE_PRECISION << "," << lon / COORDINATE_PRECISION << ")";
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
|
||||
{
|
||||
const float delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
|
||||
const float y = sin(delta_long) * cos(lat2);
|
||||
const float x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::GetBearing(const FixedPointCoordinate &other) const
|
||||
{
|
||||
const float delta_long = DegreeToRadian(lon / COORDINATE_PRECISION - other.lon / COORDINATE_PRECISION);
|
||||
const float lat1 = DegreeToRadian(other.lat / COORDINATE_PRECISION);
|
||||
const float lat2 = DegreeToRadian(lat / COORDINATE_PRECISION);
|
||||
const float y = std::sin(delta_long) * std::cos(lat2);
|
||||
const float x = std::cos(lat1) * std::sin(lat2) - std::sin(lat1) * std::cos(lat2) * std::cos(delta_long);
|
||||
float result = RadianToDegree(std::atan2(y, x));
|
||||
|
||||
while (result < 0.f)
|
||||
{
|
||||
result += 360.f;
|
||||
}
|
||||
|
||||
while (result >= 360.f)
|
||||
{
|
||||
result -= 360.f;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::DegreeToRadian(const float degree)
|
||||
{
|
||||
return degree * (M_PI / 180.f);
|
||||
}
|
||||
|
||||
float FixedPointCoordinate::RadianToDegree(const float radian)
|
||||
{
|
||||
return radian * (180.f / M_PI);
|
||||
}
|
||||
|
@ -117,6 +117,19 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
|
||||
unsigned GetOutDegree(const NodeIterator n) const { return m_nodes[n].edges; }
|
||||
|
||||
unsigned GetDirectedOutDegree(const NodeIterator n) const
|
||||
{
|
||||
unsigned degree = 0;
|
||||
for(EdgeIterator edge = BeginEdges(n); edge < EndEdges(n); ++edge)
|
||||
{
|
||||
if (GetEdgeData(edge).forward)
|
||||
{
|
||||
++degree;
|
||||
}
|
||||
}
|
||||
return degree;
|
||||
}
|
||||
|
||||
NodeIterator GetTarget(const EdgeIterator e) const { return NodeIterator(m_edges[e].target); }
|
||||
|
||||
void SetTarget(const EdgeIterator e, const NodeIterator n) { m_edges[e].target = n; }
|
||||
@ -135,7 +148,7 @@ template <typename EdgeDataT> class DynamicGraph
|
||||
return EdgeIterator(m_nodes[n].firstEdge + m_nodes[n].edges);
|
||||
}
|
||||
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeID node) const
|
||||
EdgeRange GetAdjacentEdgeRange(const NodeIterator node) const
|
||||
{
|
||||
return boost::irange(BeginEdges(node), EndEdges(node));
|
||||
}
|
||||
|
237
DataStructures/JSONContainer.h
Normal file
237
DataStructures/JSONContainer.h
Normal file
@ -0,0 +1,237 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
// based on https://svn.apache.org/repos/asf/mesos/tags/release-0.9.0-incubating-RC0/src/common/json.hpp
|
||||
|
||||
#ifndef JSON_CONTAINER_H
|
||||
#define JSON_CONTAINER_H
|
||||
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <boost/variant.hpp>
|
||||
|
||||
#include <iostream>
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace JSON
|
||||
{
|
||||
|
||||
struct String;
|
||||
struct Number;
|
||||
struct Object;
|
||||
struct Array;
|
||||
struct True;
|
||||
struct False;
|
||||
struct Null;
|
||||
|
||||
typedef boost::variant<boost::recursive_wrapper<String>,
|
||||
boost::recursive_wrapper<Number>,
|
||||
boost::recursive_wrapper<Object>,
|
||||
boost::recursive_wrapper<Array>,
|
||||
boost::recursive_wrapper<True>,
|
||||
boost::recursive_wrapper<False>,
|
||||
boost::recursive_wrapper<Null> > Value;
|
||||
|
||||
struct String
|
||||
{
|
||||
String() {}
|
||||
String(const char *value) : value(value) {}
|
||||
String(const std::string &value) : value(value) {}
|
||||
std::string value;
|
||||
};
|
||||
|
||||
struct Number
|
||||
{
|
||||
Number() {}
|
||||
Number(double value) : value(value) {}
|
||||
double value;
|
||||
};
|
||||
|
||||
struct Object
|
||||
{
|
||||
std::unordered_map<std::string, Value> values;
|
||||
};
|
||||
|
||||
struct Array
|
||||
{
|
||||
std::vector<Value> values;
|
||||
};
|
||||
|
||||
struct True
|
||||
{
|
||||
};
|
||||
|
||||
struct False
|
||||
{
|
||||
};
|
||||
|
||||
struct Null
|
||||
{
|
||||
};
|
||||
|
||||
struct Renderer : boost::static_visitor<>
|
||||
{
|
||||
Renderer(std::ostream &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const { out << "\"" << string.value << "\""; }
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
out.precision(10);
|
||||
out << number.value;
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
out << "{";
|
||||
auto iterator = object.values.begin();
|
||||
while (iterator != object.values.end())
|
||||
{
|
||||
out << "\"" << (*iterator).first << "\":";
|
||||
boost::apply_visitor(Renderer(out), (*iterator).second);
|
||||
if (++iterator != object.values.end())
|
||||
{
|
||||
out << ",";
|
||||
}
|
||||
}
|
||||
out << "}";
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
out << "[";
|
||||
std::vector<Value>::const_iterator iterator;
|
||||
iterator = array.values.begin();
|
||||
while (iterator != array.values.end())
|
||||
{
|
||||
boost::apply_visitor(Renderer(out), *iterator);
|
||||
if (++iterator != array.values.end())
|
||||
{
|
||||
out << ",";
|
||||
}
|
||||
}
|
||||
out << "]";
|
||||
}
|
||||
|
||||
void operator()(const True &) const { out << "true"; }
|
||||
|
||||
void operator()(const False &) const { out << "false"; }
|
||||
|
||||
void operator()(const Null &) const { out << "null"; }
|
||||
|
||||
private:
|
||||
std::ostream &out;
|
||||
};
|
||||
|
||||
struct ArrayRenderer : boost::static_visitor<>
|
||||
{
|
||||
ArrayRenderer(std::vector<char> &_out) : out(_out) {}
|
||||
|
||||
void operator()(const String &string) const {
|
||||
out.push_back('\"');
|
||||
out.insert(out.end(), string.value.begin(), string.value.end());
|
||||
out.push_back('\"');
|
||||
}
|
||||
|
||||
void operator()(const Number &number) const
|
||||
{
|
||||
const std::string number_string = FixedDoubleToString(number.value);
|
||||
out.insert(out.end(), number_string.begin(), number_string.end());
|
||||
}
|
||||
|
||||
void operator()(const Object &object) const
|
||||
{
|
||||
out.push_back('{');
|
||||
auto iterator = object.values.begin();
|
||||
while (iterator != object.values.end())
|
||||
{
|
||||
out.push_back('\"');
|
||||
out.insert(out.end(), (*iterator).first.begin(), (*iterator).first.end());
|
||||
out.push_back('\"');
|
||||
out.push_back(':');
|
||||
|
||||
boost::apply_visitor(ArrayRenderer(out), (*iterator).second);
|
||||
if (++iterator != object.values.end())
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back('}');
|
||||
}
|
||||
|
||||
void operator()(const Array &array) const
|
||||
{
|
||||
out.push_back('[');
|
||||
std::vector<Value>::const_iterator iterator;
|
||||
iterator = array.values.begin();
|
||||
while (iterator != array.values.end())
|
||||
{
|
||||
boost::apply_visitor(ArrayRenderer(out), *iterator);
|
||||
if (++iterator != array.values.end())
|
||||
{
|
||||
out.push_back(',');
|
||||
}
|
||||
}
|
||||
out.push_back(']');
|
||||
}
|
||||
|
||||
void operator()(const True &) const {
|
||||
const std::string temp("true");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const False &) const {
|
||||
const std::string temp("false");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
void operator()(const Null &) const {
|
||||
const std::string temp("null");
|
||||
out.insert(out.end(), temp.begin(), temp.end());
|
||||
}
|
||||
|
||||
private:
|
||||
std::vector<char> &out;
|
||||
};
|
||||
|
||||
inline void render(std::ostream &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
boost::apply_visitor(Renderer(out), value);
|
||||
}
|
||||
|
||||
inline void render(std::vector<char> &out, const Object &object)
|
||||
{
|
||||
Value value = object;
|
||||
boost::apply_visitor(ArrayRenderer(out), value);
|
||||
}
|
||||
|
||||
} // namespace JSON
|
||||
|
||||
#endif // JSON_CONTAINER_H
|
@ -115,6 +115,12 @@ struct PhantomNode
|
||||
);
|
||||
}
|
||||
|
||||
bool isValid() const
|
||||
{
|
||||
return location.isValid() &&
|
||||
(name_id != std::numeric_limits<unsigned>::max());
|
||||
}
|
||||
|
||||
bool operator==(const PhantomNode & other) const
|
||||
{
|
||||
return location == other.location;
|
||||
|
@ -1,6 +1,40 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#include "RestrictionMap.h"
|
||||
#include "NodeBasedGraph.h"
|
||||
|
||||
#include "../Util/SimpleLogger.h"
|
||||
|
||||
bool RestrictionMap::IsNodeAViaNode(const NodeID node) const
|
||||
{
|
||||
return m_no_turn_via_node_set.find(node) != m_no_turn_via_node_set.end();
|
||||
}
|
||||
|
||||
RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &graph,
|
||||
const std::vector<TurnRestriction> &input_restrictions_list)
|
||||
: m_count(0), m_graph(graph)
|
||||
@ -9,8 +43,12 @@ RestrictionMap::RestrictionMap(const std::shared_ptr<NodeBasedDynamicGraph> &gra
|
||||
// and all end-nodes
|
||||
for (auto &restriction : input_restrictions_list)
|
||||
{
|
||||
|
||||
m_no_turn_via_node_set.insert(restriction.viaNode);
|
||||
|
||||
std::pair<NodeID, NodeID> restriction_source =
|
||||
std::make_pair(restriction.fromNode, restriction.viaNode);
|
||||
|
||||
unsigned index;
|
||||
auto restriction_iter = m_restriction_map.find(restriction_source);
|
||||
if (restriction_iter == m_restriction_map.end())
|
||||
@ -70,7 +108,9 @@ void RestrictionMap::FixupArrivingTurnRestriction(const NodeID u, const NodeID v
|
||||
const std::pair<NodeID, NodeID> restr_start = std::make_pair(x, u);
|
||||
auto restriction_iterator = m_restriction_map.find(restr_start);
|
||||
if (restriction_iterator == m_restriction_map.end())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const unsigned index = restriction_iterator->second;
|
||||
auto &bucket = m_restriction_bucket_list.at(index);
|
||||
@ -141,6 +181,7 @@ NodeID RestrictionMap::CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID
|
||||
*/
|
||||
bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const
|
||||
{
|
||||
// SimpleLogger().Write(logDEBUG) << "checking turn <" << u << "," << v << "," << w << ">";
|
||||
BOOST_ASSERT(u != std::numeric_limits<unsigned>::max());
|
||||
BOOST_ASSERT(v != std::numeric_limits<unsigned>::max());
|
||||
BOOST_ASSERT(w != std::numeric_limits<unsigned>::max());
|
||||
@ -162,6 +203,5 @@ bool RestrictionMap::CheckIfTurnIsRestricted(const NodeID u, const NodeID v, con
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
@ -30,17 +30,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "../typedefs.h"
|
||||
#include "DynamicGraph.h"
|
||||
#include "Restriction.h"
|
||||
#include "NodeBasedGraph.h"
|
||||
#include "../Util/StdHashExtensions.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/unordered_map.hpp>
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
|
||||
/*!
|
||||
* Makee it efficent to look up if an edge is the start + via node of a TurnRestriction.
|
||||
* Is needed by EdgeBasedGraphFactory.
|
||||
*/
|
||||
|
||||
// Make it efficent to look up if an edge is the start + via node of a TurnRestriction
|
||||
// EdgeBasedEdgeFactory decides by it if edges are inserted or geometry is compressed
|
||||
class RestrictionMap
|
||||
{
|
||||
public:
|
||||
@ -51,7 +52,7 @@ class RestrictionMap
|
||||
void FixupStartingTurnRestriction(const NodeID u, const NodeID v, const NodeID w);
|
||||
NodeID CheckForEmanatingIsOnlyTurn(const NodeID u, const NodeID v) const;
|
||||
bool CheckIfTurnIsRestricted(const NodeID u, const NodeID v, const NodeID w) const;
|
||||
|
||||
bool IsNodeAViaNode(const NodeID node) const;
|
||||
unsigned size() { return m_count; }
|
||||
|
||||
private:
|
||||
@ -65,7 +66,8 @@ class RestrictionMap
|
||||
//! index -> list of (target, isOnly)
|
||||
std::vector<EmanatingRestrictionsVector> m_restriction_bucket_list;
|
||||
//! maps (start, via) -> bucket index
|
||||
boost::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||
std::unordered_map<RestrictionSource, unsigned> m_restriction_map;
|
||||
std::unordered_set<NodeID> m_no_turn_via_node_set;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -30,6 +30,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#include "SearchEngineData.h"
|
||||
#include "../RoutingAlgorithms/AlternativePathRouting.h"
|
||||
#include "../RoutingAlgorithms/ManyToManyRouting.h"
|
||||
#include "../RoutingAlgorithms/ShortestPathRouting.h"
|
||||
|
||||
template <class DataFacadeT> class SearchEngine
|
||||
@ -41,10 +42,11 @@ template <class DataFacadeT> class SearchEngine
|
||||
public:
|
||||
ShortestPathRouting<DataFacadeT> shortest_path;
|
||||
AlternativeRouting<DataFacadeT> alternative_path;
|
||||
ManyToManyRouting<DataFacadeT> distance_table;
|
||||
|
||||
explicit SearchEngine(DataFacadeT *facade)
|
||||
: facade(facade), shortest_path(facade, engine_working_data),
|
||||
alternative_path(facade, engine_working_data)
|
||||
alternative_path(facade, engine_working_data), distance_table(facade, engine_working_data)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -128,7 +128,7 @@ class StaticRTree
|
||||
Contains(lower_left));
|
||||
}
|
||||
|
||||
inline double GetMinDist(const FixedPointCoordinate &location) const
|
||||
inline float GetMinDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
bool is_contained = Contains(location);
|
||||
if (is_contained)
|
||||
@ -136,7 +136,7 @@ class StaticRTree
|
||||
return 0.;
|
||||
}
|
||||
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
min_dist = std::min(min_dist,
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
location.lat, location.lon, max_lat, min_lon));
|
||||
@ -152,9 +152,9 @@ class StaticRTree
|
||||
return min_dist;
|
||||
}
|
||||
|
||||
inline double GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
inline float GetMinMaxDist(const FixedPointCoordinate &location) const
|
||||
{
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
// Get minmax distance to each of the four sides
|
||||
FixedPointCoordinate upper_left(max_lat, min_lon);
|
||||
FixedPointCoordinate upper_right(max_lat, max_lon);
|
||||
@ -240,13 +240,13 @@ class StaticRTree
|
||||
|
||||
struct QueryCandidate
|
||||
{
|
||||
explicit QueryCandidate(const uint32_t n_id, const double dist)
|
||||
explicit QueryCandidate(const uint32_t n_id, const float dist)
|
||||
: node_id(n_id), min_dist(dist)
|
||||
{
|
||||
}
|
||||
QueryCandidate() : node_id(UINT_MAX), min_dist(std::numeric_limits<double>::max()) {}
|
||||
QueryCandidate() : node_id(UINT_MAX), min_dist(std::numeric_limits<float>::max()) {}
|
||||
uint32_t node_id;
|
||||
double min_dist;
|
||||
float min_dist;
|
||||
inline bool operator<(const QueryCandidate &other) const
|
||||
{
|
||||
return min_dist < other.min_dist;
|
||||
@ -490,13 +490,13 @@ class StaticRTree
|
||||
{
|
||||
bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
bool found_a_nearest_edge = false;
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
double current_min_dist =
|
||||
float current_min_dist =
|
||||
m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||
traversal_queue.emplace(0, current_min_dist);
|
||||
|
||||
@ -522,7 +522,7 @@ class StaticRTree
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_minimum_distance =
|
||||
float current_minimum_distance =
|
||||
FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
input_coordinate.lat,
|
||||
input_coordinate.lon,
|
||||
@ -563,9 +563,9 @@ class StaticRTree
|
||||
const TreeNode &child_tree_node = m_search_tree[child_id];
|
||||
const RectangleT &child_rectangle =
|
||||
child_tree_node.minimum_bounding_rectangle;
|
||||
const double current_min_dist =
|
||||
const float current_min_dist =
|
||||
child_rectangle.GetMinDist(input_coordinate);
|
||||
const double current_min_max_dist =
|
||||
const float current_min_max_dist =
|
||||
child_rectangle.GetMinMaxDist(input_coordinate);
|
||||
if (current_min_max_dist < min_max_dist)
|
||||
{
|
||||
@ -597,19 +597,19 @@ class StaticRTree
|
||||
const bool ignore_tiny_components = (zoom_level <= 14);
|
||||
DataT nearest_edge;
|
||||
|
||||
double min_dist = std::numeric_limits<double>::max();
|
||||
double min_max_dist = std::numeric_limits<double>::max();
|
||||
float min_dist = std::numeric_limits<float>::max();
|
||||
float min_max_dist = std::numeric_limits<float>::max();
|
||||
bool found_a_nearest_edge = false;
|
||||
|
||||
FixedPointCoordinate nearest, current_start_coordinate, current_end_coordinate;
|
||||
|
||||
// initialize queue with root element
|
||||
std::priority_queue<QueryCandidate> traversal_queue;
|
||||
double current_min_dist =
|
||||
float current_min_dist =
|
||||
m_search_tree[0].minimum_bounding_rectangle.GetMinDist(input_coordinate);
|
||||
traversal_queue.emplace(0, current_min_dist);
|
||||
|
||||
BOOST_ASSERT_MSG(std::numeric_limits<double>::epsilon() >
|
||||
BOOST_ASSERT_MSG(std::numeric_limits<float>::epsilon() >
|
||||
(0. - traversal_queue.top().min_dist),
|
||||
"Root element in NN Search has min dist != 0.");
|
||||
|
||||
@ -635,8 +635,8 @@ class StaticRTree
|
||||
continue;
|
||||
}
|
||||
|
||||
double current_ratio = 0.;
|
||||
const double current_perpendicular_distance =
|
||||
float current_ratio = 0.;
|
||||
const float current_perpendicular_distance =
|
||||
FixedPointCoordinate::ComputePerpendicularDistance(
|
||||
m_coordinate_list->at(current_edge.u),
|
||||
m_coordinate_list->at(current_edge.v),
|
||||
@ -647,7 +647,7 @@ class StaticRTree
|
||||
BOOST_ASSERT(0. <= current_perpendicular_distance);
|
||||
|
||||
if ((current_perpendicular_distance < min_dist) &&
|
||||
!DoubleEpsilonCompare(current_perpendicular_distance, min_dist))
|
||||
!EpsilonCompare(current_perpendicular_distance, min_dist))
|
||||
{ // found a new minimum
|
||||
min_dist = current_perpendicular_distance;
|
||||
// TODO: use assignment c'tor in PhantomNode
|
||||
@ -685,9 +685,9 @@ class StaticRTree
|
||||
const int32_t child_id = current_tree_node.children[i];
|
||||
TreeNode &child_tree_node = m_search_tree[child_id];
|
||||
RectangleT &child_rectangle = child_tree_node.minimum_bounding_rectangle;
|
||||
const double current_min_dist =
|
||||
const float current_min_dist =
|
||||
child_rectangle.GetMinDist(input_coordinate);
|
||||
const double current_min_max_dist =
|
||||
const float current_min_max_dist =
|
||||
child_rectangle.GetMinMaxDist(input_coordinate);
|
||||
if (current_min_max_dist < min_max_dist)
|
||||
{
|
||||
@ -717,18 +717,18 @@ class StaticRTree
|
||||
result_phantom_node.location.lat = input_coordinate.lat;
|
||||
}
|
||||
|
||||
double ratio = 0.;
|
||||
float ratio = 0.f;
|
||||
|
||||
if (found_a_nearest_edge)
|
||||
{
|
||||
const double distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_1 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
current_start_coordinate, result_phantom_node.location);
|
||||
|
||||
const double distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
const float distance_2 = FixedPointCoordinate::ApproximateEuclideanDistance(
|
||||
current_start_coordinate, current_end_coordinate);
|
||||
|
||||
ratio = distance_1 / distance_2;
|
||||
ratio = std::min(1., ratio);
|
||||
ratio = std::min(1.f, ratio);
|
||||
|
||||
if (SPECIAL_NODEID != result_phantom_node.forward_node_id)
|
||||
{
|
||||
@ -768,9 +768,10 @@ class StaticRTree
|
||||
return (a == b && c == d) || (a == c && b == d) || (a == d && b == c);
|
||||
}
|
||||
|
||||
inline bool DoubleEpsilonCompare(const double d1, const double d2) const
|
||||
template<typename FloatT>
|
||||
inline bool EpsilonCompare(const FloatT d1, const FloatT d2) const
|
||||
{
|
||||
return (std::abs(d1 - d2) < std::numeric_limits<double>::epsilon());
|
||||
return (std::abs(d1 - d2) < std::numeric_limits<FloatT>::epsilon());
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -80,7 +80,9 @@ struct TurnInstructionsClass
|
||||
static inline bool TurnIsNecessary(const TurnInstruction turn_instruction)
|
||||
{
|
||||
if (TurnInstruction::NoTurn == turn_instruction || TurnInstruction::StayOnRoundAbout == turn_instruction)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
@ -56,7 +56,6 @@ template <class DataFacadeT> class BaseDescriptor
|
||||
virtual ~BaseDescriptor() {}
|
||||
virtual void Run(const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
DataFacadeT *facade,
|
||||
http::Reply &reply) = 0;
|
||||
virtual void SetConfig(const DescriptorConfig &config) = 0;
|
||||
};
|
||||
|
@ -29,41 +29,6 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
DescriptionFactory::DescriptionFactory() : entireLength(0) {}
|
||||
|
||||
DescriptionFactory::~DescriptionFactory() {}
|
||||
|
||||
inline double DescriptionFactory::DegreeToRadian(const double degree) const
|
||||
{
|
||||
return degree * (M_PI / 180.);
|
||||
}
|
||||
|
||||
inline double DescriptionFactory::RadianToDegree(const double radian) const
|
||||
{
|
||||
return radian * (180. / M_PI);
|
||||
}
|
||||
|
||||
double DescriptionFactory::GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B)
|
||||
const
|
||||
{
|
||||
double delta_long = DegreeToRadian(B.lon / COORDINATE_PRECISION - A.lon / COORDINATE_PRECISION);
|
||||
|
||||
const double lat1 = DegreeToRadian(A.lat / COORDINATE_PRECISION);
|
||||
const double lat2 = DegreeToRadian(B.lat / COORDINATE_PRECISION);
|
||||
|
||||
const double y = sin(delta_long) * cos(lat2);
|
||||
const double x = cos(lat1) * sin(lat2) - sin(lat1) * cos(lat2) * cos(delta_long);
|
||||
double result = RadianToDegree(atan2(y, x));
|
||||
while (result < 0.)
|
||||
{
|
||||
result += 360.;
|
||||
}
|
||||
|
||||
while (result >= 360.)
|
||||
{
|
||||
result -= 360.;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void DescriptionFactory::SetStartSegment(const PhantomNode &source)
|
||||
{
|
||||
start_phantom = source;
|
||||
@ -83,49 +48,33 @@ void DescriptionFactory::AppendSegment(const FixedPointCoordinate &coordinate,
|
||||
if ((1 == path_description.size()) && (path_description.back().location == coordinate))
|
||||
{
|
||||
path_description.back().name_id = path_point.name_id;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
path_description.emplace_back(coordinate,
|
||||
path_point.name_id,
|
||||
path_point.segment_duration,
|
||||
0,
|
||||
path_point.turn_instruction);
|
||||
}
|
||||
|
||||
path_description.emplace_back(coordinate,
|
||||
path_point.name_id,
|
||||
path_point.segment_duration,
|
||||
0,
|
||||
path_point.turn_instruction);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded,
|
||||
std::vector<std::string> &output)
|
||||
JSON::Value DescriptionFactory::AppendEncodedPolylineString(const bool return_encoded)
|
||||
{
|
||||
std::string temp;
|
||||
if (return_encoded)
|
||||
{
|
||||
polyline_compressor.printEncodedString(path_description, temp);
|
||||
return polyline_compressor.printEncodedString(path_description);
|
||||
}
|
||||
else
|
||||
{
|
||||
polyline_compressor.printUnencodedString(path_description, temp);
|
||||
}
|
||||
output.emplace_back(temp);
|
||||
return polyline_compressor.printUnencodedString(path_description);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendEncodedPolylineString(std::vector<std::string> &output) const
|
||||
JSON::Value DescriptionFactory::AppendUnencodedPolylineString() const
|
||||
{
|
||||
std::string temp;
|
||||
polyline_compressor.printEncodedString(path_description, temp);
|
||||
output.emplace_back(temp);
|
||||
}
|
||||
|
||||
void DescriptionFactory::AppendUnencodedPolylineString(std::vector<std::string> &output) const
|
||||
{
|
||||
std::string temp;
|
||||
polyline_compressor.printUnencodedString(path_description, temp);
|
||||
output.emplace_back(temp);
|
||||
return polyline_compressor.printUnencodedString(path_description);
|
||||
}
|
||||
|
||||
void DescriptionFactory::BuildRouteSummary(const double distance, const unsigned time)
|
||||
{
|
||||
summary.startName = start_phantom.name_id;
|
||||
summary.destName = target_phantom.name_id;
|
||||
summary.source_name_id = start_phantom.name_id;
|
||||
summary.target_name_id = target_phantom.name_id;
|
||||
summary.BuildDurationAndLengthStrings(distance, time);
|
||||
}
|
||||
|
@ -57,18 +57,17 @@ class DescriptionFactory
|
||||
public:
|
||||
struct RouteSummary
|
||||
{
|
||||
std::string lengthString;
|
||||
std::string durationString;
|
||||
unsigned startName;
|
||||
unsigned destName;
|
||||
RouteSummary() : lengthString("0"), durationString("0"), startName(0), destName(0) {}
|
||||
unsigned distance;
|
||||
EdgeWeight duration;
|
||||
unsigned source_name_id;
|
||||
unsigned target_name_id;
|
||||
RouteSummary() : distance(0), duration(0), source_name_id(0), target_name_id(0) {}
|
||||
|
||||
void BuildDurationAndLengthStrings(const double distance, const unsigned time)
|
||||
void BuildDurationAndLengthStrings(const double raw_distance, const unsigned raw_duration)
|
||||
{
|
||||
// compute distance/duration for route summary
|
||||
intToString(round(distance), lengthString);
|
||||
int travel_time = round(time / 10.);
|
||||
intToString(std::max(travel_time, 1), durationString);
|
||||
distance = round(raw_distance);
|
||||
duration = round(raw_duration / 10.);
|
||||
}
|
||||
} summary;
|
||||
|
||||
@ -77,15 +76,12 @@ class DescriptionFactory
|
||||
// I know, declaring this public is considered bad. I'm lazy
|
||||
std::vector<SegmentInformation> path_description;
|
||||
DescriptionFactory();
|
||||
virtual ~DescriptionFactory();
|
||||
double GetBearing(const FixedPointCoordinate &C, const FixedPointCoordinate &B) const;
|
||||
void AppendEncodedPolylineString(std::vector<std::string> &output) const;
|
||||
void AppendUnencodedPolylineString(std::vector<std::string> &output) const;
|
||||
JSON::Value AppendUnencodedPolylineString() const;
|
||||
void AppendSegment(const FixedPointCoordinate &coordinate, const PathData &data);
|
||||
void BuildRouteSummary(const double distance, const unsigned time);
|
||||
void SetStartSegment(const PhantomNode &start_phantom);
|
||||
void SetEndSegment(const PhantomNode &start_phantom);
|
||||
void AppendEncodedPolylineString(const bool return_encoded, std::vector<std::string> &output);
|
||||
JSON::Value AppendEncodedPolylineString(const bool return_encoded);
|
||||
|
||||
template <class DataFacadeT> void Run(const DataFacadeT *facade, const unsigned zoomLevel)
|
||||
{
|
||||
@ -179,14 +175,14 @@ class DescriptionFactory
|
||||
target_phantom.name_id = (path_description.end() - 2)->name_id;
|
||||
}
|
||||
}
|
||||
if (std::numeric_limits<double>::epsilon() > path_description[0].length)
|
||||
if (std::numeric_limits<double>::epsilon() > path_description.front().length)
|
||||
{
|
||||
if (path_description.size() > 2)
|
||||
{
|
||||
path_description.erase(path_description.begin());
|
||||
path_description[0].turn_instruction = TurnInstruction::HeadOn;
|
||||
path_description[0].necessary = true;
|
||||
start_phantom.name_id = path_description[0].name_id;
|
||||
path_description.front().turn_instruction = TurnInstruction::HeadOn;
|
||||
path_description.front().necessary = true;
|
||||
start_phantom.name_id = path_description.front().name_id;
|
||||
}
|
||||
}
|
||||
|
||||
@ -198,8 +194,7 @@ class DescriptionFactory
|
||||
{
|
||||
if (path_description[i].necessary)
|
||||
{
|
||||
double angle =
|
||||
GetBearing(path_description[i].location, path_description[i + 1].location);
|
||||
const double angle = path_description[i+1].location.GetBearing(path_description[i].location);
|
||||
path_description[i].bearing = angle * 10;
|
||||
}
|
||||
}
|
||||
|
@ -35,63 +35,68 @@ template <class DataFacadeT> class GPXDescriptor : public BaseDescriptor<DataFac
|
||||
private:
|
||||
DescriptorConfig config;
|
||||
FixedPointCoordinate current;
|
||||
DataFacadeT * facade;
|
||||
|
||||
std::string tmp;
|
||||
void AddRoutePoint(const FixedPointCoordinate & coordinate, std::vector<char> & output)
|
||||
{
|
||||
const std::string route_point_head = "<rtept lat=\"";
|
||||
const std::string route_point_middle = " lon=\"";
|
||||
const std::string route_point_tail = "\"></rtept>";
|
||||
|
||||
std::string tmp;
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lat, tmp);
|
||||
output.insert(output.end(), route_point_head.begin(), route_point_head.end());
|
||||
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||
output.push_back('\"');
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(coordinate.lon, tmp);
|
||||
output.insert(output.end(), route_point_middle.begin(), route_point_middle.end());
|
||||
output.insert(output.end(), tmp.begin(), tmp.end());
|
||||
output.insert(output.end(), route_point_tail.begin(), route_point_tail.end());
|
||||
}
|
||||
|
||||
public:
|
||||
GPXDescriptor(DataFacadeT *facade) : facade(facade) {}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||
|
||||
// TODO: reorder parameters
|
||||
void Run(const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_node_list,
|
||||
DataFacadeT *facade,
|
||||
http::Reply &reply)
|
||||
{
|
||||
reply.content.emplace_back("<?xml version=\"1.0\" encoding=\"UTF-8\"?>");
|
||||
reply.content.emplace_back("<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||
"\">");
|
||||
reply.content.emplace_back("<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||
"</metadata>");
|
||||
reply.content.emplace_back("<rte>");
|
||||
bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
|
||||
(!raw_route.unpacked_path_segments.front().empty());
|
||||
std::string header("<?xml version=\"1.0\" encoding=\"UTF-8\"?>"
|
||||
"<gpx creator=\"OSRM Routing Engine\" version=\"1.1\" "
|
||||
"xmlns=\"http://www.topografix.com/GPX/1/1\" "
|
||||
"xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" "
|
||||
"xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 gpx.xsd"
|
||||
"\">"
|
||||
"<metadata><copyright author=\"Project OSRM\"><license>Data (c)"
|
||||
" OpenStreetMap contributors (ODbL)</license></copyright>"
|
||||
"</metadata>"
|
||||
"<rte>");
|
||||
reply.content.insert(reply.content.end(), header.begin(), header.end());
|
||||
const bool found_route = (raw_route.shortest_path_length != INVALID_EDGE_WEIGHT) &&
|
||||
(!raw_route.unpacked_path_segments.front().empty());
|
||||
if (found_route)
|
||||
{
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.source_phantom.location.lat, tmp);
|
||||
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.source_phantom.location.lon, tmp);
|
||||
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
|
||||
AddRoutePoint(phantom_node_list.source_phantom.location, reply.content);
|
||||
|
||||
for (const std::vector<PathData> &path_data_vector : raw_route.unpacked_path_segments)
|
||||
{
|
||||
for (const PathData &path_data : path_data_vector)
|
||||
{
|
||||
FixedPointCoordinate current_coordinate =
|
||||
const FixedPointCoordinate current_coordinate =
|
||||
facade->GetCoordinateOfNode(path_data.node);
|
||||
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lat,
|
||||
tmp);
|
||||
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(current_coordinate.lon,
|
||||
tmp);
|
||||
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
|
||||
AddRoutePoint(current_coordinate, reply.content);
|
||||
}
|
||||
}
|
||||
// Add the via point or the end coordinate
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.target_phantom.location.lat, tmp);
|
||||
reply.content.emplace_back("<rtept lat=\"" + tmp + "\" ");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(
|
||||
phantom_node_list.target_phantom.location.lon, tmp);
|
||||
reply.content.emplace_back("lon=\"" + tmp + "\"></rtept>");
|
||||
AddRoutePoint(phantom_node_list.target_phantom.location, reply.content);
|
||||
|
||||
}
|
||||
reply.content.emplace_back("</rte></gpx>");
|
||||
std::string footer("</rte></gpx>");
|
||||
reply.content.insert(reply.content.end(), footer.begin(), footer.end());
|
||||
}
|
||||
};
|
||||
#endif // GPX_DESCRIPTOR_H
|
||||
|
@ -1,524 +1,356 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef JSON_DESCRIPTOR_H_
|
||||
#define JSON_DESCRIPTOR_H_
|
||||
|
||||
#include "BaseDescriptor.h"
|
||||
#include "DescriptionFactory.h"
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/Azimuth.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
// TODO: initalize in c'tor
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory;
|
||||
DescriptionFactory alternate_descriptionFactory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
int name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
||||
int name_id;
|
||||
int length;
|
||||
int position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
||||
|
||||
struct RouteNames
|
||||
{
|
||||
std::string shortest_path_name_1;
|
||||
std::string shortest_path_name_2;
|
||||
std::string alternative_path_name_1;
|
||||
std::string alternative_path_name_2;
|
||||
};
|
||||
|
||||
public:
|
||||
JSONDescriptor() : facade(nullptr), entered_restricted_area_count(0)
|
||||
{
|
||||
shortest_leg_end_indices.emplace_back(0);
|
||||
alternative_leg_end_indices.emplace_back(0);
|
||||
}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
void Run(const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
// TODO: move facade initalization to c'tor
|
||||
DataFacadeT *f,
|
||||
http::Reply &reply)
|
||||
{
|
||||
facade = f;
|
||||
reply.content.emplace_back("{\"status\":");
|
||||
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
reply.content.emplace_back(
|
||||
"207,\"status_message\": \"Cannot find route between points\"}");
|
||||
return;
|
||||
}
|
||||
|
||||
SimpleLogger().Write(logDEBUG) << "distance: " << raw_route.shortest_path_length;
|
||||
|
||||
// check if first segment is non-zero
|
||||
std::string road_name =
|
||||
facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
||||
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(phantom_nodes.source_phantom);
|
||||
reply.content.emplace_back("0,"
|
||||
"\"status_message\": \"Found route between points\",");
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i]);
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
shortest_leg_end_indices.emplace_back(added_segments + shortest_leg_end_indices.back());
|
||||
}
|
||||
description_factory.SetEndSegment(phantom_nodes.target_phantom);
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
reply.content.emplace_back("\"route_geometry\": ");
|
||||
if (config.geometry)
|
||||
{
|
||||
description_factory.AppendEncodedPolylineString(config.encode_geometry, reply.content);
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.content.emplace_back("[]");
|
||||
}
|
||||
|
||||
reply.content.emplace_back(",\"route_instructions\": [");
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(description_factory,
|
||||
reply,
|
||||
raw_route.shortest_path_length,
|
||||
facade,
|
||||
shortest_path_segments);
|
||||
}
|
||||
reply.content.emplace_back("],");
|
||||
description_factory.BuildRouteSummary(description_factory.entireLength,
|
||||
raw_route.shortest_path_length);
|
||||
|
||||
reply.content.emplace_back("\"route_summary\":");
|
||||
reply.content.emplace_back("{");
|
||||
reply.content.emplace_back("\"total_distance\":");
|
||||
reply.content.emplace_back(description_factory.summary.lengthString);
|
||||
reply.content.emplace_back(","
|
||||
"\"total_time\":");
|
||||
reply.content.emplace_back(description_factory.summary.durationString);
|
||||
reply.content.emplace_back(","
|
||||
"\"start_point\":\"");
|
||||
reply.content.emplace_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
||||
reply.content.emplace_back("\","
|
||||
"\"end_point\":\"");
|
||||
reply.content.emplace_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||
reply.content.emplace_back("\"");
|
||||
reply.content.emplace_back("}");
|
||||
reply.content.emplace_back(",");
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (raw_route.alternative_path_length != INVALID_EDGE_WEIGHT)
|
||||
{
|
||||
alternate_descriptionFactory.SetStartSegment(phantom_nodes.source_phantom);
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_descriptionFactory.AppendSegment(current, path_data);
|
||||
}
|
||||
}
|
||||
alternate_descriptionFactory.Run(facade, config.zoom_level);
|
||||
|
||||
// //give an array of alternative routes
|
||||
reply.content.emplace_back("\"alternative_geometries\": [");
|
||||
if (config.geometry && INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
// Generate the linestrings for each alternative
|
||||
alternate_descriptionFactory.AppendEncodedPolylineString(config.encode_geometry,
|
||||
reply.content);
|
||||
}
|
||||
reply.content.emplace_back("],");
|
||||
reply.content.emplace_back("\"alternative_instructions\":[");
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
reply.content.emplace_back("[");
|
||||
// Generate instructions for each alternative
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(alternate_descriptionFactory,
|
||||
reply,
|
||||
raw_route.alternative_path_length,
|
||||
facade,
|
||||
alternative_path_segments);
|
||||
}
|
||||
reply.content.emplace_back("]");
|
||||
}
|
||||
reply.content.emplace_back("],");
|
||||
reply.content.emplace_back("\"alternative_summaries\":[");
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
// Generate route summary (length, duration) for each alternative
|
||||
alternate_descriptionFactory.BuildRouteSummary(
|
||||
alternate_descriptionFactory.entireLength, raw_route.alternative_path_length);
|
||||
reply.content.emplace_back("{");
|
||||
reply.content.emplace_back("\"total_distance\":");
|
||||
reply.content.emplace_back(alternate_descriptionFactory.summary.lengthString);
|
||||
reply.content.emplace_back(","
|
||||
"\"total_time\":");
|
||||
reply.content.emplace_back(alternate_descriptionFactory.summary.durationString);
|
||||
reply.content.emplace_back(","
|
||||
"\"start_point\":\"");
|
||||
reply.content.emplace_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.startName));
|
||||
reply.content.emplace_back("\","
|
||||
"\"end_point\":\"");
|
||||
reply.content.emplace_back(
|
||||
facade->GetEscapedNameForNameID(description_factory.summary.destName));
|
||||
reply.content.emplace_back("\"");
|
||||
reply.content.emplace_back("}");
|
||||
}
|
||||
reply.content.emplace_back("],");
|
||||
|
||||
// //Get Names for both routes
|
||||
RouteNames routeNames;
|
||||
GetRouteNames(shortest_path_segments, alternative_path_segments, facade, routeNames);
|
||||
|
||||
reply.content.emplace_back("\"route_name\":[\"");
|
||||
reply.content.emplace_back(routeNames.shortest_path_name_1);
|
||||
reply.content.emplace_back("\",\"");
|
||||
reply.content.emplace_back(routeNames.shortest_path_name_2);
|
||||
reply.content.emplace_back("\"],"
|
||||
"\"alternative_names\":[");
|
||||
reply.content.emplace_back("[\"");
|
||||
reply.content.emplace_back(routeNames.alternative_path_name_1);
|
||||
reply.content.emplace_back("\",\"");
|
||||
reply.content.emplace_back(routeNames.alternative_path_name_2);
|
||||
reply.content.emplace_back("\"]");
|
||||
reply.content.emplace_back("],");
|
||||
// list all viapoints so that the client may display it
|
||||
reply.content.emplace_back("\"via_points\":[");
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
std::string tmp;
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
raw_route.segment_end_coordinates.front().source_phantom.location, tmp);
|
||||
reply.content.emplace_back("[");
|
||||
reply.content.emplace_back(tmp);
|
||||
reply.content.emplace_back("]");
|
||||
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
tmp.clear();
|
||||
FixedPointCoordinate::convertInternalReversedCoordinateToString(
|
||||
nodes.target_phantom.location, tmp);
|
||||
reply.content.emplace_back(",[");
|
||||
reply.content.emplace_back(tmp);
|
||||
reply.content.emplace_back("]");
|
||||
}
|
||||
|
||||
reply.content.emplace_back("],");
|
||||
reply.content.emplace_back("\"via_indices\":[");
|
||||
for (const unsigned index : shortest_leg_end_indices)
|
||||
{
|
||||
tmp.clear();
|
||||
intToString(index, tmp);
|
||||
reply.content.emplace_back(tmp);
|
||||
if (index != shortest_leg_end_indices.back())
|
||||
{
|
||||
reply.content.emplace_back(",");
|
||||
}
|
||||
}
|
||||
reply.content.emplace_back("],\"alternative_indices\":[");
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
reply.content.emplace_back("0,");
|
||||
tmp.clear();
|
||||
intToString(alternate_descriptionFactory.path_description.size(), tmp);
|
||||
reply.content.emplace_back(tmp);
|
||||
}
|
||||
|
||||
reply.content.emplace_back("],");
|
||||
reply.content.emplace_back("\"hint_data\": {");
|
||||
reply.content.emplace_back("\"checksum\":");
|
||||
intToString(raw_route.check_sum, tmp);
|
||||
reply.content.emplace_back(tmp);
|
||||
reply.content.emplace_back(", \"locations\": [");
|
||||
|
||||
std::string hint;
|
||||
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
||||
{
|
||||
reply.content.emplace_back("\"");
|
||||
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||
reply.content.emplace_back(hint);
|
||||
reply.content.emplace_back("\", ");
|
||||
}
|
||||
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||
reply.content.emplace_back("\"");
|
||||
reply.content.emplace_back(hint);
|
||||
reply.content.emplace_back("\"]");
|
||||
reply.content.emplace_back("}}");
|
||||
}
|
||||
|
||||
// construct routes names
|
||||
void GetRouteNames(std::vector<Segment> &shortest_path_segments,
|
||||
std::vector<Segment> &alternative_path_segments,
|
||||
const DataFacadeT *facade,
|
||||
RouteNames &routeNames)
|
||||
{
|
||||
Segment shortest_segment_1, shortest_segment_2;
|
||||
Segment alternativeSegment1, alternative_segment_2;
|
||||
|
||||
auto length_comperator = [](Segment a, Segment b)
|
||||
{ return a.length < b.length; };
|
||||
auto name_id_comperator = [](Segment a, Segment b)
|
||||
{ return a.name_id < b.name_id; };
|
||||
|
||||
if (!shortest_path_segments.empty())
|
||||
{
|
||||
std::sort(
|
||||
shortest_path_segments.begin(), shortest_path_segments.end(), length_comperator);
|
||||
shortest_segment_1 = shortest_path_segments[0];
|
||||
if (!alternative_path_segments.empty())
|
||||
{
|
||||
std::sort(alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
length_comperator);
|
||||
alternativeSegment1 = alternative_path_segments[0];
|
||||
}
|
||||
std::vector<Segment> shortestDifference(shortest_path_segments.size());
|
||||
std::vector<Segment> alternativeDifference(alternative_path_segments.size());
|
||||
std::set_difference(shortest_path_segments.begin(),
|
||||
shortest_path_segments.end(),
|
||||
alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
shortestDifference.begin(),
|
||||
length_comperator);
|
||||
int size_of_difference = shortestDifference.size();
|
||||
if (size_of_difference)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < size_of_difference &&
|
||||
shortestDifference[i].name_id == shortest_path_segments[0].name_id)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (i < size_of_difference)
|
||||
{
|
||||
shortest_segment_2 = shortestDifference[i];
|
||||
}
|
||||
}
|
||||
|
||||
std::set_difference(alternative_path_segments.begin(),
|
||||
alternative_path_segments.end(),
|
||||
shortest_path_segments.begin(),
|
||||
shortest_path_segments.end(),
|
||||
alternativeDifference.begin(),
|
||||
name_id_comperator);
|
||||
size_of_difference = alternativeDifference.size();
|
||||
if (size_of_difference)
|
||||
{
|
||||
int i = 0;
|
||||
while (i < size_of_difference &&
|
||||
alternativeDifference[i].name_id == alternative_path_segments[0].name_id)
|
||||
{
|
||||
++i;
|
||||
}
|
||||
if (i < size_of_difference)
|
||||
{
|
||||
alternative_segment_2 = alternativeDifference[i];
|
||||
}
|
||||
}
|
||||
if (shortest_segment_1.position > shortest_segment_2.position)
|
||||
std::swap(shortest_segment_1, shortest_segment_2);
|
||||
|
||||
if (alternativeSegment1.position > alternative_segment_2.position)
|
||||
std::swap(alternativeSegment1, alternative_segment_2);
|
||||
|
||||
routeNames.shortest_path_name_1 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_1.name_id);
|
||||
routeNames.shortest_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(shortest_segment_2.name_id);
|
||||
|
||||
routeNames.alternative_path_name_1 =
|
||||
facade->GetEscapedNameForNameID(alternativeSegment1.name_id);
|
||||
routeNames.alternative_path_name_2 =
|
||||
facade->GetEscapedNameForNameID(alternative_segment_2.name_id);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
http::Reply &reply,
|
||||
const int route_length,
|
||||
const DataFacadeT *facade,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
// Example: ["Turn left","High Street",200,4,10,"200m","NE",22.5]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (necessary_segments_running_index)
|
||||
{
|
||||
reply.content.emplace_back(",");
|
||||
}
|
||||
reply.content.emplace_back("[\"");
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
intToString(as_integer(TurnInstruction::EnterRoundAbout), temp_instruction);
|
||||
reply.content.emplace_back(temp_instruction);
|
||||
reply.content.emplace_back("-");
|
||||
intToString(round_about.leave_at_exit + 1, temp_instruction);
|
||||
reply.content.emplace_back(temp_instruction);
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
intToString(as_integer(current_instruction), temp_instruction);
|
||||
reply.content.emplace_back(temp_instruction);
|
||||
}
|
||||
|
||||
reply.content.emplace_back("\",\"");
|
||||
reply.content.emplace_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||
reply.content.emplace_back("\",");
|
||||
intToString(segment.length, temp_dist);
|
||||
reply.content.emplace_back(temp_dist);
|
||||
reply.content.emplace_back(",");
|
||||
intToString(necessary_segments_running_index, temp_length);
|
||||
reply.content.emplace_back(temp_length);
|
||||
reply.content.emplace_back(",");
|
||||
intToString(round(segment.duration / 10.), temp_duration);
|
||||
reply.content.emplace_back(temp_duration);
|
||||
reply.content.emplace_back(",\"");
|
||||
intToString(segment.length, temp_length);
|
||||
reply.content.emplace_back(temp_length);
|
||||
reply.content.emplace_back("m\",\"");
|
||||
int bearing_value = round(segment.bearing / 10.);
|
||||
reply.content.emplace_back(Azimuth::Get(bearing_value));
|
||||
reply.content.emplace_back("\",");
|
||||
intToString(bearing_value, temp_bearing);
|
||||
reply.content.emplace_back(temp_bearing);
|
||||
reply.content.emplace_back("]");
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
Segment(segment.name_id, segment.length, route_segments_list.size()));
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
if (INVALID_EDGE_WEIGHT != route_length)
|
||||
{
|
||||
reply.content.emplace_back(",[\"");
|
||||
intToString(as_integer(TurnInstruction::ReachedYourDestination), temp_instruction);
|
||||
reply.content.emplace_back(temp_instruction);
|
||||
reply.content.emplace_back("\",\"");
|
||||
reply.content.emplace_back("\",");
|
||||
reply.content.emplace_back("0");
|
||||
reply.content.emplace_back(",");
|
||||
intToString(necessary_segments_running_index - 1, temp_length);
|
||||
reply.content.emplace_back(temp_length);
|
||||
reply.content.emplace_back(",");
|
||||
reply.content.emplace_back("0");
|
||||
reply.content.emplace_back(",\"");
|
||||
reply.content.emplace_back("\",\"");
|
||||
reply.content.emplace_back(Azimuth::Get(0.0));
|
||||
reply.content.emplace_back("\",");
|
||||
reply.content.emplace_back("0.0");
|
||||
reply.content.emplace_back("]");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef JSON_DESCRIPTOR_H_
|
||||
#define JSON_DESCRIPTOR_H_
|
||||
|
||||
#include "BaseDescriptor.h"
|
||||
#include "DescriptionFactory.h"
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../Algorithms/ExtractRouteNames.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../DataStructures/SegmentInformation.h"
|
||||
#include "../DataStructures/TurnInstructions.h"
|
||||
#include "../Util/Azimuth.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
template <class DataFacadeT> class JSONDescriptor : public BaseDescriptor<DataFacadeT>
|
||||
{
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
DescriptorConfig config;
|
||||
DescriptionFactory description_factory, alternate_description_factory;
|
||||
FixedPointCoordinate current;
|
||||
unsigned entered_restricted_area_count;
|
||||
struct RoundAbout
|
||||
{
|
||||
RoundAbout() : start_index(INT_MAX), name_id(INT_MAX), leave_at_exit(INT_MAX) {}
|
||||
int start_index;
|
||||
int name_id;
|
||||
int leave_at_exit;
|
||||
} round_about;
|
||||
|
||||
struct Segment
|
||||
{
|
||||
Segment() : name_id(-1), length(-1), position(-1) {}
|
||||
Segment(int n, int l, int p) : name_id(n), length(l), position(p) {}
|
||||
int name_id;
|
||||
int length;
|
||||
int position;
|
||||
};
|
||||
std::vector<Segment> shortest_path_segments, alternative_path_segments;
|
||||
std::vector<unsigned> shortest_leg_end_indices, alternative_leg_end_indices;
|
||||
ExtractRouteNames<DataFacadeT, Segment> GenerateRouteNames;
|
||||
|
||||
|
||||
public:
|
||||
JSONDescriptor(DataFacadeT *facade) : facade(facade), entered_restricted_area_count(0)
|
||||
{
|
||||
shortest_leg_end_indices.emplace_back(0);
|
||||
alternative_leg_end_indices.emplace_back(0);
|
||||
}
|
||||
|
||||
void SetConfig(const DescriptorConfig &c) { config = c; }
|
||||
|
||||
unsigned DescribeLeg(const std::vector<PathData> route_leg, const PhantomNodes &leg_phantoms)
|
||||
{
|
||||
unsigned added_element_count = 0;
|
||||
// Get all the coordinates for the computed route
|
||||
FixedPointCoordinate current_coordinate;
|
||||
for (const PathData &path_data : route_leg)
|
||||
{
|
||||
current_coordinate = facade->GetCoordinateOfNode(path_data.node);
|
||||
description_factory.AppendSegment(current_coordinate, path_data);
|
||||
++added_element_count;
|
||||
}
|
||||
++added_element_count;
|
||||
BOOST_ASSERT((route_leg.size() + 1) == added_element_count);
|
||||
return added_element_count;
|
||||
}
|
||||
|
||||
void Run(const RawRouteData &raw_route,
|
||||
const PhantomNodes &phantom_nodes,
|
||||
http::Reply &reply)
|
||||
{
|
||||
JSON::Object json_result;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
// We do not need to do much, if there is no route ;-)
|
||||
json_result.values["status"] = 207;
|
||||
json_result.values["status_message"] = "Cannot find route between points";
|
||||
JSON::render(reply.content, json_result);
|
||||
return;
|
||||
}
|
||||
|
||||
// check if first segment is non-zero
|
||||
std::string road_name =
|
||||
facade->GetEscapedNameForNameID(phantom_nodes.source_phantom.name_id);
|
||||
|
||||
BOOST_ASSERT(raw_route.unpacked_path_segments.size() ==
|
||||
raw_route.segment_end_coordinates.size());
|
||||
|
||||
description_factory.SetStartSegment(phantom_nodes.source_phantom);
|
||||
json_result.values["status"] = 0;
|
||||
json_result.values["status_message"] = "Found route between points";
|
||||
|
||||
// for each unpacked segment add the leg to the description
|
||||
for (unsigned i = 0; i < raw_route.unpacked_path_segments.size(); ++i)
|
||||
{
|
||||
const int added_segments = DescribeLeg(raw_route.unpacked_path_segments[i],
|
||||
raw_route.segment_end_coordinates[i]);
|
||||
BOOST_ASSERT(0 < added_segments);
|
||||
shortest_leg_end_indices.emplace_back(added_segments + shortest_leg_end_indices.back());
|
||||
}
|
||||
description_factory.SetEndSegment(phantom_nodes.target_phantom);
|
||||
description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value route_geometry = description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
||||
json_result.values["route_geometry"] = route_geometry;
|
||||
}
|
||||
if (config.instructions)
|
||||
{
|
||||
JSON::Array json_route_instructions;
|
||||
BuildTextualDescription(description_factory,
|
||||
json_route_instructions,
|
||||
raw_route.shortest_path_length,
|
||||
shortest_path_segments);
|
||||
json_result.values["route_instructions"] = json_route_instructions;
|
||||
}
|
||||
description_factory.BuildRouteSummary(description_factory.entireLength,
|
||||
raw_route.shortest_path_length);
|
||||
JSON::Object json_route_summary;
|
||||
json_route_summary.values["total_distance"] = description_factory.summary.distance;
|
||||
json_route_summary.values["total_time"] = description_factory.summary.duration;
|
||||
json_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(description_factory.summary.source_name_id);
|
||||
json_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(description_factory.summary.target_name_id);
|
||||
json_result.values["route_summary"] = json_route_summary;
|
||||
|
||||
BOOST_ASSERT(!raw_route.segment_end_coordinates.empty());
|
||||
|
||||
JSON::Array json_via_points_array;
|
||||
JSON::Array json_first_coordinate;
|
||||
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lat/COORDINATE_PRECISION);
|
||||
json_first_coordinate.values.push_back(raw_route.segment_end_coordinates.front().source_phantom.location.lon/COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_first_coordinate);
|
||||
for (const PhantomNodes &nodes : raw_route.segment_end_coordinates)
|
||||
{
|
||||
std::string tmp;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lat/COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(nodes.target_phantom.location.lon/COORDINATE_PRECISION);
|
||||
json_via_points_array.values.push_back(json_coordinate);
|
||||
}
|
||||
json_result.values["via_points"] = json_via_points_array;
|
||||
|
||||
JSON::Array json_via_indices_array;
|
||||
json_via_indices_array.values.insert(json_via_indices_array.values.end(), shortest_leg_end_indices.begin(), shortest_leg_end_indices.end());
|
||||
json_result.values["via_indices"] = json_via_indices_array;
|
||||
|
||||
// only one alternative route is computed at this time, so this is hardcoded
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
json_result.values["found_alternative"] = JSON::True();
|
||||
alternate_description_factory.SetStartSegment(phantom_nodes.source_phantom);
|
||||
// Get all the coordinates for the computed route
|
||||
for (const PathData &path_data : raw_route.unpacked_alternative)
|
||||
{
|
||||
current = facade->GetCoordinateOfNode(path_data.node);
|
||||
alternate_description_factory.AppendSegment(current, path_data);
|
||||
}
|
||||
alternate_description_factory.Run(facade, config.zoom_level);
|
||||
|
||||
if (config.geometry)
|
||||
{
|
||||
JSON::Value alternate_geometry_string = alternate_description_factory.AppendEncodedPolylineString(config.encode_geometry);
|
||||
JSON::Array json_alternate_geometries_array;
|
||||
json_alternate_geometries_array.values.push_back(alternate_geometry_string);
|
||||
json_result.values["alternative_geometries"] = json_alternate_geometries_array;
|
||||
}
|
||||
// Generate instructions for each alternative (simulated here)
|
||||
JSON::Array json_alt_instructions;
|
||||
JSON::Array json_current_alt_instructions;
|
||||
if (config.instructions)
|
||||
{
|
||||
BuildTextualDescription(alternate_description_factory,
|
||||
json_current_alt_instructions,
|
||||
raw_route.alternative_path_length,
|
||||
alternative_path_segments);
|
||||
json_alt_instructions.values.push_back(json_current_alt_instructions);
|
||||
json_result.values["alternative_instructions"] = json_alt_instructions;
|
||||
}
|
||||
alternate_description_factory.BuildRouteSummary(
|
||||
alternate_description_factory.entireLength, raw_route.alternative_path_length);
|
||||
|
||||
JSON::Object json_alternate_route_summary;
|
||||
JSON::Array json_alternate_route_summary_array;
|
||||
json_alternate_route_summary.values["total_distance"] = alternate_description_factory.summary.distance;
|
||||
json_alternate_route_summary.values["total_time"] = alternate_description_factory.summary.duration;
|
||||
json_alternate_route_summary.values["start_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.source_name_id);
|
||||
json_alternate_route_summary.values["end_point"] = facade->GetEscapedNameForNameID(alternate_description_factory.summary.target_name_id);
|
||||
json_alternate_route_summary_array.values.push_back(json_alternate_route_summary);
|
||||
json_result.values["alternative_summaries"] = json_alternate_route_summary_array;
|
||||
|
||||
JSON::Array json_altenative_indices_array;
|
||||
json_altenative_indices_array.values.push_back(0);
|
||||
json_altenative_indices_array.values.push_back(alternate_description_factory.path_description.size());
|
||||
json_result.values["alternative_indices"] = json_altenative_indices_array;
|
||||
} else {
|
||||
json_result.values["found_alternative"] = JSON::False();
|
||||
}
|
||||
|
||||
// Get Names for both routes
|
||||
RouteNames route_names = GenerateRouteNames(shortest_path_segments, alternative_path_segments, facade);
|
||||
JSON::Array json_route_names;
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_1);
|
||||
json_route_names.values.push_back(route_names.shortest_path_name_2);
|
||||
json_result.values["route_name"] = json_route_names;
|
||||
|
||||
if (INVALID_EDGE_WEIGHT != raw_route.alternative_path_length)
|
||||
{
|
||||
JSON::Array json_alternate_names_array;
|
||||
JSON::Array json_alternate_names;
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_1);
|
||||
json_alternate_names.values.push_back(route_names.alternative_path_name_2);
|
||||
json_alternate_names_array.values.push_back(json_alternate_names);
|
||||
json_result.values["alternative_names"] = json_alternate_names_array;
|
||||
}
|
||||
|
||||
JSON::Object json_hint_object;
|
||||
json_hint_object.values["checksum"] = raw_route.check_sum;
|
||||
JSON::Array json_location_hint_array;
|
||||
std::string hint;
|
||||
for (unsigned i = 0; i < raw_route.segment_end_coordinates.size(); ++i)
|
||||
{
|
||||
EncodeObjectToBase64(raw_route.segment_end_coordinates[i].source_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
}
|
||||
EncodeObjectToBase64(raw_route.segment_end_coordinates.back().target_phantom, hint);
|
||||
json_location_hint_array.values.push_back(hint);
|
||||
json_hint_object.values["locations"] = json_location_hint_array;
|
||||
json_result.values["hint_data"] = json_hint_object;
|
||||
|
||||
// render the content to the output array
|
||||
TIMER_START(route_render);
|
||||
JSON::render(reply.content, json_result);
|
||||
TIMER_STOP(route_render);
|
||||
SimpleLogger().Write(logDEBUG) << "rendering took: " << TIMER_MSEC(route_render);
|
||||
}
|
||||
|
||||
// TODO: reorder parameters
|
||||
inline void BuildTextualDescription(DescriptionFactory &description_factory,
|
||||
JSON::Array & json_instruction_array,
|
||||
const int route_length,
|
||||
std::vector<Segment> &route_segments_list)
|
||||
{
|
||||
// Segment information has following format:
|
||||
//["instruction id","streetname",length,position,time,"length","earth_direction",azimuth]
|
||||
unsigned necessary_segments_running_index = 0;
|
||||
round_about.leave_at_exit = 0;
|
||||
round_about.name_id = 0;
|
||||
std::string temp_dist, temp_length, temp_duration, temp_bearing, temp_instruction;
|
||||
|
||||
// Fetch data from Factory and generate a string from it.
|
||||
for (const SegmentInformation &segment : description_factory.path_description)
|
||||
{
|
||||
JSON::Array json_instruction_row;
|
||||
TurnInstruction current_instruction = segment.turn_instruction;
|
||||
entered_restricted_area_count += (current_instruction != segment.turn_instruction);
|
||||
if (TurnInstructionsClass::TurnIsNecessary(current_instruction))
|
||||
{
|
||||
if (TurnInstruction::EnterRoundAbout == current_instruction)
|
||||
{
|
||||
round_about.name_id = segment.name_id;
|
||||
round_about.start_index = necessary_segments_running_index;
|
||||
}
|
||||
else
|
||||
{
|
||||
std::string current_turn_instruction;
|
||||
if (TurnInstruction::LeaveRoundAbout == current_instruction)
|
||||
{
|
||||
temp_instruction = IntToString(as_integer(TurnInstruction::EnterRoundAbout));
|
||||
current_turn_instruction += temp_instruction;
|
||||
current_turn_instruction += "-";
|
||||
temp_instruction = IntToString(round_about.leave_at_exit + 1);
|
||||
current_turn_instruction += temp_instruction;
|
||||
round_about.leave_at_exit = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
temp_instruction = IntToString(as_integer(current_instruction));
|
||||
current_turn_instruction += temp_instruction;
|
||||
}
|
||||
json_instruction_row.values.push_back(current_turn_instruction);
|
||||
|
||||
json_instruction_row.values.push_back(facade->GetEscapedNameForNameID(segment.name_id));
|
||||
json_instruction_row.values.push_back(std::round(segment.length));
|
||||
json_instruction_row.values.push_back(necessary_segments_running_index);
|
||||
json_instruction_row.values.push_back(round(segment.duration / 10));
|
||||
json_instruction_row.values.push_back(IntToString(segment.length)+"m");
|
||||
int bearing_value = round(segment.bearing / 10.);
|
||||
json_instruction_row.values.push_back(Azimuth::Get(bearing_value));
|
||||
json_instruction_row.values.push_back(bearing_value);
|
||||
|
||||
route_segments_list.emplace_back(
|
||||
segment.name_id, segment.length, route_segments_list.size());
|
||||
json_instruction_array.values.push_back(json_instruction_row);
|
||||
}
|
||||
}
|
||||
else if (TurnInstruction::StayOnRoundAbout == current_instruction)
|
||||
{
|
||||
++round_about.leave_at_exit;
|
||||
}
|
||||
if (segment.necessary)
|
||||
{
|
||||
++necessary_segments_running_index;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO: check if this in an invariant
|
||||
if (INVALID_EDGE_WEIGHT != route_length)
|
||||
{
|
||||
JSON::Array json_last_instruction_row;
|
||||
temp_instruction = IntToString(as_integer(TurnInstruction::ReachedYourDestination));
|
||||
json_last_instruction_row.values.push_back(temp_instruction);
|
||||
json_last_instruction_row.values.push_back("");
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back(necessary_segments_running_index - 1);
|
||||
json_last_instruction_row.values.push_back(0);
|
||||
json_last_instruction_row.values.push_back("0m");
|
||||
json_last_instruction_row.values.push_back(Azimuth::Get(0.0));
|
||||
json_last_instruction_row.values.push_back(0.);
|
||||
json_instruction_array.values.push_back(json_last_instruction_row);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* JSON_DESCRIPTOR_H_ */
|
||||
|
@ -217,14 +217,15 @@ void ExtractionContainers::PrepareData(const std::string &output_file_name,
|
||||
restrictions_out_stream.open(restrictions_file_name.c_str(), std::ios::binary);
|
||||
restrictions_out_stream.write((char *)&uuid, sizeof(UUID));
|
||||
restrictions_out_stream.write((char *)&number_of_useable_restrictions, sizeof(unsigned));
|
||||
for (restrictions_iterator = restrictions_list.begin();
|
||||
restrictions_iterator != restrictions_list.end();
|
||||
++restrictions_iterator)
|
||||
// for (restrictions_iterator = restrictions_list.begin();
|
||||
// restrictions_iterator != restrictions_list.end();
|
||||
// ++restrictions_iterator)
|
||||
for(const auto & restriction_container : restrictions_list)
|
||||
{
|
||||
if (std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.fromNode &&
|
||||
std::numeric_limits<unsigned>::max() != restrictions_iterator->restriction.toNode)
|
||||
if (std::numeric_limits<unsigned>::max() != restriction_container.restriction.fromNode &&
|
||||
std::numeric_limits<unsigned>::max() != restriction_container.restriction.toNode)
|
||||
{
|
||||
restrictions_out_stream.write((char *)&(restrictions_iterator->restriction),
|
||||
restrictions_out_stream.write((char *)&(restriction_container.restriction),
|
||||
sizeof(TurnRestriction));
|
||||
}
|
||||
}
|
||||
|
@ -63,102 +63,104 @@ bool ExtractorCallbacks::ProcessRestriction(const InputRestrictionContainer &res
|
||||
/** warning: caller needs to take care of synchronization! */
|
||||
void ExtractorCallbacks::ProcessWay(ExtractionWay &parsed_way)
|
||||
{
|
||||
if ((0 < parsed_way.speed) || (0 < parsed_way.duration))
|
||||
if ((0 >= parsed_way.speed) && (0 >= parsed_way.duration))
|
||||
{ // Only true if the way is specified by the speed profile
|
||||
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||
<< " of size " << parsed_way.path.size();
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (0 < parsed_way.duration)
|
||||
{
|
||||
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||
// segment
|
||||
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||
}
|
||||
if (std::numeric_limits<unsigned>::max() == parsed_way.id)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found bogus way with id: " << parsed_way.id
|
||||
<< " of size " << parsed_way.path.size();
|
||||
return;
|
||||
}
|
||||
|
||||
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||
return;
|
||||
}
|
||||
if (0 < parsed_way.duration)
|
||||
{
|
||||
// TODO: iterate all way segments and set duration corresponding to the length of each
|
||||
// segment
|
||||
parsed_way.speed = parsed_way.duration / (parsed_way.path.size() - 1);
|
||||
}
|
||||
|
||||
// Get the unique identifier for the street name
|
||||
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
||||
if (string_map.end() == string_map_iterator)
|
||||
{
|
||||
parsed_way.nameID = external_memory.name_list.size();
|
||||
external_memory.name_list.push_back(parsed_way.name);
|
||||
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
}
|
||||
else
|
||||
{
|
||||
parsed_way.nameID = string_map_iterator->second;
|
||||
}
|
||||
if (std::numeric_limits<double>::epsilon() >= std::abs(-1. - parsed_way.speed))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "found way with bogus speed, id: " << parsed_way.id;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ExtractionWay::opposite == parsed_way.direction)
|
||||
// Get the unique identifier for the street name
|
||||
const auto &string_map_iterator = string_map.find(parsed_way.name);
|
||||
if (string_map.end() == string_map_iterator)
|
||||
{
|
||||
parsed_way.nameID = external_memory.name_list.size();
|
||||
external_memory.name_list.push_back(parsed_way.name);
|
||||
string_map.insert(std::make_pair(parsed_way.name, parsed_way.nameID));
|
||||
}
|
||||
else
|
||||
{
|
||||
parsed_way.nameID = string_map_iterator->second;
|
||||
}
|
||||
|
||||
if (ExtractionWay::opposite == parsed_way.direction)
|
||||
{
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
parsed_way.direction = ExtractionWay::oneway;
|
||||
}
|
||||
|
||||
const bool split_bidirectional_edge =
|
||||
(parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||
|
||||
for (unsigned n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||
{
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
false,
|
||||
split_bidirectional_edge));
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||
}
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
||||
|
||||
// The following information is needed to identify start and end segments of restrictions
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
WayIDStartAndEndEdge(parsed_way.id,
|
||||
parsed_way.path[0],
|
||||
parsed_way.path[1],
|
||||
parsed_way.path[parsed_way.path.size() - 2],
|
||||
parsed_way.path.back()));
|
||||
|
||||
if (split_bidirectional_edge)
|
||||
{ // Only true if the way should be split
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||
{
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
parsed_way.direction = ExtractionWay::oneway;
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction),
|
||||
split_bidirectional_edge));
|
||||
}
|
||||
|
||||
const bool split_bidirectional_edge =
|
||||
(parsed_way.backward_speed > 0) && (parsed_way.speed != parsed_way.backward_speed);
|
||||
|
||||
for (unsigned n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||
{
|
||||
external_memory.all_edges_list.push_back(InternalExtractorEdge(
|
||||
parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
parsed_way.type,
|
||||
(split_bidirectional_edge ? ExtractionWay::oneway : parsed_way.direction),
|
||||
parsed_way.speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
false,
|
||||
split_bidirectional_edge));
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path[n]);
|
||||
}
|
||||
external_memory.used_node_id_list.push_back(parsed_way.path.back());
|
||||
|
||||
// The following information is needed to identify start and end segments of restrictions
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
WayIDStartAndEndEdge(parsed_way.id,
|
||||
parsed_way.path[0],
|
||||
parsed_way.path[1],
|
||||
parsed_way.path[parsed_way.path.size() - 2],
|
||||
parsed_way.path.back()));
|
||||
|
||||
if (split_bidirectional_edge)
|
||||
{ // Only true if the way should be split
|
||||
std::reverse(parsed_way.path.begin(), parsed_way.path.end());
|
||||
for (std::vector<NodeID>::size_type n = 0; n < parsed_way.path.size() - 1; ++n)
|
||||
{
|
||||
external_memory.all_edges_list.push_back(
|
||||
InternalExtractorEdge(parsed_way.path[n],
|
||||
parsed_way.path[n + 1],
|
||||
parsed_way.type,
|
||||
ExtractionWay::oneway,
|
||||
parsed_way.backward_speed,
|
||||
parsed_way.nameID,
|
||||
parsed_way.roundabout,
|
||||
parsed_way.ignoreInGrid,
|
||||
(0 < parsed_way.duration),
|
||||
parsed_way.isAccessRestricted,
|
||||
(ExtractionWay::oneway == parsed_way.direction),
|
||||
split_bidirectional_edge));
|
||||
}
|
||||
external_memory.way_start_end_id_list.push_back(
|
||||
WayIDStartAndEndEdge(parsed_way.id,
|
||||
parsed_way.path[0],
|
||||
parsed_way.path[1],
|
||||
parsed_way.path[parsed_way.path.size() - 2],
|
||||
parsed_way.path.back()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -28,9 +28,10 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef FIXED_POINT_COORDINATE_H_
|
||||
#define FIXED_POINT_COORDINATE_H_
|
||||
|
||||
#include <functional>
|
||||
#include <iosfwd> //for std::ostream
|
||||
|
||||
constexpr double COORDINATE_PRECISION = 1000000.;
|
||||
constexpr float COORDINATE_PRECISION = 1000000.;
|
||||
|
||||
struct FixedPointCoordinate
|
||||
{
|
||||
@ -50,11 +51,13 @@ struct FixedPointCoordinate
|
||||
static double ApproximateDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2);
|
||||
|
||||
static double ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2);
|
||||
static float ApproximateEuclideanDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2);
|
||||
|
||||
static double
|
||||
ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
static float ApproximateEuclideanDistance(const int lat1, const int lon1, const int lat2, const int lon2);
|
||||
|
||||
static float ApproximateSquaredEuclideanDistance(const FixedPointCoordinate &c1,
|
||||
const FixedPointCoordinate &c2);
|
||||
|
||||
static void convertInternalLatLonToString(const int value, std::string &output);
|
||||
|
||||
@ -64,17 +67,24 @@ struct FixedPointCoordinate
|
||||
static void convertInternalReversedCoordinateToString(const FixedPointCoordinate &coord,
|
||||
std::string &output);
|
||||
|
||||
static double ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &point,
|
||||
const FixedPointCoordinate &segA,
|
||||
const FixedPointCoordinate &segB);
|
||||
|
||||
static double ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
||||
static float ComputePerpendicularDistance(const FixedPointCoordinate &coord_a,
|
||||
const FixedPointCoordinate &coord_b,
|
||||
const FixedPointCoordinate &query_location,
|
||||
FixedPointCoordinate &nearest_location,
|
||||
double &r);
|
||||
float &r);
|
||||
|
||||
static float GetBearing(const FixedPointCoordinate &A, const FixedPointCoordinate &B);
|
||||
|
||||
float GetBearing(const FixedPointCoordinate &other) const;
|
||||
|
||||
void Output(std::ostream &out) const;
|
||||
|
||||
static float DegreeToRadian(const float degree);
|
||||
static float RadianToDegree(const float radian);
|
||||
};
|
||||
|
||||
inline std::ostream &operator<<(std::ostream &o, FixedPointCoordinate const &c)
|
||||
|
@ -58,7 +58,7 @@ class Reply
|
||||
std::vector<Header> headers;
|
||||
std::vector<boost::asio::const_buffer> toBuffers();
|
||||
std::vector<boost::asio::const_buffer> HeaderstoBuffers();
|
||||
std::vector<std::string> content;
|
||||
std::vector<char> content;
|
||||
static Reply StockReply(status_type status);
|
||||
void setSize(const unsigned size);
|
||||
void SetUncompressedSize();
|
||||
|
@ -28,6 +28,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "OSRM_impl.h"
|
||||
#include "OSRM.h"
|
||||
|
||||
#include "../Plugins/DistanceTablePlugin.h"
|
||||
#include "../Plugins/HelloWorldPlugin.h"
|
||||
#include "../Plugins/LocatePlugin.h"
|
||||
#include "../Plugins/NearestPlugin.h"
|
||||
@ -55,6 +56,7 @@ OSRM_impl::OSRM_impl(const ServerPaths &server_paths, const bool use_shared_memo
|
||||
}
|
||||
|
||||
// The following plugins handle all requests.
|
||||
RegisterPlugin(new DistanceTablePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
RegisterPlugin(new HelloWorldPlugin());
|
||||
RegisterPlugin(new LocatePlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
RegisterPlugin(new NearestPlugin<BaseDataFacade<QueryEdge::EdgeData>>(query_data_facade));
|
||||
|
141
Plugins/DistanceTablePlugin.h
Normal file
141
Plugins/DistanceTablePlugin.h
Normal file
@ -0,0 +1,141 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef DISTANCE_TABLE_PLUGIN_H
|
||||
#define DISTANCE_TABLE_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Descriptors/BaseDescriptor.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template <class DataFacadeT> class DistanceTablePlugin : public BasePlugin
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||
|
||||
public:
|
||||
explicit DistanceTablePlugin(DataFacadeT *facade) : descriptor_string("table"), facade(facade)
|
||||
{
|
||||
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||
}
|
||||
|
||||
virtual ~DistanceTablePlugin() {}
|
||||
|
||||
const std::string GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
// check number of parameters
|
||||
if (2 > route_parameters.coordinates.size())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData raw_route;
|
||||
raw_route.check_sum = facade->GetCheckSum();
|
||||
|
||||
if (std::any_of(begin(route_parameters.coordinates),
|
||||
end(route_parameters.coordinates),
|
||||
[&](FixedPointCoordinate coordinate)
|
||||
{ return !coordinate.isValid(); }))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||
{
|
||||
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||
}
|
||||
|
||||
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||
|
||||
unsigned max_locations = std::min((std::size_t)100, raw_route.raw_via_node_coordinates.size());
|
||||
for (unsigned i = 0; i < max_locations; ++i)
|
||||
{
|
||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||
!route_parameters.hints[i].empty())
|
||||
{
|
||||
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||
phantom_node_vector[i],
|
||||
route_parameters.zoom_level);
|
||||
BOOST_ASSERT(phantom_node_vector[i].isValid(facade->GetNumberOfNodes()));
|
||||
}
|
||||
|
||||
TIMER_START(distance_table);
|
||||
std::shared_ptr<std::vector<EdgeWeight>> result_table = search_engine_ptr->distance_table(phantom_node_vector);
|
||||
TIMER_STOP(distance_table);
|
||||
|
||||
if (!result_table)
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
JSON::Object json_object;
|
||||
JSON::Array json_array;
|
||||
const unsigned number_of_locations = phantom_node_vector.size();
|
||||
for(unsigned row = 0; row < number_of_locations; ++row)
|
||||
{
|
||||
JSON::Array json_row;
|
||||
auto row_begin_iterator = result_table->begin() + (row*number_of_locations);
|
||||
auto row_end_iterator = result_table->begin() + ((row+1)*number_of_locations);
|
||||
json_row.values.insert(json_row.values.end(), row_begin_iterator, row_end_iterator);
|
||||
json_array.values.push_back(json_row);
|
||||
}
|
||||
json_object.values["distance_table"] = json_array;
|
||||
JSON::render(reply.content, json_object);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
DataFacadeT *facade;
|
||||
};
|
||||
|
||||
#endif // DISTANCE_TABLE_PLUGIN_H
|
@ -25,10 +25,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef HELLOWORLDPLUGIN_H_
|
||||
#define HELLOWORLDPLUGIN_H_
|
||||
#ifndef HELLO_WORLD_PLUGIN_H
|
||||
#define HELLO_WORLD_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <string>
|
||||
@ -46,70 +47,58 @@ class HelloWorldPlugin : public BasePlugin
|
||||
void HandleRequest(const RouteParameters &routeParameters, http::Reply &reply)
|
||||
{
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.emplace_back("<html><head><title>Hello World Demonstration "
|
||||
"Document</title></head><body><h1>Hello, World!</h1>");
|
||||
reply.content.emplace_back("<pre>");
|
||||
reply.content.emplace_back("zoom level: ");
|
||||
intToString(routeParameters.zoom_level, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\nchecksum: ");
|
||||
intToString(routeParameters.check_sum, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\ninstructions: ");
|
||||
reply.content.emplace_back((routeParameters.print_instructions ? "yes" : "no"));
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\ngeometry: ");
|
||||
reply.content.emplace_back((routeParameters.geometry ? "yes" : "no"));
|
||||
reply.content.emplace_back("\ncompression: ");
|
||||
reply.content.emplace_back((routeParameters.compression ? "yes" : "no"));
|
||||
reply.content.emplace_back("\noutput format: ");
|
||||
reply.content.emplace_back(routeParameters.output_format);
|
||||
reply.content.emplace_back("\njson parameter: ");
|
||||
reply.content.emplace_back(routeParameters.jsonp_parameter);
|
||||
reply.content.emplace_back("\nlanguage: ");
|
||||
reply.content.emplace_back(routeParameters.language);
|
||||
reply.content.emplace_back("\nNumber of locations: ");
|
||||
intToString(routeParameters.coordinates.size(), temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\n");
|
||||
|
||||
JSON::Object json_result;
|
||||
std::string temp_string;
|
||||
json_result.values["title"] = "Hello World";
|
||||
|
||||
temp_string = IntToString(routeParameters.zoom_level);
|
||||
json_result.values["zoom_level"] = temp_string;
|
||||
|
||||
temp_string = IntToString(routeParameters.check_sum);
|
||||
json_result.values["check_sum"] = temp_string;
|
||||
json_result.values["instructions"] = (routeParameters.print_instructions ? "yes" : "no");
|
||||
json_result.values["geometry"] = (routeParameters.geometry ? "yes" : "no");
|
||||
json_result.values["compression"] = (routeParameters.compression ? "yes" : "no");
|
||||
json_result.values["output_format"] = (!routeParameters.output_format.empty() ? "yes" : "no");
|
||||
|
||||
json_result.values["jsonp_parameter"] = (!routeParameters.jsonp_parameter.empty() ? "yes" : "no");
|
||||
json_result.values["language"] = (!routeParameters.language.empty() ? "yes" : "no");
|
||||
|
||||
temp_string = IntToString(routeParameters.coordinates.size());
|
||||
json_result.values["location_count"] = temp_string;
|
||||
|
||||
JSON::Array json_locations;
|
||||
unsigned counter = 0;
|
||||
for (const FixedPointCoordinate &coordinate : routeParameters.coordinates)
|
||||
{
|
||||
reply.content.emplace_back(" [");
|
||||
intToString(counter, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("] ");
|
||||
doubleToString(coordinate.lat / COORDINATE_PRECISION, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back(",");
|
||||
doubleToString(coordinate.lon / COORDINATE_PRECISION, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\n");
|
||||
JSON::Object json_location;
|
||||
JSON::Array json_coordinates;
|
||||
|
||||
json_coordinates.values.push_back(coordinate.lat / COORDINATE_PRECISION);
|
||||
json_coordinates.values.push_back(coordinate.lon / COORDINATE_PRECISION);
|
||||
json_location.values[IntToString(counter)] = json_coordinates;
|
||||
json_locations.values.push_back(json_location);
|
||||
++counter;
|
||||
}
|
||||
json_result.values["locations"] = json_locations;
|
||||
json_result.values["hint_count"] = routeParameters.hints.size();
|
||||
|
||||
reply.content.emplace_back("Number of hints: ");
|
||||
intToString(routeParameters.hints.size(), temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("\n");
|
||||
|
||||
JSON::Array json_hints;
|
||||
counter = 0;
|
||||
for (const std::string ¤t_string : routeParameters.hints)
|
||||
for (const std::string ¤t_hint : routeParameters.hints)
|
||||
{
|
||||
reply.content.emplace_back(" [");
|
||||
intToString(counter, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
reply.content.emplace_back("] ");
|
||||
reply.content.emplace_back(current_string);
|
||||
reply.content.emplace_back("\n");
|
||||
// JSON::String json_hint_string = current_hint;
|
||||
json_hints.values.push_back(current_hint);
|
||||
++counter;
|
||||
}
|
||||
reply.content.emplace_back("</pre></body></html>");
|
||||
json_result.values["hints"] = json_hints;
|
||||
|
||||
JSON::render(reply.content, json_result);
|
||||
}
|
||||
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
};
|
||||
|
||||
#endif /* HELLOWORLDPLUGIN_H_ */
|
||||
#endif // HELLO_WORLD_PLUGIN_H
|
||||
|
@ -29,10 +29,12 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define LOCATE_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
// locates the nearest node in the road network for a given coordinate.
|
||||
#include <string>
|
||||
|
||||
// locates the nearest node in the road network for a given coordinate.
|
||||
template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
||||
{
|
||||
public:
|
||||
@ -42,70 +44,31 @@ template <class DataFacadeT> class LocatePlugin : public BasePlugin
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
// check number of parameters
|
||||
if (route_parameters.coordinates.empty() || !route_parameters.coordinates.front().isValid())
|
||||
if (route_parameters.coordinates.empty() ||
|
||||
!route_parameters.coordinates.front().isValid())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
// query to helpdesk
|
||||
JSON::Object json_result;
|
||||
FixedPointCoordinate result;
|
||||
std::string tmp;
|
||||
// json
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(route_parameters.jsonp_parameter);
|
||||
reply.content.emplace_back("(");
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.emplace_back("{");
|
||||
if (!facade->LocateClosestEndPointForCoordinate(route_parameters.coordinates.front(),
|
||||
result))
|
||||
{
|
||||
reply.content.emplace_back("\"status\":207,");
|
||||
reply.content.emplace_back("\"mapped_coordinate\":[]");
|
||||
json_result.values["status"] = 207;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Write coordinate to stream
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.emplace_back("\"status\":0,");
|
||||
reply.content.emplace_back("\"mapped_coordinate\":");
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lat, tmp);
|
||||
reply.content.emplace_back("[");
|
||||
reply.content.emplace_back(tmp);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.lon, tmp);
|
||||
reply.content.emplace_back(",");
|
||||
reply.content.emplace_back(tmp);
|
||||
reply.content.emplace_back("]");
|
||||
json_result.values["status"] = 0;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(result.lat/COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(result.lon/COORDINATE_PRECISION);
|
||||
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||
}
|
||||
reply.content.emplace_back("}");
|
||||
reply.headers.resize(3);
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
unsigned content_length = 0;
|
||||
for (const std::string &snippet : reply.content)
|
||||
{
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
return;
|
||||
|
||||
JSON::render(reply.content, json_result);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -29,10 +29,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#define NEAREST_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../DataStructures/PhantomNodes.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
|
||||
/*
|
||||
* This Plugin locates the nearest point on a street in the road network for a given coordinate.
|
||||
@ -43,8 +44,6 @@ template <class DataFacadeT> class NearestPlugin : public BasePlugin
|
||||
public:
|
||||
explicit NearestPlugin(DataFacadeT *facade) : facade(facade), descriptor_string("nearest")
|
||||
{
|
||||
descriptor_table.emplace("", 0); // default descriptor
|
||||
descriptor_table.emplace("json", 1);
|
||||
}
|
||||
|
||||
const std::string GetDescriptor() const { return descriptor_string; }
|
||||
@ -52,86 +51,40 @@ template <class DataFacadeT> class NearestPlugin : public BasePlugin
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
// check number of parameters
|
||||
if (route_parameters.coordinates.empty())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
if (!route_parameters.coordinates.front().isValid())
|
||||
if (route_parameters.coordinates.empty() ||
|
||||
!route_parameters.coordinates.front().isValid())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
PhantomNode result;
|
||||
PhantomNode phantom_node;
|
||||
facade->FindPhantomNodeForCoordinate(
|
||||
route_parameters.coordinates.front(), result, route_parameters.zoom_level);
|
||||
route_parameters.coordinates.front(), phantom_node, route_parameters.zoom_level);
|
||||
|
||||
// json
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
JSON::Object json_result;
|
||||
if (!phantom_node.isValid())
|
||||
{
|
||||
reply.content.emplace_back(route_parameters.jsonp_parameter);
|
||||
reply.content.emplace_back("(");
|
||||
}
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.emplace_back("{\"status\":");
|
||||
if (SPECIAL_NODEID != result.forward_node_id)
|
||||
{
|
||||
reply.content.emplace_back("0,");
|
||||
json_result.values["status"] = 207;
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.content.emplace_back("207,");
|
||||
reply.status = http::Reply::ok;
|
||||
json_result.values["status"] = 0;
|
||||
JSON::Array json_coordinate;
|
||||
json_coordinate.values.push_back(phantom_node.location.lat/COORDINATE_PRECISION);
|
||||
json_coordinate.values.push_back(phantom_node.location.lon/COORDINATE_PRECISION);
|
||||
json_result.values["mapped_coordinate"] = json_coordinate;
|
||||
std::string temp_string;
|
||||
facade->GetName(phantom_node.name_id, temp_string);
|
||||
json_result.values["name"] = temp_string;
|
||||
}
|
||||
reply.content.emplace_back("\"mapped_coordinate\":[");
|
||||
std::string temp_string;
|
||||
|
||||
if (SPECIAL_NODEID != result.forward_node_id)
|
||||
{
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lat, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
FixedPointCoordinate::convertInternalLatLonToString(result.location.lon, temp_string);
|
||||
reply.content.emplace_back(",");
|
||||
reply.content.emplace_back(temp_string);
|
||||
}
|
||||
reply.content.emplace_back("],\"name\":\"");
|
||||
if (SPECIAL_NODEID != result.forward_node_id)
|
||||
{
|
||||
facade->GetName(result.name_id, temp_string);
|
||||
reply.content.emplace_back(temp_string);
|
||||
}
|
||||
reply.content.emplace_back("\"}");
|
||||
reply.headers.resize(3);
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"location.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"location.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
unsigned content_length = 0;
|
||||
for (const std::string &snippet : reply.content)
|
||||
{
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, temp_string);
|
||||
reply.headers[0].value = temp_string;
|
||||
JSON::render(reply.content, json_result);
|
||||
}
|
||||
|
||||
private:
|
||||
DataFacadeT *facade;
|
||||
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||
std::string descriptor_string;
|
||||
};
|
||||
|
||||
|
@ -28,8 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef TIMESTAMP_PLUGIN_H
|
||||
#define TIMESTAMP_PLUGIN_H
|
||||
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
template <class DataFacadeT> class TimestampPlugin : public BasePlugin
|
||||
{
|
||||
public:
|
||||
@ -40,46 +43,12 @@ template <class DataFacadeT> class TimestampPlugin : public BasePlugin
|
||||
const std::string GetDescriptor() const { return descriptor_string; }
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
std::string tmp;
|
||||
|
||||
// json
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(route_parameters.jsonp_parameter);
|
||||
reply.content.emplace_back("(");
|
||||
}
|
||||
|
||||
reply.status = http::Reply::ok;
|
||||
reply.content.emplace_back("{");
|
||||
reply.content.emplace_back("\"status\":");
|
||||
reply.content.emplace_back("0,");
|
||||
reply.content.emplace_back("\"timestamp\":\"");
|
||||
reply.content.emplace_back(facade->GetTimestamp());
|
||||
reply.content.emplace_back("\"");
|
||||
reply.content.emplace_back("}");
|
||||
reply.headers.resize(3);
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(")");
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"timestamp.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"timestamp.json\"";
|
||||
}
|
||||
unsigned content_length = 0;
|
||||
for (const std::string &snippet : reply.content)
|
||||
{
|
||||
content_length += snippet.length();
|
||||
}
|
||||
intToString(content_length, tmp);
|
||||
reply.headers[0].value = tmp;
|
||||
JSON::Object json_result;
|
||||
json_result.values["status"] = 0;
|
||||
const std::string timestamp = facade->GetTimestamp();
|
||||
json_result.values["timestamp"] = timestamp;
|
||||
JSON::render(reply.content, json_result);
|
||||
}
|
||||
|
||||
private:
|
||||
|
@ -1,241 +1,182 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef VIAROUTEPLUGIN_H_
|
||||
#define VIAROUTEPLUGIN_H_
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Descriptors/BaseDescriptor.h"
|
||||
#include "../Descriptors/GPXDescriptor.h"
|
||||
#include "../Descriptors/JSONDescriptor.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
||||
{
|
||||
private:
|
||||
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||
|
||||
public:
|
||||
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||
{
|
||||
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||
|
||||
descriptor_table.emplace("json", 0);
|
||||
descriptor_table.emplace("gpx", 1);
|
||||
}
|
||||
|
||||
virtual ~ViaRoutePlugin() {}
|
||||
|
||||
const std::string GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
// check number of parameters
|
||||
if (2 > route_parameters.coordinates.size())
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData raw_route;
|
||||
raw_route.check_sum = facade->GetCheckSum();
|
||||
|
||||
if (std::any_of(begin(route_parameters.coordinates),
|
||||
end(route_parameters.coordinates),
|
||||
[&](FixedPointCoordinate coordinate)
|
||||
{ return !coordinate.isValid(); }))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||
{
|
||||
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||
}
|
||||
|
||||
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||
|
||||
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
|
||||
{
|
||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||
!route_parameters.hints[i].empty())
|
||||
{
|
||||
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||
phantom_node_vector[i],
|
||||
route_parameters.zoom_level);
|
||||
}
|
||||
|
||||
PhantomNodes current_phantom_node_pair;
|
||||
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
|
||||
{
|
||||
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
|
||||
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
|
||||
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
|
||||
}
|
||||
|
||||
if ((route_parameters.alternate_route) && (1 == raw_route.segment_end_coordinates.size()))
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||
raw_route);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
|
||||
}
|
||||
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(route_parameters.jsonp_parameter);
|
||||
reply.content.emplace_back("(");
|
||||
}
|
||||
|
||||
DescriptorConfig descriptor_config;
|
||||
|
||||
auto iter = descriptor_table.find(route_parameters.output_format);
|
||||
unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
|
||||
|
||||
descriptor_config.zoom_level = route_parameters.zoom_level;
|
||||
descriptor_config.instructions = route_parameters.print_instructions;
|
||||
descriptor_config.geometry = route_parameters.geometry;
|
||||
descriptor_config.encode_geometry = route_parameters.compression;
|
||||
|
||||
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||
switch (descriptor_type)
|
||||
{
|
||||
// case 0:
|
||||
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
|
||||
// break;
|
||||
case 1:
|
||||
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>();
|
||||
break;
|
||||
default:
|
||||
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
|
||||
break;
|
||||
}
|
||||
|
||||
PhantomNodes phantom_nodes;
|
||||
phantom_nodes.source_phantom = raw_route.segment_end_coordinates.front().source_phantom;
|
||||
phantom_nodes.target_phantom = raw_route.segment_end_coordinates.back().target_phantom;
|
||||
descriptor->SetConfig(descriptor_config);
|
||||
descriptor->Run(raw_route, phantom_nodes, facade, reply);
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.emplace_back(")\n");
|
||||
}
|
||||
reply.headers.resize(3);
|
||||
reply.headers[0].name = "Content-Length";
|
||||
|
||||
unsigned content_length = 0;
|
||||
for (const std::string &snippet : reply.content)
|
||||
{
|
||||
content_length += snippet.length();
|
||||
}
|
||||
std::string tmp_string;
|
||||
intToString(content_length, tmp_string);
|
||||
reply.headers[0].value = tmp_string;
|
||||
|
||||
switch (descriptor_type)
|
||||
{
|
||||
case 0:
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||
}
|
||||
|
||||
break;
|
||||
case 1:
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
|
||||
|
||||
break;
|
||||
default:
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.json\"";
|
||||
}
|
||||
break;
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
DataFacadeT *facade;
|
||||
};
|
||||
|
||||
#endif /* VIAROUTEPLUGIN_H_ */
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef VIA_ROUTE_PLUGIN_H
|
||||
#define VIA_ROUTE_PLUGIN_H
|
||||
|
||||
#include "BasePlugin.h"
|
||||
|
||||
#include "../Algorithms/ObjectToBase64.h"
|
||||
|
||||
#include "../DataStructures/QueryEdge.h"
|
||||
#include "../DataStructures/SearchEngine.h"
|
||||
#include "../Descriptors/BaseDescriptor.h"
|
||||
#include "../Descriptors/GPXDescriptor.h"
|
||||
#include "../Descriptors/JSONDescriptor.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
#include "../Util/TimingUtil.h"
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#include <algorithm>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
template <class DataFacadeT> class ViaRoutePlugin : public BasePlugin
|
||||
{
|
||||
private:
|
||||
std::unordered_map<std::string, unsigned> descriptor_table;
|
||||
std::shared_ptr<SearchEngine<DataFacadeT>> search_engine_ptr;
|
||||
|
||||
public:
|
||||
explicit ViaRoutePlugin(DataFacadeT *facade) : descriptor_string("viaroute"), facade(facade)
|
||||
{
|
||||
search_engine_ptr = std::make_shared<SearchEngine<DataFacadeT>>(facade);
|
||||
|
||||
descriptor_table.emplace("json", 0);
|
||||
descriptor_table.emplace("gpx", 1);
|
||||
// descriptor_table.emplace("geojson", 2);
|
||||
}
|
||||
|
||||
virtual ~ViaRoutePlugin() {}
|
||||
|
||||
const std::string GetDescriptor() const { return descriptor_string; }
|
||||
|
||||
void HandleRequest(const RouteParameters &route_parameters, http::Reply &reply)
|
||||
{
|
||||
// check number of parameters
|
||||
if (2 > route_parameters.coordinates.size() ||
|
||||
std::any_of(begin(route_parameters.coordinates),
|
||||
end(route_parameters.coordinates),
|
||||
[&](FixedPointCoordinate coordinate)
|
||||
{ return !coordinate.isValid(); }))
|
||||
{
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
return;
|
||||
}
|
||||
|
||||
RawRouteData raw_route;
|
||||
raw_route.check_sum = facade->GetCheckSum();
|
||||
for (const FixedPointCoordinate &coordinate : route_parameters.coordinates)
|
||||
{
|
||||
raw_route.raw_via_node_coordinates.emplace_back(coordinate);
|
||||
}
|
||||
|
||||
std::vector<PhantomNode> phantom_node_vector(raw_route.raw_via_node_coordinates.size());
|
||||
const bool checksum_OK = (route_parameters.check_sum == raw_route.check_sum);
|
||||
|
||||
for (unsigned i = 0; i < raw_route.raw_via_node_coordinates.size(); ++i)
|
||||
{
|
||||
if (checksum_OK && i < route_parameters.hints.size() &&
|
||||
!route_parameters.hints[i].empty())
|
||||
{
|
||||
DecodeObjectFromBase64(route_parameters.hints[i], phantom_node_vector[i]);
|
||||
if (phantom_node_vector[i].isValid(facade->GetNumberOfNodes()))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
facade->FindPhantomNodeForCoordinate(raw_route.raw_via_node_coordinates[i],
|
||||
phantom_node_vector[i],
|
||||
route_parameters.zoom_level);
|
||||
}
|
||||
|
||||
PhantomNodes current_phantom_node_pair;
|
||||
for (unsigned i = 0; i < phantom_node_vector.size() - 1; ++i)
|
||||
{
|
||||
current_phantom_node_pair.source_phantom = phantom_node_vector[i];
|
||||
current_phantom_node_pair.target_phantom = phantom_node_vector[i + 1];
|
||||
raw_route.segment_end_coordinates.emplace_back(current_phantom_node_pair);
|
||||
}
|
||||
|
||||
const bool is_alternate_requested = route_parameters.alternate_route;
|
||||
const bool is_only_one_segment = (1 == raw_route.segment_end_coordinates.size());
|
||||
TIMER_START(routing);
|
||||
if (is_alternate_requested && is_only_one_segment)
|
||||
{
|
||||
search_engine_ptr->alternative_path(raw_route.segment_end_coordinates.front(),
|
||||
raw_route);
|
||||
}
|
||||
else
|
||||
{
|
||||
search_engine_ptr->shortest_path(raw_route.segment_end_coordinates, raw_route);
|
||||
}
|
||||
TIMER_STOP(routing);
|
||||
SimpleLogger().Write() << "routing took " << TIMER_MSEC(routing) << "ms";
|
||||
|
||||
if (INVALID_EDGE_WEIGHT == raw_route.shortest_path_length)
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << "Error occurred, single path not found";
|
||||
}
|
||||
reply.status = http::Reply::ok;
|
||||
|
||||
DescriptorConfig descriptor_config;
|
||||
|
||||
auto iter = descriptor_table.find(route_parameters.output_format);
|
||||
unsigned descriptor_type = (iter != descriptor_table.end() ? iter->second : 0);
|
||||
|
||||
descriptor_config.zoom_level = route_parameters.zoom_level;
|
||||
descriptor_config.instructions = route_parameters.print_instructions;
|
||||
descriptor_config.geometry = route_parameters.geometry;
|
||||
descriptor_config.encode_geometry = route_parameters.compression;
|
||||
|
||||
std::shared_ptr<BaseDescriptor<DataFacadeT>> descriptor;
|
||||
switch (descriptor_type)
|
||||
{
|
||||
// case 0:
|
||||
// descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>();
|
||||
// break;
|
||||
case 1:
|
||||
descriptor = std::make_shared<GPXDescriptor<DataFacadeT>>(facade);
|
||||
break;
|
||||
// case 2:
|
||||
// descriptor = std::make_shared<GEOJSONDescriptor<DataFacadeT>>();
|
||||
// break;
|
||||
default:
|
||||
descriptor = std::make_shared<JSONDescriptor<DataFacadeT>>(facade);
|
||||
break;
|
||||
}
|
||||
|
||||
PhantomNodes phantom_nodes;
|
||||
phantom_nodes.source_phantom = raw_route.segment_end_coordinates.front().source_phantom;
|
||||
phantom_nodes.target_phantom = raw_route.segment_end_coordinates.back().target_phantom;
|
||||
descriptor->SetConfig(descriptor_config);
|
||||
TIMER_START(descriptor);
|
||||
descriptor->Run(raw_route, phantom_nodes, reply);
|
||||
TIMER_STOP(descriptor);
|
||||
SimpleLogger().Write() << "descriptor took " << TIMER_MSEC(descriptor) << "ms";
|
||||
}
|
||||
|
||||
private:
|
||||
std::string descriptor_string;
|
||||
DataFacadeT *facade;
|
||||
};
|
||||
|
||||
#endif // VIA_ROUTE_PLUGIN_H
|
||||
|
@ -78,6 +78,7 @@ template <class DataFacadeT> class AlternativeRouting : private BasicRoutingInte
|
||||
{
|
||||
if (phantom_node_pair.PhantomNodesHaveEqualLocation())
|
||||
{
|
||||
BOOST_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
|
246
RoutingAlgorithms/ManyToManyRouting.h
Normal file
246
RoutingAlgorithms/ManyToManyRouting.h
Normal file
@ -0,0 +1,246 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef MANY_TO_MANY_ROUTING_H
|
||||
#define MANY_TO_MANY_ROUTING_H
|
||||
|
||||
#include "BasicRoutingInterface.h"
|
||||
#include "../DataStructures/SearchEngineData.h"
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
|
||||
#include <limits>
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
template <class DataFacadeT> class ManyToManyRouting : public BasicRoutingInterface<DataFacadeT>
|
||||
{
|
||||
typedef BasicRoutingInterface<DataFacadeT> super;
|
||||
typedef SearchEngineData::QueryHeap QueryHeap;
|
||||
SearchEngineData &engine_working_data;
|
||||
|
||||
struct NodeBucket
|
||||
{
|
||||
unsigned target_id; // essentially a row in the distance matrix
|
||||
EdgeWeight distance;
|
||||
NodeBucket(const unsigned target_id, const EdgeWeight distance)
|
||||
: target_id(target_id), distance(distance)
|
||||
{
|
||||
}
|
||||
};
|
||||
typedef std::unordered_map<NodeID, std::vector<NodeBucket>> SearchSpaceWithBuckets;
|
||||
|
||||
public:
|
||||
ManyToManyRouting(DataFacadeT *facade, SearchEngineData &engine_working_data)
|
||||
: super(facade), engine_working_data(engine_working_data)
|
||||
{
|
||||
}
|
||||
|
||||
~ManyToManyRouting() {}
|
||||
|
||||
std::shared_ptr<std::vector<EdgeWeight>>
|
||||
operator()(const std::vector<PhantomNode> &phantom_nodes_vector) const
|
||||
{
|
||||
const unsigned number_of_locations = phantom_nodes_vector.size();
|
||||
std::shared_ptr<std::vector<EdgeWeight>> result_table = std::make_shared<std::vector<EdgeWeight>>(
|
||||
number_of_locations * number_of_locations, std::numeric_limits<EdgeWeight>::max());
|
||||
|
||||
engine_working_data.InitializeOrClearFirstThreadLocalStorage(
|
||||
super::facade->GetNumberOfNodes());
|
||||
|
||||
QueryHeap &query_heap = *(engine_working_data.forwardHeap);
|
||||
|
||||
SearchSpaceWithBuckets search_space_with_buckets;
|
||||
|
||||
unsigned target_id = 0;
|
||||
for (const PhantomNode &phantom_node : phantom_nodes_vector)
|
||||
{
|
||||
query_heap.Clear();
|
||||
// insert target(s) at distance 0
|
||||
if (SPECIAL_NODEID != phantom_node.forward_node_id)
|
||||
{
|
||||
query_heap.Insert(phantom_node.forward_node_id, phantom_node.GetForwardWeightPlusOffset(), phantom_node.forward_node_id);
|
||||
}
|
||||
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
|
||||
{
|
||||
query_heap.Insert(phantom_node.reverse_node_id, phantom_node.GetReverseWeightPlusOffset(), phantom_node.reverse_node_id);
|
||||
}
|
||||
|
||||
// explore search space
|
||||
while (!query_heap.Empty())
|
||||
{
|
||||
BackwardRoutingStep(target_id, query_heap, search_space_with_buckets);
|
||||
}
|
||||
++target_id;
|
||||
}
|
||||
|
||||
// for each source do forward search
|
||||
unsigned source_id = 0;
|
||||
for (const PhantomNode &phantom_node : phantom_nodes_vector)
|
||||
{
|
||||
query_heap.Clear();
|
||||
// insert sources at distance 0
|
||||
if (SPECIAL_NODEID != phantom_node.forward_node_id)
|
||||
{
|
||||
query_heap.Insert(phantom_node.forward_node_id, -phantom_node.GetForwardWeightPlusOffset(), phantom_node.forward_node_id);
|
||||
}
|
||||
if (SPECIAL_NODEID != phantom_node.reverse_node_id)
|
||||
{
|
||||
query_heap.Insert(phantom_node.reverse_node_id, -phantom_node.GetReverseWeightPlusOffset(), phantom_node.reverse_node_id);
|
||||
}
|
||||
|
||||
// explore search space
|
||||
while (!query_heap.Empty())
|
||||
{
|
||||
ForwardRoutingStep(source_id,
|
||||
number_of_locations,
|
||||
query_heap,
|
||||
search_space_with_buckets,
|
||||
result_table);
|
||||
}
|
||||
|
||||
++source_id;
|
||||
}
|
||||
BOOST_ASSERT(source_id == target_id);
|
||||
return result_table;
|
||||
}
|
||||
|
||||
void ForwardRoutingStep(const unsigned source_id,
|
||||
const unsigned number_of_locations,
|
||||
QueryHeap &query_heap,
|
||||
const SearchSpaceWithBuckets &search_space_with_buckets,
|
||||
std::shared_ptr<std::vector<EdgeWeight>> result_table) const
|
||||
{
|
||||
const NodeID node = query_heap.DeleteMin();
|
||||
const int source_distance = query_heap.GetKey(node);
|
||||
|
||||
// check if each encountered node has an entry
|
||||
const auto bucket_iterator = search_space_with_buckets.find(node);
|
||||
// iterate bucket if there exists one
|
||||
if (bucket_iterator != search_space_with_buckets.end())
|
||||
{
|
||||
const std::vector<NodeBucket> &bucket_list = bucket_iterator->second;
|
||||
for (const NodeBucket ¤t_bucket : bucket_list)
|
||||
{
|
||||
// get target id from bucket entry
|
||||
const unsigned target_id = current_bucket.target_id;
|
||||
const unsigned target_distance = current_bucket.distance;
|
||||
const EdgeWeight current_distance =
|
||||
(*result_table)[source_id * number_of_locations + target_id];
|
||||
// check if new distance is better
|
||||
if ((source_distance + target_distance) < current_distance)
|
||||
{
|
||||
(*result_table)[source_id * number_of_locations + target_id] =
|
||||
(source_distance + target_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (StallAtNode<true>(node, source_distance, query_heap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
RelaxOutgoingEdges<true>(node, source_distance, query_heap);
|
||||
}
|
||||
|
||||
void BackwardRoutingStep(const unsigned target_id,
|
||||
QueryHeap &query_heap,
|
||||
SearchSpaceWithBuckets &search_space_with_buckets) const
|
||||
{
|
||||
const NodeID node = query_heap.DeleteMin();
|
||||
const int target_distance = query_heap.GetKey(node);
|
||||
|
||||
// store settled nodes in search space bucket
|
||||
search_space_with_buckets[node].emplace_back(target_id, target_distance);
|
||||
|
||||
if (StallAtNode<false>(node, target_distance, query_heap))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RelaxOutgoingEdges<false>(node, target_distance, query_heap);
|
||||
}
|
||||
|
||||
template <bool forward_direction>
|
||||
inline void
|
||||
RelaxOutgoingEdges(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
|
||||
{
|
||||
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto &data = super::facade->GetEdgeData(edge);
|
||||
const bool direction_flag = (forward_direction ? data.forward : data.backward);
|
||||
if (direction_flag)
|
||||
{
|
||||
const NodeID to = super::facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
|
||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||
const int to_distance = distance + edge_weight;
|
||||
|
||||
// New Node discovered -> Add to Heap + Node Info Storage
|
||||
if (!query_heap.WasInserted(to))
|
||||
{
|
||||
query_heap.Insert(to, to_distance, node);
|
||||
}
|
||||
// Found a shorter Path -> Update distance
|
||||
else if (to_distance < query_heap.GetKey(to))
|
||||
{
|
||||
// new parent
|
||||
query_heap.GetData(to).parent = node;
|
||||
query_heap.DecreaseKey(to, to_distance);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Stalling
|
||||
template <bool forward_direction>
|
||||
inline bool StallAtNode(const NodeID node, const EdgeWeight distance, QueryHeap &query_heap) const
|
||||
{
|
||||
for (auto edge : super::facade->GetAdjacentEdgeRange(node))
|
||||
{
|
||||
const auto &data = super::facade->GetEdgeData(edge);
|
||||
const bool reverse_flag = ((!forward_direction) ? data.forward : data.backward);
|
||||
if (reverse_flag)
|
||||
{
|
||||
const NodeID to = super::facade->GetTarget(edge);
|
||||
const int edge_weight = data.distance;
|
||||
BOOST_ASSERT_MSG(edge_weight > 0, "edge_weight invalid");
|
||||
if (query_heap.WasInserted(to))
|
||||
{
|
||||
if (query_heap.GetKey(to) + edge_weight < distance)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
@ -51,13 +51,15 @@ template <class DataFacadeT> class ShortestPathRouting : public BasicRoutingInte
|
||||
void operator()(const std::vector<PhantomNodes> &phantom_nodes_vector,
|
||||
RawRouteData &raw_route_data) const
|
||||
{
|
||||
for (const PhantomNodes &phantom_node_pair : phantom_nodes_vector)
|
||||
if(std::any_of(begin(phantom_nodes_vector),
|
||||
end(phantom_nodes_vector),
|
||||
[](PhantomNodes phantom_node_pair)
|
||||
{ return phantom_node_pair.AtLeastOnePhantomNodeIsInvalid(); }))
|
||||
{
|
||||
if (phantom_node_pair.AtLeastOnePhantomNodeIsInvalid())
|
||||
{
|
||||
return;
|
||||
}
|
||||
BOOST_ASSERT(false);
|
||||
return;
|
||||
}
|
||||
|
||||
int distance1 = 0;
|
||||
int distance2 = 0;
|
||||
bool search_from_1st_node = true;
|
||||
|
@ -45,7 +45,7 @@ struct APIGrammar : qi::grammar<Iterator>
|
||||
zoom = (-qi::lit('&')) >> qi::lit('z') >> '=' >> qi::short_[boost::bind(&HandlerT::setZoomLevel, handler, ::_1)];
|
||||
output = (-qi::lit('&')) >> qi::lit("output") >> '=' >> string[boost::bind(&HandlerT::setOutputFormat, handler, ::_1)];
|
||||
jsonp = (-qi::lit('&')) >> qi::lit("jsonp") >> '=' >> stringwithPercent[boost::bind(&HandlerT::setJSONpParameter, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::int_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
checksum = (-qi::lit('&')) >> qi::lit("checksum") >> '=' >> qi::uint_[boost::bind(&HandlerT::setChecksum, handler, ::_1)];
|
||||
instruction = (-qi::lit('&')) >> qi::lit("instructions") >> '=' >> qi::bool_[boost::bind(&HandlerT::setInstructionFlag, handler, ::_1)];
|
||||
geometry = (-qi::lit('&')) >> qi::lit("geometry") >> '=' >> qi::bool_[boost::bind(&HandlerT::setGeometryFlag, handler, ::_1)];
|
||||
cmp = (-qi::lit('&')) >> qi::lit("compression") >> '=' >> qi::bool_[boost::bind(&HandlerT::setCompressionFlag, handler, ::_1)];
|
||||
|
@ -81,6 +81,7 @@ void Connection::handle_read(const boost::system::error_code &e, std::size_t byt
|
||||
Header compression_header;
|
||||
std::vector<char> compressed_output;
|
||||
std::vector<boost::asio::const_buffer> output_buffer;
|
||||
|
||||
switch (compression_type)
|
||||
{
|
||||
case deflateRFC1951:
|
||||
@ -158,7 +159,7 @@ void Connection::handle_write(const boost::system::error_code &e)
|
||||
}
|
||||
}
|
||||
|
||||
void Connection::compressBufferCollection(std::vector<std::string> uncompressed_data,
|
||||
void Connection::compressBufferCollection(std::vector<char> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> &compressed_data)
|
||||
{
|
||||
@ -171,16 +172,10 @@ void Connection::compressBufferCollection(std::vector<std::string> uncompressed_
|
||||
}
|
||||
|
||||
BOOST_ASSERT(compressed_data.empty());
|
||||
boost::iostreams::filtering_ostream compressing_stream;
|
||||
|
||||
compressing_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
|
||||
compressing_stream.push(boost::iostreams::back_inserter(compressed_data));
|
||||
|
||||
for (const std::string &line : uncompressed_data)
|
||||
{
|
||||
compressing_stream << line;
|
||||
}
|
||||
|
||||
compressing_stream.reset();
|
||||
boost::iostreams::filtering_ostream gzip_stream;
|
||||
gzip_stream.push(boost::iostreams::gzip_compressor(compression_parameters));
|
||||
gzip_stream.push(boost::iostreams::back_inserter(compressed_data));
|
||||
gzip_stream.write(&uncompressed_data[0], uncompressed_data.size());
|
||||
boost::iostreams::close(gzip_stream);
|
||||
}
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class Connection : public std::enable_shared_from_this<Connection>
|
||||
/// Handle completion of a write operation.
|
||||
void handle_write(const boost::system::error_code &e);
|
||||
|
||||
void compressBufferCollection(std::vector<std::string> uncompressed_data,
|
||||
void compressBufferCollection(std::vector<char> uncompressed_data,
|
||||
CompressionType compression_type,
|
||||
std::vector<char> &compressed_data);
|
||||
|
||||
|
@ -79,13 +79,13 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
|
||||
if (boost::filesystem::exists(timestamp_path))
|
||||
{
|
||||
SimpleLogger().Write() << "Loading Timestamp";
|
||||
boost::filesystem::ifstream timestampInStream(timestamp_path);
|
||||
if (!timestampInStream)
|
||||
boost::filesystem::ifstream timestamp_stream(timestamp_path);
|
||||
if (!timestamp_stream)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING) << timestamp_path << " not found";
|
||||
}
|
||||
getline(timestampInStream, m_timestamp);
|
||||
timestampInStream.close();
|
||||
getline(timestamp_stream, m_timestamp);
|
||||
timestamp_stream.close();
|
||||
}
|
||||
if (m_timestamp.empty())
|
||||
{
|
||||
@ -279,16 +279,23 @@ template <class EdgeDataT> class InternalDataFacade : public BaseDataFacade<Edge
|
||||
|
||||
// load data
|
||||
SimpleLogger().Write() << "loading graph data";
|
||||
AssertPathExists(hsgr_path);
|
||||
LoadGraph(hsgr_path);
|
||||
SimpleLogger().Write() << "loading egde information";
|
||||
AssertPathExists(nodes_data_path);
|
||||
AssertPathExists(edges_data_path);
|
||||
LoadNodeAndEdgeInformation(nodes_data_path, edges_data_path);
|
||||
SimpleLogger().Write() << "loading geometries";
|
||||
AssertPathExists(geometries_path);
|
||||
LoadGeometries(geometries_path);
|
||||
SimpleLogger().Write() << "loading r-tree";
|
||||
AssertPathExists(ram_index_path);
|
||||
AssertPathExists(file_index_path);
|
||||
LoadRTree(ram_index_path, file_index_path);
|
||||
SimpleLogger().Write() << "loading timestamp";
|
||||
LoadTimestamp(timestamp_path);
|
||||
SimpleLogger().Write() << "loading street names";
|
||||
AssertPathExists(names_data_path);
|
||||
LoadStreetNames(names_data_path);
|
||||
}
|
||||
|
||||
|
@ -38,7 +38,7 @@ void Reply::setSize(const unsigned size)
|
||||
{
|
||||
if ("Content-Length" == h.name)
|
||||
{
|
||||
intToString(size, h.value);
|
||||
h.value = IntToString(size);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -47,10 +47,7 @@ void Reply::setSize(const unsigned size)
|
||||
void Reply::SetUncompressedSize()
|
||||
{
|
||||
unsigned uncompressed_size = 0;
|
||||
for (const std::string ¤t_line : content)
|
||||
{
|
||||
uncompressed_size += current_line.size();
|
||||
}
|
||||
uncompressed_size = content.size();
|
||||
setSize(uncompressed_size);
|
||||
}
|
||||
|
||||
@ -66,10 +63,7 @@ std::vector<boost::asio::const_buffer> Reply::toBuffers()
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(crlf));
|
||||
for (const std::string &line : content)
|
||||
{
|
||||
buffers.push_back(boost::asio::buffer(line));
|
||||
}
|
||||
buffers.push_back(boost::asio::buffer(content));
|
||||
return buffers;
|
||||
}
|
||||
|
||||
@ -94,14 +88,15 @@ Reply Reply::StockReply(Reply::status_type status)
|
||||
Reply rep;
|
||||
rep.status = status;
|
||||
rep.content.clear();
|
||||
rep.content.push_back(rep.ToString(status));
|
||||
|
||||
const std::string status_string = rep.ToString(status);
|
||||
rep.content.insert(rep.content.end(), status_string.begin(), status_string.end());
|
||||
rep.headers.resize(3);
|
||||
rep.headers[0].name = "Access-Control-Allow-Origin";
|
||||
rep.headers[0].value = "*";
|
||||
rep.headers[1].name = "Content-Length";
|
||||
|
||||
std::string size_string;
|
||||
intToString(rep.content.size(), size_string);
|
||||
std::string size_string = IntToString(rep.content.size());
|
||||
|
||||
rep.headers[1].value = size_string;
|
||||
rep.headers[2].name = "Content-Type";
|
||||
|
@ -29,6 +29,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#include "RequestHandler.h"
|
||||
#include "Http/Request.h"
|
||||
|
||||
#include "../DataStructures/JSONContainer.h"
|
||||
#include "../Library/OSRM.h"
|
||||
#include "../Util/SimpleLogger.h"
|
||||
#include "../Util/StringUtil.h"
|
||||
@ -85,18 +86,51 @@ void RequestHandler::handle_request(const http::Request &req, http::Reply &reply
|
||||
reply = http::Reply::StockReply(http::Reply::badRequest);
|
||||
reply.content.clear();
|
||||
const int position = std::distance(request.begin(), it);
|
||||
reply.content.push_back(
|
||||
"{\"status\":400,\"status_message\":\"Query string malformed close to position ");
|
||||
std::string tmp_position_string;
|
||||
intToString(position, tmp_position_string);
|
||||
reply.content.push_back(tmp_position_string);
|
||||
reply.content.push_back("\"}");
|
||||
JSON::Object json_result;
|
||||
json_result.values["status"] = 400;
|
||||
std::string tmp_position_string = IntToString(position);
|
||||
std::string message = ("Query string malformed close to position " + IntToString(position));
|
||||
json_result.values["status_message"] = message;
|
||||
JSON::render(reply.content, json_result);
|
||||
}
|
||||
else
|
||||
{
|
||||
// parsing done, lets call the right plugin to handle the request
|
||||
BOOST_ASSERT_MSG(routing_machine != nullptr, "pointer not init'ed");
|
||||
|
||||
if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
const std::string json_p = (route_parameters.jsonp_parameter + "(");
|
||||
reply.content.insert(reply.content.end(), json_p.begin(), json_p.end());
|
||||
}
|
||||
routing_machine->RunQuery(route_parameters, reply);
|
||||
|
||||
// set headers, still ugly and should be reworked
|
||||
reply.headers.resize(3);
|
||||
if ("gpx" == route_parameters.output_format)
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/gpx+xml; charset=UTF-8";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"route.gpx\"";
|
||||
}
|
||||
else if (!route_parameters.jsonp_parameter.empty())
|
||||
{
|
||||
reply.content.push_back(')');
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "text/javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"response.js\"";
|
||||
}
|
||||
else
|
||||
{
|
||||
reply.headers[1].name = "Content-Type";
|
||||
reply.headers[1].value = "application/x-javascript";
|
||||
reply.headers[2].name = "Content-Disposition";
|
||||
reply.headers[2].value = "attachment; filename=\"response.json\"";
|
||||
}
|
||||
reply.headers[0].name = "Content-Length";
|
||||
reply.headers[0].value = IntToString(reply.content.size());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
@ -262,10 +262,10 @@ RequestParser::consume(Request &req, char input, http::CompressionType *compress
|
||||
return boost::indeterminate;
|
||||
}
|
||||
return false;
|
||||
case expecting_newline_3:
|
||||
default: // expecting_newline_3:
|
||||
return (input == '\n');
|
||||
default:
|
||||
return false;
|
||||
// default:
|
||||
// return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -41,12 +41,8 @@ struct ServerFactory
|
||||
ServerFactory(const ServerFactory &) = delete;
|
||||
static Server *CreateServer(std::string &ip_address, int ip_port, int threads)
|
||||
{
|
||||
|
||||
SimpleLogger().Write() << "http 1.1 compression handled by zlib version " << zlibVersion();
|
||||
|
||||
std::string port_stream;
|
||||
intToString(ip_port, port_stream);
|
||||
|
||||
std::string port_stream = IntToString(ip_port);
|
||||
return new Server(ip_address, port_stream, std::min(omp_get_num_procs(), threads));
|
||||
}
|
||||
};
|
||||
|
@ -110,10 +110,10 @@ int main(int argc, const char *argv[])
|
||||
// attention: super-inefficient hack below:
|
||||
|
||||
std::stringstream my_stream;
|
||||
for (const std::string &line : osrm_reply.content)
|
||||
for (const auto &element : osrm_reply.content)
|
||||
{
|
||||
std::cout << line;
|
||||
my_stream << line;
|
||||
std::cout << element;
|
||||
my_stream << element;
|
||||
}
|
||||
std::cout << std::endl;
|
||||
|
||||
|
@ -140,13 +140,8 @@ inline void AssertPathExists(const boost::filesystem::path &path)
|
||||
{
|
||||
if (!boost::filesystem::is_regular_file(path))
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << path << " check failed";
|
||||
throw OSRMException(path.string() + " not found.");
|
||||
}
|
||||
else
|
||||
{
|
||||
SimpleLogger().Write(logDEBUG) << path << " exists";
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* BOOST_FILE_SYSTEM_FIX_H */
|
||||
|
@ -28,767 +28,13 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef COMPUTE_ANGLE_H
|
||||
#define COMPUTE_ANGLE_H
|
||||
|
||||
#include "TrigonometryTables.h"
|
||||
#include "../Util/MercatorUtil.h"
|
||||
#include <osrm/Coordinate.h>
|
||||
|
||||
#include <boost/assert.hpp>
|
||||
#include <cmath>
|
||||
|
||||
constexpr unsigned short atan_table[4096] = {
|
||||
0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065,
|
||||
0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0,
|
||||
0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a,
|
||||
0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4,
|
||||
0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e,
|
||||
0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9,
|
||||
0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343,
|
||||
0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd,
|
||||
0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437,
|
||||
0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2,
|
||||
0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c,
|
||||
0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6,
|
||||
0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620,
|
||||
0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b,
|
||||
0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715,
|
||||
0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f,
|
||||
0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809,
|
||||
0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883,
|
||||
0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd,
|
||||
0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978,
|
||||
0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2,
|
||||
0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c,
|
||||
0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6,
|
||||
0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60,
|
||||
0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda,
|
||||
0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54,
|
||||
0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce,
|
||||
0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48,
|
||||
0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3,
|
||||
0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d,
|
||||
0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7,
|
||||
0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31,
|
||||
0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab,
|
||||
0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025,
|
||||
0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e,
|
||||
0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118,
|
||||
0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192,
|
||||
0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c,
|
||||
0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286,
|
||||
0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300,
|
||||
0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a,
|
||||
0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4,
|
||||
0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d,
|
||||
0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7,
|
||||
0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561,
|
||||
0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db,
|
||||
0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654,
|
||||
0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce,
|
||||
0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748,
|
||||
0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1,
|
||||
0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b,
|
||||
0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4,
|
||||
0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e,
|
||||
0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8,
|
||||
0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21,
|
||||
0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a,
|
||||
0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14,
|
||||
0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d,
|
||||
0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07,
|
||||
0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80,
|
||||
0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9,
|
||||
0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73,
|
||||
0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec,
|
||||
0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65,
|
||||
0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede,
|
||||
0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57,
|
||||
0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1,
|
||||
0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a,
|
||||
0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3,
|
||||
0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c,
|
||||
0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5,
|
||||
0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e,
|
||||
0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6,
|
||||
0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f,
|
||||
0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398,
|
||||
0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411,
|
||||
0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a,
|
||||
0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502,
|
||||
0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b,
|
||||
0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4,
|
||||
0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c,
|
||||
0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5,
|
||||
0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d,
|
||||
0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6,
|
||||
0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e,
|
||||
0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7,
|
||||
0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f,
|
||||
0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7,
|
||||
0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f,
|
||||
0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8,
|
||||
0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20,
|
||||
0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98,
|
||||
0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10,
|
||||
0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88,
|
||||
0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00,
|
||||
0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78,
|
||||
0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0,
|
||||
0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68,
|
||||
0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf,
|
||||
0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57,
|
||||
0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf,
|
||||
0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046,
|
||||
0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be,
|
||||
0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135,
|
||||
0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad,
|
||||
0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224,
|
||||
0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c,
|
||||
0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313,
|
||||
0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a,
|
||||
0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401,
|
||||
0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479,
|
||||
0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0,
|
||||
0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567,
|
||||
0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de,
|
||||
0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655,
|
||||
0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb,
|
||||
0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742,
|
||||
0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9,
|
||||
0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830,
|
||||
0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6,
|
||||
0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d,
|
||||
0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993,
|
||||
0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a,
|
||||
0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80,
|
||||
0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7,
|
||||
0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d,
|
||||
0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3,
|
||||
0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59,
|
||||
0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf,
|
||||
0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45,
|
||||
0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb,
|
||||
0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31,
|
||||
0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7,
|
||||
0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d,
|
||||
0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93,
|
||||
0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008,
|
||||
0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e,
|
||||
0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3,
|
||||
0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169,
|
||||
0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de,
|
||||
0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253,
|
||||
0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9,
|
||||
0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e,
|
||||
0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3,
|
||||
0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428,
|
||||
0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d,
|
||||
0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512,
|
||||
0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586,
|
||||
0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb,
|
||||
0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670,
|
||||
0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5,
|
||||
0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759,
|
||||
0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd,
|
||||
0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842,
|
||||
0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6,
|
||||
0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a,
|
||||
0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f,
|
||||
0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13,
|
||||
0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87,
|
||||
0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb,
|
||||
0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f,
|
||||
0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2,
|
||||
0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56,
|
||||
0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca,
|
||||
0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d,
|
||||
0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1,
|
||||
0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24,
|
||||
0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97,
|
||||
0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b,
|
||||
0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e,
|
||||
0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1,
|
||||
0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064,
|
||||
0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7,
|
||||
0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a,
|
||||
0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc,
|
||||
0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f,
|
||||
0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2,
|
||||
0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314,
|
||||
0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387,
|
||||
0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9,
|
||||
0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b,
|
||||
0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de,
|
||||
0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550,
|
||||
0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2,
|
||||
0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634,
|
||||
0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6,
|
||||
0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717,
|
||||
0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789,
|
||||
0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb,
|
||||
0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c,
|
||||
0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de,
|
||||
0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f,
|
||||
0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0,
|
||||
0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31,
|
||||
0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2,
|
||||
0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13,
|
||||
0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84,
|
||||
0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5,
|
||||
0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66,
|
||||
0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7,
|
||||
0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47,
|
||||
0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8,
|
||||
0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28,
|
||||
0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98,
|
||||
0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09,
|
||||
0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79,
|
||||
0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9,
|
||||
0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059,
|
||||
0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8,
|
||||
0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138,
|
||||
0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8,
|
||||
0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217,
|
||||
0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287,
|
||||
0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6,
|
||||
0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366,
|
||||
0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5,
|
||||
0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444,
|
||||
0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3,
|
||||
0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522,
|
||||
0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591,
|
||||
0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff,
|
||||
0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e,
|
||||
0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc,
|
||||
0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b,
|
||||
0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9,
|
||||
0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827,
|
||||
0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896,
|
||||
0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904,
|
||||
0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972,
|
||||
0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df,
|
||||
0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d,
|
||||
0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb,
|
||||
0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28,
|
||||
0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96,
|
||||
0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03,
|
||||
0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70,
|
||||
0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde,
|
||||
0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b,
|
||||
0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8,
|
||||
0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25,
|
||||
0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91,
|
||||
0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe,
|
||||
0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b,
|
||||
0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7,
|
||||
0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043,
|
||||
0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0,
|
||||
0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c,
|
||||
0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188,
|
||||
0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4,
|
||||
0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260,
|
||||
0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc,
|
||||
0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337,
|
||||
0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3,
|
||||
0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e,
|
||||
0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a,
|
||||
0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5,
|
||||
0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550,
|
||||
0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb,
|
||||
0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626,
|
||||
0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691,
|
||||
0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb,
|
||||
0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766,
|
||||
0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1,
|
||||
0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b,
|
||||
0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5,
|
||||
0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910,
|
||||
0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a,
|
||||
0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4,
|
||||
0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e,
|
||||
0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7,
|
||||
0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21,
|
||||
0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b,
|
||||
0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4,
|
||||
0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d,
|
||||
0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7,
|
||||
0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30,
|
||||
0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99,
|
||||
0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02,
|
||||
0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b,
|
||||
0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3,
|
||||
0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c,
|
||||
0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4,
|
||||
0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d,
|
||||
0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075,
|
||||
0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd,
|
||||
0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145,
|
||||
0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad,
|
||||
0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215,
|
||||
0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d,
|
||||
0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5,
|
||||
0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c,
|
||||
0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3,
|
||||
0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b,
|
||||
0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482,
|
||||
0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9,
|
||||
0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550,
|
||||
0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7,
|
||||
0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e,
|
||||
0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684,
|
||||
0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb,
|
||||
0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751,
|
||||
0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8,
|
||||
0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e,
|
||||
0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884,
|
||||
0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea,
|
||||
0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950,
|
||||
0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6,
|
||||
0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b,
|
||||
0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81,
|
||||
0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6,
|
||||
0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b,
|
||||
0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1,
|
||||
0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16,
|
||||
0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b,
|
||||
0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0,
|
||||
0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44,
|
||||
0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9,
|
||||
0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d,
|
||||
0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72,
|
||||
0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6,
|
||||
0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a,
|
||||
0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e,
|
||||
0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002,
|
||||
0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066,
|
||||
0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca,
|
||||
0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e,
|
||||
0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191,
|
||||
0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5,
|
||||
0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258,
|
||||
0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb,
|
||||
0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e,
|
||||
0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381,
|
||||
0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4,
|
||||
0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447,
|
||||
0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9,
|
||||
0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c,
|
||||
0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e,
|
||||
0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0,
|
||||
0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632,
|
||||
0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694,
|
||||
0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6,
|
||||
0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758,
|
||||
0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba,
|
||||
0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b,
|
||||
0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d,
|
||||
0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de,
|
||||
0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f,
|
||||
0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0,
|
||||
0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01,
|
||||
0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62,
|
||||
0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3,
|
||||
0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24,
|
||||
0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84,
|
||||
0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5,
|
||||
0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45,
|
||||
0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5,
|
||||
0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05,
|
||||
0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65,
|
||||
0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5,
|
||||
0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25,
|
||||
0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84,
|
||||
0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4,
|
||||
0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43,
|
||||
0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3,
|
||||
0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002,
|
||||
0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061,
|
||||
0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0,
|
||||
0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e,
|
||||
0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d,
|
||||
0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc,
|
||||
0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a,
|
||||
0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298,
|
||||
0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7,
|
||||
0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355,
|
||||
0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3,
|
||||
0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411,
|
||||
0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e,
|
||||
0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc,
|
||||
0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a,
|
||||
0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587,
|
||||
0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4,
|
||||
0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641,
|
||||
0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e,
|
||||
0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb,
|
||||
0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758,
|
||||
0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5,
|
||||
0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812,
|
||||
0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e,
|
||||
0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca,
|
||||
0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927,
|
||||
0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983,
|
||||
0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df,
|
||||
0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b,
|
||||
0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96,
|
||||
0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2,
|
||||
0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e,
|
||||
0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9,
|
||||
0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04,
|
||||
0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60,
|
||||
0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb,
|
||||
0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16,
|
||||
0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70,
|
||||
0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb,
|
||||
0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26,
|
||||
0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80,
|
||||
0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb,
|
||||
0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35,
|
||||
0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f,
|
||||
0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9,
|
||||
0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043,
|
||||
0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d,
|
||||
0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6,
|
||||
0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150,
|
||||
0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa,
|
||||
0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203,
|
||||
0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c,
|
||||
0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5,
|
||||
0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e,
|
||||
0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367,
|
||||
0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0,
|
||||
0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418,
|
||||
0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471,
|
||||
0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9,
|
||||
0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522,
|
||||
0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a,
|
||||
0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2,
|
||||
0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a,
|
||||
0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682,
|
||||
0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9,
|
||||
0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731,
|
||||
0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788,
|
||||
0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0,
|
||||
0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837,
|
||||
0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e,
|
||||
0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5,
|
||||
0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c,
|
||||
0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993,
|
||||
0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea,
|
||||
0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40,
|
||||
0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97,
|
||||
0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed,
|
||||
0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43,
|
||||
0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99,
|
||||
0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef,
|
||||
0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45,
|
||||
0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b,
|
||||
0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0,
|
||||
0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46,
|
||||
0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b,
|
||||
0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1,
|
||||
0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46,
|
||||
0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b,
|
||||
0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0,
|
||||
0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45,
|
||||
0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99,
|
||||
0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee,
|
||||
0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042,
|
||||
0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097,
|
||||
0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb,
|
||||
0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f,
|
||||
0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193,
|
||||
0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7,
|
||||
0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b,
|
||||
0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f,
|
||||
0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2,
|
||||
0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336,
|
||||
0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389,
|
||||
0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc,
|
||||
0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f,
|
||||
0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482,
|
||||
0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5,
|
||||
0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528,
|
||||
0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b,
|
||||
0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd,
|
||||
0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620,
|
||||
0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672,
|
||||
0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4,
|
||||
0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716,
|
||||
0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768,
|
||||
0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba,
|
||||
0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c,
|
||||
0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e,
|
||||
0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af,
|
||||
0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901,
|
||||
0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952,
|
||||
0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3,
|
||||
0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4,
|
||||
0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45,
|
||||
0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96,
|
||||
0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7,
|
||||
0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37,
|
||||
0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88,
|
||||
0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8,
|
||||
0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29,
|
||||
0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79,
|
||||
0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9,
|
||||
0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19,
|
||||
0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69,
|
||||
0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9,
|
||||
0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08,
|
||||
0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58,
|
||||
0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7,
|
||||
0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6,
|
||||
0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46,
|
||||
0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95,
|
||||
0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4,
|
||||
0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032,
|
||||
0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081,
|
||||
0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0,
|
||||
0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e,
|
||||
0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d,
|
||||
0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb,
|
||||
0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209,
|
||||
0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257,
|
||||
0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5,
|
||||
0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3,
|
||||
0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341,
|
||||
0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f,
|
||||
0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc,
|
||||
0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a,
|
||||
0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477,
|
||||
0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4,
|
||||
0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511,
|
||||
0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e,
|
||||
0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab,
|
||||
0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8,
|
||||
0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645,
|
||||
0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691,
|
||||
0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de,
|
||||
0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a,
|
||||
0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776,
|
||||
0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2,
|
||||
0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e,
|
||||
0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a,
|
||||
0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6,
|
||||
0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2,
|
||||
0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d,
|
||||
0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989,
|
||||
0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4,
|
||||
0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f,
|
||||
0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a,
|
||||
0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6,
|
||||
0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00,
|
||||
0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b,
|
||||
0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96,
|
||||
0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1,
|
||||
0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b,
|
||||
0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76,
|
||||
0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0,
|
||||
0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a,
|
||||
0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54,
|
||||
0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e,
|
||||
0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8,
|
||||
0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32,
|
||||
0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b,
|
||||
0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5,
|
||||
0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e,
|
||||
0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58,
|
||||
0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1,
|
||||
0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea,
|
||||
0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033,
|
||||
0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c,
|
||||
0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5,
|
||||
0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e,
|
||||
0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156,
|
||||
0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f,
|
||||
0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7,
|
||||
0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f,
|
||||
0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278,
|
||||
0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0,
|
||||
0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308,
|
||||
0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350,
|
||||
0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397,
|
||||
0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df,
|
||||
0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427,
|
||||
0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e,
|
||||
0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6,
|
||||
0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd,
|
||||
0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544,
|
||||
0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b,
|
||||
0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2,
|
||||
0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619,
|
||||
0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660,
|
||||
0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6,
|
||||
0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed,
|
||||
0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733,
|
||||
0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a,
|
||||
0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0,
|
||||
0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806,
|
||||
0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c,
|
||||
0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892,
|
||||
0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8,
|
||||
0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d,
|
||||
0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963,
|
||||
0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9,
|
||||
0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee,
|
||||
0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33,
|
||||
0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79,
|
||||
0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe,
|
||||
0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03,
|
||||
0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48,
|
||||
0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d,
|
||||
0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1,
|
||||
0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16,
|
||||
0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a,
|
||||
0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f,
|
||||
0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3,
|
||||
0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27,
|
||||
0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c,
|
||||
0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0,
|
||||
0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4,
|
||||
0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37,
|
||||
0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b,
|
||||
0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf,
|
||||
0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02,
|
||||
0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46,
|
||||
0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89,
|
||||
0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc,
|
||||
0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f,
|
||||
0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052,
|
||||
0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095,
|
||||
0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8,
|
||||
0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b,
|
||||
0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e,
|
||||
0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0,
|
||||
0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3,
|
||||
0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225,
|
||||
0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267,
|
||||
0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa,
|
||||
0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec,
|
||||
0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e,
|
||||
0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f,
|
||||
0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1,
|
||||
0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3,
|
||||
0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435,
|
||||
0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476,
|
||||
0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7,
|
||||
0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9,
|
||||
0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a,
|
||||
0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b,
|
||||
0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc,
|
||||
0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd,
|
||||
0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e,
|
||||
0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f,
|
||||
0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf,
|
||||
0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700,
|
||||
0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740,
|
||||
0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781,
|
||||
0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1,
|
||||
0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801,
|
||||
0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841,
|
||||
0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881,
|
||||
0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1,
|
||||
0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901,
|
||||
0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941,
|
||||
0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980,
|
||||
0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0,
|
||||
0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff,
|
||||
0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e,
|
||||
0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e,
|
||||
0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd,
|
||||
0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc,
|
||||
0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b,
|
||||
0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a,
|
||||
0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8,
|
||||
0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7,
|
||||
0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36,
|
||||
0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74,
|
||||
0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3,
|
||||
0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1,
|
||||
0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f,
|
||||
0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d,
|
||||
0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab,
|
||||
0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9,
|
||||
0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27,
|
||||
0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65,
|
||||
0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3,
|
||||
0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0,
|
||||
0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e,
|
||||
0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b,
|
||||
0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98,
|
||||
0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6,
|
||||
0xffe0, 0xffea, 0xfff4, 0xffff
|
||||
};
|
||||
|
||||
// max value is pi/4
|
||||
constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF;
|
||||
|
||||
inline double atan2_lookup(double y, double x)
|
||||
{
|
||||
if (std::abs(x) < std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
if (y >= 0.)
|
||||
{
|
||||
return M_PI / 2.;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -M_PI / 2.;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned octant = 0;
|
||||
|
||||
if (x < 0.)
|
||||
{
|
||||
octant = 1;
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0.)
|
||||
{
|
||||
octant |= 2;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
double t = y / x;
|
||||
if (t > 1.0)
|
||||
{
|
||||
octant |= 4;
|
||||
t = 1.0 / t;
|
||||
}
|
||||
|
||||
double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR;
|
||||
|
||||
switch (octant)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
angle = M_PI - angle;
|
||||
break;
|
||||
case 2:
|
||||
angle = -angle;
|
||||
break;
|
||||
case 3:
|
||||
angle = -M_PI + angle;
|
||||
break;
|
||||
case 4:
|
||||
angle = M_PI / 2.0 - angle;
|
||||
break;
|
||||
case 5:
|
||||
angle = M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 6:
|
||||
angle = -M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 7:
|
||||
angle = -M_PI / 2.0 - angle;
|
||||
break;
|
||||
}
|
||||
|
||||
return angle;
|
||||
}
|
||||
|
||||
/* Get angle of line segment (A,C)->(C,B), atan2 magic, formerly cosine theorem*/
|
||||
template <class CoordinateT>
|
||||
inline static double GetAngleBetweenThreeFixedPointCoordinates(const CoordinateT &A,
|
||||
|
@ -28,8 +28,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef INI_FILE_UTIL_H
|
||||
#define INI_FILE_UTIL_H
|
||||
|
||||
#include "SimpleLogger.h"
|
||||
|
||||
#include <boost/filesystem.hpp>
|
||||
#include <boost/filesystem/fstream.hpp>
|
||||
#include <boost/regex.hpp>
|
||||
|
||||
#include <regex>
|
||||
#include <string>
|
||||
@ -38,11 +41,11 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
inline std::string ReadIniFileAndLowerContents(const boost::filesystem::path &path)
|
||||
{
|
||||
boost::filesystem::fstream config_stream(path);
|
||||
std::string input_str((std::istreambuf_iterator<char>(config_stream)),
|
||||
std::string ini_file_content((std::istreambuf_iterator<char>(config_stream)),
|
||||
std::istreambuf_iterator<char>());
|
||||
std::regex regex("^([^=]*)"); // match from start of line to '='
|
||||
std::string format("\\L$1\\E"); // replace with downcased substring
|
||||
return std::regex_replace(input_str, regex, format);
|
||||
boost::regex regex( "^([^=]*)" ); //match from start of line to '='
|
||||
std::string format( "\\L$1\\E" ); //replace with downcased substring
|
||||
return boost::regex_replace( ini_file_content, regex, format );
|
||||
}
|
||||
|
||||
#endif // INI_FILE_UTIL_H
|
||||
|
@ -28,16 +28,18 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
#ifndef MERCATOR_UTIL_H
|
||||
#define MERCATOR_UTIL_H
|
||||
|
||||
#include "SimpleLogger.h"
|
||||
|
||||
#include <cmath>
|
||||
|
||||
inline double y2lat(const double a)
|
||||
inline float y2lat(const float a)
|
||||
{
|
||||
return 180. / M_PI * (2. * atan(exp(a * M_PI / 180.)) - M_PI / 2.);
|
||||
return 180.f / M_PI * (2.f * std::atan(std::exp(a * M_PI / 180.f)) - M_PI / 2.f);
|
||||
}
|
||||
|
||||
inline double lat2y(const double a)
|
||||
inline float lat2y(const float a)
|
||||
{
|
||||
return 180. / M_PI * log(tan(M_PI / 4. + a * (M_PI / 180.) / 2.));
|
||||
return 180.f / M_PI * log(tan(M_PI / 4.f + a * (M_PI / 180.f) / 2.f));
|
||||
}
|
||||
|
||||
#endif // MERCATOR_UTIL_H
|
||||
|
@ -159,6 +159,7 @@ inline unsigned GenerateServerProgramOptions(const int argc,
|
||||
boost::program_options::store(parse_config_file(config_stream, config_file_options),
|
||||
option_variables);
|
||||
boost::program_options::notify(option_variables);
|
||||
return INIT_OK_START_ENGINE;
|
||||
}
|
||||
|
||||
if (1 > requested_num_threads)
|
||||
|
46
Util/StdHashExtensions.h
Normal file
46
Util/StdHashExtensions.h
Normal file
@ -0,0 +1,46 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2014, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef STD_HASH_EXTENSIONS_H
|
||||
#define STD_HASH_EXTENSIONS_H
|
||||
|
||||
#include "../typedefs.h"
|
||||
|
||||
#include <functional>
|
||||
|
||||
namespace std
|
||||
{
|
||||
template <> struct hash<std::pair<NodeID, NodeID>>
|
||||
{
|
||||
size_t operator()(const std::pair<NodeID, NodeID> &pair) const
|
||||
{
|
||||
return std::hash<int>()(pair.first) ^ std::hash<int>()(pair.second);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
#endif // STD_HASH_EXTENSIONS_H
|
@ -80,11 +80,12 @@ auto as_integer(Enumeration const value)
|
||||
return static_cast<typename std::underlying_type<Enumeration>::type>(value);
|
||||
}
|
||||
|
||||
static inline void intToString(const int value, std::string &output)
|
||||
static inline std::string IntToString(const int value)
|
||||
{
|
||||
output.clear();
|
||||
std::string output;
|
||||
std::back_insert_iterator<std::string> sink(output);
|
||||
boost::spirit::karma::generate(sink, boost::spirit::karma::int_, value);
|
||||
return output;
|
||||
}
|
||||
|
||||
static inline void int64ToString(const int64_t value, std::string &output)
|
||||
@ -168,11 +169,35 @@ static inline double StringToDouble(const char *p)
|
||||
return r;
|
||||
}
|
||||
|
||||
static inline void doubleToString(const double value, std::string &output)
|
||||
template <typename T>
|
||||
struct scientific_policy : boost::spirit::karma::real_policies<T>
|
||||
{
|
||||
output.clear();
|
||||
// we want the numbers always to be in fixed format
|
||||
static int floatfield(T n) { return boost::spirit::karma::real_policies<T>::fmtflags::fixed; }
|
||||
static unsigned int precision(T) { return 6; }
|
||||
};
|
||||
typedef
|
||||
boost::spirit::karma::real_generator<double, scientific_policy<double> >
|
||||
science_type;
|
||||
|
||||
static inline std::string FixedDoubleToString(const double value)
|
||||
{
|
||||
std::string output;
|
||||
std::back_insert_iterator<std::string> sink(output);
|
||||
boost::spirit::karma::generate(sink, boost::spirit::karma::double_, value);
|
||||
boost::spirit::karma::generate(sink, science_type(), value);
|
||||
if (output.size() >= 2 && output[output.size()-2] == '.' && output[output.size()-1] == '0')
|
||||
{
|
||||
output.resize(output.size()-2);
|
||||
}
|
||||
return output;
|
||||
}
|
||||
|
||||
static inline std::string DoubleToString(const double value)
|
||||
{
|
||||
std::string output;
|
||||
std::back_insert_iterator<std::string> sink(output);
|
||||
boost::spirit::karma::generate(sink, value);
|
||||
return output;
|
||||
}
|
||||
|
||||
static inline void doubleToStringWithTwoDigitsBehindComma(const double value, std::string &output)
|
||||
|
789
Util/TrigonometryTables.h
Normal file
789
Util/TrigonometryTables.h
Normal file
@ -0,0 +1,789 @@
|
||||
/*
|
||||
|
||||
Copyright (c) 2013, Project OSRM, Dennis Luxen, others
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
Redistributions of source code must retain the above copyright notice, this list
|
||||
of conditions and the following disclaimer.
|
||||
Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef TRIGONOMETRY_TABLES_H
|
||||
#define TRIGONOMETRY_TABLES_H
|
||||
|
||||
#include <cmath>
|
||||
|
||||
#include <limits>
|
||||
|
||||
constexpr unsigned short atan_table[4096] = {
|
||||
0x0000, 0x0014, 0x0028, 0x003d, 0x0051, 0x0065,
|
||||
0x007a, 0x008e, 0x00a3, 0x00b7, 0x00cb, 0x00e0,
|
||||
0x00f4, 0x0108, 0x011d, 0x0131, 0x0146, 0x015a,
|
||||
0x016e, 0x0183, 0x0197, 0x01ab, 0x01c0, 0x01d4,
|
||||
0x01e9, 0x01fd, 0x0211, 0x0226, 0x023a, 0x024e,
|
||||
0x0263, 0x0277, 0x028c, 0x02a0, 0x02b4, 0x02c9,
|
||||
0x02dd, 0x02f1, 0x0306, 0x031a, 0x032f, 0x0343,
|
||||
0x0357, 0x036c, 0x0380, 0x0394, 0x03a9, 0x03bd,
|
||||
0x03d2, 0x03e6, 0x03fa, 0x040f, 0x0423, 0x0437,
|
||||
0x044c, 0x0460, 0x0475, 0x0489, 0x049d, 0x04b2,
|
||||
0x04c6, 0x04da, 0x04ef, 0x0503, 0x0517, 0x052c,
|
||||
0x0540, 0x0555, 0x0569, 0x057d, 0x0592, 0x05a6,
|
||||
0x05ba, 0x05cf, 0x05e3, 0x05f8, 0x060c, 0x0620,
|
||||
0x0635, 0x0649, 0x065d, 0x0672, 0x0686, 0x069b,
|
||||
0x06af, 0x06c3, 0x06d8, 0x06ec, 0x0700, 0x0715,
|
||||
0x0729, 0x073d, 0x0752, 0x0766, 0x077b, 0x078f,
|
||||
0x07a3, 0x07b8, 0x07cc, 0x07e0, 0x07f5, 0x0809,
|
||||
0x081d, 0x0832, 0x0846, 0x085b, 0x086f, 0x0883,
|
||||
0x0898, 0x08ac, 0x08c0, 0x08d5, 0x08e9, 0x08fd,
|
||||
0x0912, 0x0926, 0x093b, 0x094f, 0x0963, 0x0978,
|
||||
0x098c, 0x09a0, 0x09b5, 0x09c9, 0x09dd, 0x09f2,
|
||||
0x0a06, 0x0a1a, 0x0a2f, 0x0a43, 0x0a58, 0x0a6c,
|
||||
0x0a80, 0x0a95, 0x0aa9, 0x0abd, 0x0ad2, 0x0ae6,
|
||||
0x0afa, 0x0b0f, 0x0b23, 0x0b37, 0x0b4c, 0x0b60,
|
||||
0x0b75, 0x0b89, 0x0b9d, 0x0bb2, 0x0bc6, 0x0bda,
|
||||
0x0bef, 0x0c03, 0x0c17, 0x0c2c, 0x0c40, 0x0c54,
|
||||
0x0c69, 0x0c7d, 0x0c91, 0x0ca6, 0x0cba, 0x0cce,
|
||||
0x0ce3, 0x0cf7, 0x0d0b, 0x0d20, 0x0d34, 0x0d48,
|
||||
0x0d5d, 0x0d71, 0x0d86, 0x0d9a, 0x0dae, 0x0dc3,
|
||||
0x0dd7, 0x0deb, 0x0e00, 0x0e14, 0x0e28, 0x0e3d,
|
||||
0x0e51, 0x0e65, 0x0e7a, 0x0e8e, 0x0ea2, 0x0eb7,
|
||||
0x0ecb, 0x0edf, 0x0ef4, 0x0f08, 0x0f1c, 0x0f31,
|
||||
0x0f45, 0x0f59, 0x0f6e, 0x0f82, 0x0f96, 0x0fab,
|
||||
0x0fbf, 0x0fd3, 0x0fe8, 0x0ffc, 0x1010, 0x1025,
|
||||
0x1039, 0x104d, 0x1062, 0x1076, 0x108a, 0x109e,
|
||||
0x10b3, 0x10c7, 0x10db, 0x10f0, 0x1104, 0x1118,
|
||||
0x112d, 0x1141, 0x1155, 0x116a, 0x117e, 0x1192,
|
||||
0x11a7, 0x11bb, 0x11cf, 0x11e4, 0x11f8, 0x120c,
|
||||
0x1221, 0x1235, 0x1249, 0x125d, 0x1272, 0x1286,
|
||||
0x129a, 0x12af, 0x12c3, 0x12d7, 0x12ec, 0x1300,
|
||||
0x1314, 0x1329, 0x133d, 0x1351, 0x1365, 0x137a,
|
||||
0x138e, 0x13a2, 0x13b7, 0x13cb, 0x13df, 0x13f4,
|
||||
0x1408, 0x141c, 0x1431, 0x1445, 0x1459, 0x146d,
|
||||
0x1482, 0x1496, 0x14aa, 0x14bf, 0x14d3, 0x14e7,
|
||||
0x14fb, 0x1510, 0x1524, 0x1538, 0x154d, 0x1561,
|
||||
0x1575, 0x1589, 0x159e, 0x15b2, 0x15c6, 0x15db,
|
||||
0x15ef, 0x1603, 0x1617, 0x162c, 0x1640, 0x1654,
|
||||
0x1669, 0x167d, 0x1691, 0x16a5, 0x16ba, 0x16ce,
|
||||
0x16e2, 0x16f7, 0x170b, 0x171f, 0x1733, 0x1748,
|
||||
0x175c, 0x1770, 0x1784, 0x1799, 0x17ad, 0x17c1,
|
||||
0x17d6, 0x17ea, 0x17fe, 0x1812, 0x1827, 0x183b,
|
||||
0x184f, 0x1863, 0x1878, 0x188c, 0x18a0, 0x18b4,
|
||||
0x18c9, 0x18dd, 0x18f1, 0x1905, 0x191a, 0x192e,
|
||||
0x1942, 0x1957, 0x196b, 0x197f, 0x1993, 0x19a8,
|
||||
0x19bc, 0x19d0, 0x19e4, 0x19f9, 0x1a0d, 0x1a21,
|
||||
0x1a35, 0x1a49, 0x1a5e, 0x1a72, 0x1a86, 0x1a9a,
|
||||
0x1aaf, 0x1ac3, 0x1ad7, 0x1aeb, 0x1b00, 0x1b14,
|
||||
0x1b28, 0x1b3c, 0x1b51, 0x1b65, 0x1b79, 0x1b8d,
|
||||
0x1ba2, 0x1bb6, 0x1bca, 0x1bde, 0x1bf2, 0x1c07,
|
||||
0x1c1b, 0x1c2f, 0x1c43, 0x1c58, 0x1c6c, 0x1c80,
|
||||
0x1c94, 0x1ca8, 0x1cbd, 0x1cd1, 0x1ce5, 0x1cf9,
|
||||
0x1d0e, 0x1d22, 0x1d36, 0x1d4a, 0x1d5e, 0x1d73,
|
||||
0x1d87, 0x1d9b, 0x1daf, 0x1dc3, 0x1dd8, 0x1dec,
|
||||
0x1e00, 0x1e14, 0x1e28, 0x1e3d, 0x1e51, 0x1e65,
|
||||
0x1e79, 0x1e8d, 0x1ea2, 0x1eb6, 0x1eca, 0x1ede,
|
||||
0x1ef2, 0x1f07, 0x1f1b, 0x1f2f, 0x1f43, 0x1f57,
|
||||
0x1f6c, 0x1f80, 0x1f94, 0x1fa8, 0x1fbc, 0x1fd1,
|
||||
0x1fe5, 0x1ff9, 0x200d, 0x2021, 0x2035, 0x204a,
|
||||
0x205e, 0x2072, 0x2086, 0x209a, 0x20ae, 0x20c3,
|
||||
0x20d7, 0x20eb, 0x20ff, 0x2113, 0x2127, 0x213c,
|
||||
0x2150, 0x2164, 0x2178, 0x218c, 0x21a0, 0x21b5,
|
||||
0x21c9, 0x21dd, 0x21f1, 0x2205, 0x2219, 0x222e,
|
||||
0x2242, 0x2256, 0x226a, 0x227e, 0x2292, 0x22a6,
|
||||
0x22bb, 0x22cf, 0x22e3, 0x22f7, 0x230b, 0x231f,
|
||||
0x2333, 0x2348, 0x235c, 0x2370, 0x2384, 0x2398,
|
||||
0x23ac, 0x23c0, 0x23d5, 0x23e9, 0x23fd, 0x2411,
|
||||
0x2425, 0x2439, 0x244d, 0x2461, 0x2476, 0x248a,
|
||||
0x249e, 0x24b2, 0x24c6, 0x24da, 0x24ee, 0x2502,
|
||||
0x2517, 0x252b, 0x253f, 0x2553, 0x2567, 0x257b,
|
||||
0x258f, 0x25a3, 0x25b7, 0x25cb, 0x25e0, 0x25f4,
|
||||
0x2608, 0x261c, 0x2630, 0x2644, 0x2658, 0x266c,
|
||||
0x2680, 0x2694, 0x26a9, 0x26bd, 0x26d1, 0x26e5,
|
||||
0x26f9, 0x270d, 0x2721, 0x2735, 0x2749, 0x275d,
|
||||
0x2771, 0x2785, 0x279a, 0x27ae, 0x27c2, 0x27d6,
|
||||
0x27ea, 0x27fe, 0x2812, 0x2826, 0x283a, 0x284e,
|
||||
0x2862, 0x2876, 0x288a, 0x289e, 0x28b3, 0x28c7,
|
||||
0x28db, 0x28ef, 0x2903, 0x2917, 0x292b, 0x293f,
|
||||
0x2953, 0x2967, 0x297b, 0x298f, 0x29a3, 0x29b7,
|
||||
0x29cb, 0x29df, 0x29f3, 0x2a07, 0x2a1b, 0x2a2f,
|
||||
0x2a43, 0x2a58, 0x2a6c, 0x2a80, 0x2a94, 0x2aa8,
|
||||
0x2abc, 0x2ad0, 0x2ae4, 0x2af8, 0x2b0c, 0x2b20,
|
||||
0x2b34, 0x2b48, 0x2b5c, 0x2b70, 0x2b84, 0x2b98,
|
||||
0x2bac, 0x2bc0, 0x2bd4, 0x2be8, 0x2bfc, 0x2c10,
|
||||
0x2c24, 0x2c38, 0x2c4c, 0x2c60, 0x2c74, 0x2c88,
|
||||
0x2c9c, 0x2cb0, 0x2cc4, 0x2cd8, 0x2cec, 0x2d00,
|
||||
0x2d14, 0x2d28, 0x2d3c, 0x2d50, 0x2d64, 0x2d78,
|
||||
0x2d8c, 0x2da0, 0x2db4, 0x2dc8, 0x2ddc, 0x2df0,
|
||||
0x2e04, 0x2e18, 0x2e2c, 0x2e40, 0x2e54, 0x2e68,
|
||||
0x2e7c, 0x2e90, 0x2ea3, 0x2eb7, 0x2ecb, 0x2edf,
|
||||
0x2ef3, 0x2f07, 0x2f1b, 0x2f2f, 0x2f43, 0x2f57,
|
||||
0x2f6b, 0x2f7f, 0x2f93, 0x2fa7, 0x2fbb, 0x2fcf,
|
||||
0x2fe3, 0x2ff7, 0x300b, 0x301e, 0x3032, 0x3046,
|
||||
0x305a, 0x306e, 0x3082, 0x3096, 0x30aa, 0x30be,
|
||||
0x30d2, 0x30e6, 0x30fa, 0x310e, 0x3122, 0x3135,
|
||||
0x3149, 0x315d, 0x3171, 0x3185, 0x3199, 0x31ad,
|
||||
0x31c1, 0x31d5, 0x31e9, 0x31fd, 0x3210, 0x3224,
|
||||
0x3238, 0x324c, 0x3260, 0x3274, 0x3288, 0x329c,
|
||||
0x32b0, 0x32c3, 0x32d7, 0x32eb, 0x32ff, 0x3313,
|
||||
0x3327, 0x333b, 0x334f, 0x3363, 0x3376, 0x338a,
|
||||
0x339e, 0x33b2, 0x33c6, 0x33da, 0x33ee, 0x3401,
|
||||
0x3415, 0x3429, 0x343d, 0x3451, 0x3465, 0x3479,
|
||||
0x348c, 0x34a0, 0x34b4, 0x34c8, 0x34dc, 0x34f0,
|
||||
0x3504, 0x3517, 0x352b, 0x353f, 0x3553, 0x3567,
|
||||
0x357b, 0x358e, 0x35a2, 0x35b6, 0x35ca, 0x35de,
|
||||
0x35f2, 0x3605, 0x3619, 0x362d, 0x3641, 0x3655,
|
||||
0x3668, 0x367c, 0x3690, 0x36a4, 0x36b8, 0x36cb,
|
||||
0x36df, 0x36f3, 0x3707, 0x371b, 0x372f, 0x3742,
|
||||
0x3756, 0x376a, 0x377e, 0x3791, 0x37a5, 0x37b9,
|
||||
0x37cd, 0x37e1, 0x37f4, 0x3808, 0x381c, 0x3830,
|
||||
0x3844, 0x3857, 0x386b, 0x387f, 0x3893, 0x38a6,
|
||||
0x38ba, 0x38ce, 0x38e2, 0x38f5, 0x3909, 0x391d,
|
||||
0x3931, 0x3944, 0x3958, 0x396c, 0x3980, 0x3993,
|
||||
0x39a7, 0x39bb, 0x39cf, 0x39e2, 0x39f6, 0x3a0a,
|
||||
0x3a1e, 0x3a31, 0x3a45, 0x3a59, 0x3a6d, 0x3a80,
|
||||
0x3a94, 0x3aa8, 0x3abb, 0x3acf, 0x3ae3, 0x3af7,
|
||||
0x3b0a, 0x3b1e, 0x3b32, 0x3b45, 0x3b59, 0x3b6d,
|
||||
0x3b81, 0x3b94, 0x3ba8, 0x3bbc, 0x3bcf, 0x3be3,
|
||||
0x3bf7, 0x3c0b, 0x3c1e, 0x3c32, 0x3c46, 0x3c59,
|
||||
0x3c6d, 0x3c81, 0x3c94, 0x3ca8, 0x3cbc, 0x3ccf,
|
||||
0x3ce3, 0x3cf7, 0x3d0a, 0x3d1e, 0x3d32, 0x3d45,
|
||||
0x3d59, 0x3d6d, 0x3d80, 0x3d94, 0x3da8, 0x3dbb,
|
||||
0x3dcf, 0x3de3, 0x3df6, 0x3e0a, 0x3e1e, 0x3e31,
|
||||
0x3e45, 0x3e59, 0x3e6c, 0x3e80, 0x3e93, 0x3ea7,
|
||||
0x3ebb, 0x3ece, 0x3ee2, 0x3ef6, 0x3f09, 0x3f1d,
|
||||
0x3f30, 0x3f44, 0x3f58, 0x3f6b, 0x3f7f, 0x3f93,
|
||||
0x3fa6, 0x3fba, 0x3fcd, 0x3fe1, 0x3ff5, 0x4008,
|
||||
0x401c, 0x402f, 0x4043, 0x4057, 0x406a, 0x407e,
|
||||
0x4091, 0x40a5, 0x40b8, 0x40cc, 0x40e0, 0x40f3,
|
||||
0x4107, 0x411a, 0x412e, 0x4142, 0x4155, 0x4169,
|
||||
0x417c, 0x4190, 0x41a3, 0x41b7, 0x41ca, 0x41de,
|
||||
0x41f2, 0x4205, 0x4219, 0x422c, 0x4240, 0x4253,
|
||||
0x4267, 0x427a, 0x428e, 0x42a1, 0x42b5, 0x42c9,
|
||||
0x42dc, 0x42f0, 0x4303, 0x4317, 0x432a, 0x433e,
|
||||
0x4351, 0x4365, 0x4378, 0x438c, 0x439f, 0x43b3,
|
||||
0x43c6, 0x43da, 0x43ed, 0x4401, 0x4414, 0x4428,
|
||||
0x443b, 0x444f, 0x4462, 0x4476, 0x4489, 0x449d,
|
||||
0x44b0, 0x44c4, 0x44d7, 0x44eb, 0x44fe, 0x4512,
|
||||
0x4525, 0x4539, 0x454c, 0x4560, 0x4573, 0x4586,
|
||||
0x459a, 0x45ad, 0x45c1, 0x45d4, 0x45e8, 0x45fb,
|
||||
0x460f, 0x4622, 0x4636, 0x4649, 0x465c, 0x4670,
|
||||
0x4683, 0x4697, 0x46aa, 0x46be, 0x46d1, 0x46e5,
|
||||
0x46f8, 0x470b, 0x471f, 0x4732, 0x4746, 0x4759,
|
||||
0x476c, 0x4780, 0x4793, 0x47a7, 0x47ba, 0x47cd,
|
||||
0x47e1, 0x47f4, 0x4808, 0x481b, 0x482e, 0x4842,
|
||||
0x4855, 0x4869, 0x487c, 0x488f, 0x48a3, 0x48b6,
|
||||
0x48ca, 0x48dd, 0x48f0, 0x4904, 0x4917, 0x492a,
|
||||
0x493e, 0x4951, 0x4965, 0x4978, 0x498b, 0x499f,
|
||||
0x49b2, 0x49c5, 0x49d9, 0x49ec, 0x49ff, 0x4a13,
|
||||
0x4a26, 0x4a39, 0x4a4d, 0x4a60, 0x4a73, 0x4a87,
|
||||
0x4a9a, 0x4aad, 0x4ac1, 0x4ad4, 0x4ae7, 0x4afb,
|
||||
0x4b0e, 0x4b21, 0x4b35, 0x4b48, 0x4b5b, 0x4b6f,
|
||||
0x4b82, 0x4b95, 0x4ba8, 0x4bbc, 0x4bcf, 0x4be2,
|
||||
0x4bf6, 0x4c09, 0x4c1c, 0x4c2f, 0x4c43, 0x4c56,
|
||||
0x4c69, 0x4c7d, 0x4c90, 0x4ca3, 0x4cb6, 0x4cca,
|
||||
0x4cdd, 0x4cf0, 0x4d03, 0x4d17, 0x4d2a, 0x4d3d,
|
||||
0x4d50, 0x4d64, 0x4d77, 0x4d8a, 0x4d9d, 0x4db1,
|
||||
0x4dc4, 0x4dd7, 0x4dea, 0x4dfe, 0x4e11, 0x4e24,
|
||||
0x4e37, 0x4e4b, 0x4e5e, 0x4e71, 0x4e84, 0x4e97,
|
||||
0x4eab, 0x4ebe, 0x4ed1, 0x4ee4, 0x4ef7, 0x4f0b,
|
||||
0x4f1e, 0x4f31, 0x4f44, 0x4f57, 0x4f6b, 0x4f7e,
|
||||
0x4f91, 0x4fa4, 0x4fb7, 0x4fcb, 0x4fde, 0x4ff1,
|
||||
0x5004, 0x5017, 0x502a, 0x503e, 0x5051, 0x5064,
|
||||
0x5077, 0x508a, 0x509d, 0x50b1, 0x50c4, 0x50d7,
|
||||
0x50ea, 0x50fd, 0x5110, 0x5123, 0x5137, 0x514a,
|
||||
0x515d, 0x5170, 0x5183, 0x5196, 0x51a9, 0x51bc,
|
||||
0x51d0, 0x51e3, 0x51f6, 0x5209, 0x521c, 0x522f,
|
||||
0x5242, 0x5255, 0x5268, 0x527c, 0x528f, 0x52a2,
|
||||
0x52b5, 0x52c8, 0x52db, 0x52ee, 0x5301, 0x5314,
|
||||
0x5327, 0x533a, 0x534e, 0x5361, 0x5374, 0x5387,
|
||||
0x539a, 0x53ad, 0x53c0, 0x53d3, 0x53e6, 0x53f9,
|
||||
0x540c, 0x541f, 0x5432, 0x5445, 0x5458, 0x546b,
|
||||
0x547e, 0x5491, 0x54a5, 0x54b8, 0x54cb, 0x54de,
|
||||
0x54f1, 0x5504, 0x5517, 0x552a, 0x553d, 0x5550,
|
||||
0x5563, 0x5576, 0x5589, 0x559c, 0x55af, 0x55c2,
|
||||
0x55d5, 0x55e8, 0x55fb, 0x560e, 0x5621, 0x5634,
|
||||
0x5647, 0x565a, 0x566d, 0x5680, 0x5693, 0x56a6,
|
||||
0x56b9, 0x56cb, 0x56de, 0x56f1, 0x5704, 0x5717,
|
||||
0x572a, 0x573d, 0x5750, 0x5763, 0x5776, 0x5789,
|
||||
0x579c, 0x57af, 0x57c2, 0x57d5, 0x57e8, 0x57fb,
|
||||
0x580e, 0x5820, 0x5833, 0x5846, 0x5859, 0x586c,
|
||||
0x587f, 0x5892, 0x58a5, 0x58b8, 0x58cb, 0x58de,
|
||||
0x58f0, 0x5903, 0x5916, 0x5929, 0x593c, 0x594f,
|
||||
0x5962, 0x5975, 0x5988, 0x599a, 0x59ad, 0x59c0,
|
||||
0x59d3, 0x59e6, 0x59f9, 0x5a0c, 0x5a1f, 0x5a31,
|
||||
0x5a44, 0x5a57, 0x5a6a, 0x5a7d, 0x5a90, 0x5aa2,
|
||||
0x5ab5, 0x5ac8, 0x5adb, 0x5aee, 0x5b01, 0x5b13,
|
||||
0x5b26, 0x5b39, 0x5b4c, 0x5b5f, 0x5b72, 0x5b84,
|
||||
0x5b97, 0x5baa, 0x5bbd, 0x5bd0, 0x5be2, 0x5bf5,
|
||||
0x5c08, 0x5c1b, 0x5c2e, 0x5c40, 0x5c53, 0x5c66,
|
||||
0x5c79, 0x5c8c, 0x5c9e, 0x5cb1, 0x5cc4, 0x5cd7,
|
||||
0x5ce9, 0x5cfc, 0x5d0f, 0x5d22, 0x5d34, 0x5d47,
|
||||
0x5d5a, 0x5d6d, 0x5d7f, 0x5d92, 0x5da5, 0x5db8,
|
||||
0x5dca, 0x5ddd, 0x5df0, 0x5e03, 0x5e15, 0x5e28,
|
||||
0x5e3b, 0x5e4d, 0x5e60, 0x5e73, 0x5e86, 0x5e98,
|
||||
0x5eab, 0x5ebe, 0x5ed0, 0x5ee3, 0x5ef6, 0x5f09,
|
||||
0x5f1b, 0x5f2e, 0x5f41, 0x5f53, 0x5f66, 0x5f79,
|
||||
0x5f8b, 0x5f9e, 0x5fb1, 0x5fc3, 0x5fd6, 0x5fe9,
|
||||
0x5ffb, 0x600e, 0x6021, 0x6033, 0x6046, 0x6059,
|
||||
0x606b, 0x607e, 0x6091, 0x60a3, 0x60b6, 0x60c8,
|
||||
0x60db, 0x60ee, 0x6100, 0x6113, 0x6126, 0x6138,
|
||||
0x614b, 0x615d, 0x6170, 0x6183, 0x6195, 0x61a8,
|
||||
0x61ba, 0x61cd, 0x61e0, 0x61f2, 0x6205, 0x6217,
|
||||
0x622a, 0x623d, 0x624f, 0x6262, 0x6274, 0x6287,
|
||||
0x6299, 0x62ac, 0x62bf, 0x62d1, 0x62e4, 0x62f6,
|
||||
0x6309, 0x631b, 0x632e, 0x6340, 0x6353, 0x6366,
|
||||
0x6378, 0x638b, 0x639d, 0x63b0, 0x63c2, 0x63d5,
|
||||
0x63e7, 0x63fa, 0x640c, 0x641f, 0x6431, 0x6444,
|
||||
0x6456, 0x6469, 0x647b, 0x648e, 0x64a0, 0x64b3,
|
||||
0x64c5, 0x64d8, 0x64ea, 0x64fd, 0x650f, 0x6522,
|
||||
0x6534, 0x6547, 0x6559, 0x656c, 0x657e, 0x6591,
|
||||
0x65a3, 0x65b5, 0x65c8, 0x65da, 0x65ed, 0x65ff,
|
||||
0x6612, 0x6624, 0x6637, 0x6649, 0x665b, 0x666e,
|
||||
0x6680, 0x6693, 0x66a5, 0x66b8, 0x66ca, 0x66dc,
|
||||
0x66ef, 0x6701, 0x6714, 0x6726, 0x6738, 0x674b,
|
||||
0x675d, 0x6770, 0x6782, 0x6794, 0x67a7, 0x67b9,
|
||||
0x67cc, 0x67de, 0x67f0, 0x6803, 0x6815, 0x6827,
|
||||
0x683a, 0x684c, 0x685e, 0x6871, 0x6883, 0x6896,
|
||||
0x68a8, 0x68ba, 0x68cd, 0x68df, 0x68f1, 0x6904,
|
||||
0x6916, 0x6928, 0x693b, 0x694d, 0x695f, 0x6972,
|
||||
0x6984, 0x6996, 0x69a8, 0x69bb, 0x69cd, 0x69df,
|
||||
0x69f2, 0x6a04, 0x6a16, 0x6a29, 0x6a3b, 0x6a4d,
|
||||
0x6a5f, 0x6a72, 0x6a84, 0x6a96, 0x6aa9, 0x6abb,
|
||||
0x6acd, 0x6adf, 0x6af2, 0x6b04, 0x6b16, 0x6b28,
|
||||
0x6b3b, 0x6b4d, 0x6b5f, 0x6b71, 0x6b84, 0x6b96,
|
||||
0x6ba8, 0x6bba, 0x6bcd, 0x6bdf, 0x6bf1, 0x6c03,
|
||||
0x6c15, 0x6c28, 0x6c3a, 0x6c4c, 0x6c5e, 0x6c70,
|
||||
0x6c83, 0x6c95, 0x6ca7, 0x6cb9, 0x6ccb, 0x6cde,
|
||||
0x6cf0, 0x6d02, 0x6d14, 0x6d26, 0x6d39, 0x6d4b,
|
||||
0x6d5d, 0x6d6f, 0x6d81, 0x6d93, 0x6da6, 0x6db8,
|
||||
0x6dca, 0x6ddc, 0x6dee, 0x6e00, 0x6e12, 0x6e25,
|
||||
0x6e37, 0x6e49, 0x6e5b, 0x6e6d, 0x6e7f, 0x6e91,
|
||||
0x6ea3, 0x6eb6, 0x6ec8, 0x6eda, 0x6eec, 0x6efe,
|
||||
0x6f10, 0x6f22, 0x6f34, 0x6f46, 0x6f58, 0x6f6b,
|
||||
0x6f7d, 0x6f8f, 0x6fa1, 0x6fb3, 0x6fc5, 0x6fd7,
|
||||
0x6fe9, 0x6ffb, 0x700d, 0x701f, 0x7031, 0x7043,
|
||||
0x7055, 0x7068, 0x707a, 0x708c, 0x709e, 0x70b0,
|
||||
0x70c2, 0x70d4, 0x70e6, 0x70f8, 0x710a, 0x711c,
|
||||
0x712e, 0x7140, 0x7152, 0x7164, 0x7176, 0x7188,
|
||||
0x719a, 0x71ac, 0x71be, 0x71d0, 0x71e2, 0x71f4,
|
||||
0x7206, 0x7218, 0x722a, 0x723c, 0x724e, 0x7260,
|
||||
0x7272, 0x7284, 0x7296, 0x72a8, 0x72ba, 0x72cc,
|
||||
0x72dd, 0x72ef, 0x7301, 0x7313, 0x7325, 0x7337,
|
||||
0x7349, 0x735b, 0x736d, 0x737f, 0x7391, 0x73a3,
|
||||
0x73b5, 0x73c7, 0x73d8, 0x73ea, 0x73fc, 0x740e,
|
||||
0x7420, 0x7432, 0x7444, 0x7456, 0x7468, 0x747a,
|
||||
0x748b, 0x749d, 0x74af, 0x74c1, 0x74d3, 0x74e5,
|
||||
0x74f7, 0x7509, 0x751a, 0x752c, 0x753e, 0x7550,
|
||||
0x7562, 0x7574, 0x7585, 0x7597, 0x75a9, 0x75bb,
|
||||
0x75cd, 0x75df, 0x75f0, 0x7602, 0x7614, 0x7626,
|
||||
0x7638, 0x764a, 0x765b, 0x766d, 0x767f, 0x7691,
|
||||
0x76a3, 0x76b4, 0x76c6, 0x76d8, 0x76ea, 0x76fb,
|
||||
0x770d, 0x771f, 0x7731, 0x7743, 0x7754, 0x7766,
|
||||
0x7778, 0x778a, 0x779b, 0x77ad, 0x77bf, 0x77d1,
|
||||
0x77e2, 0x77f4, 0x7806, 0x7818, 0x7829, 0x783b,
|
||||
0x784d, 0x785e, 0x7870, 0x7882, 0x7894, 0x78a5,
|
||||
0x78b7, 0x78c9, 0x78da, 0x78ec, 0x78fe, 0x7910,
|
||||
0x7921, 0x7933, 0x7945, 0x7956, 0x7968, 0x797a,
|
||||
0x798b, 0x799d, 0x79af, 0x79c0, 0x79d2, 0x79e4,
|
||||
0x79f5, 0x7a07, 0x7a19, 0x7a2a, 0x7a3c, 0x7a4e,
|
||||
0x7a5f, 0x7a71, 0x7a82, 0x7a94, 0x7aa6, 0x7ab7,
|
||||
0x7ac9, 0x7adb, 0x7aec, 0x7afe, 0x7b0f, 0x7b21,
|
||||
0x7b33, 0x7b44, 0x7b56, 0x7b67, 0x7b79, 0x7b8b,
|
||||
0x7b9c, 0x7bae, 0x7bbf, 0x7bd1, 0x7be2, 0x7bf4,
|
||||
0x7c06, 0x7c17, 0x7c29, 0x7c3a, 0x7c4c, 0x7c5d,
|
||||
0x7c6f, 0x7c81, 0x7c92, 0x7ca4, 0x7cb5, 0x7cc7,
|
||||
0x7cd8, 0x7cea, 0x7cfb, 0x7d0d, 0x7d1e, 0x7d30,
|
||||
0x7d41, 0x7d53, 0x7d64, 0x7d76, 0x7d87, 0x7d99,
|
||||
0x7daa, 0x7dbc, 0x7dcd, 0x7ddf, 0x7df0, 0x7e02,
|
||||
0x7e13, 0x7e25, 0x7e36, 0x7e48, 0x7e59, 0x7e6b,
|
||||
0x7e7c, 0x7e8e, 0x7e9f, 0x7eb0, 0x7ec2, 0x7ed3,
|
||||
0x7ee5, 0x7ef6, 0x7f08, 0x7f19, 0x7f2b, 0x7f3c,
|
||||
0x7f4d, 0x7f5f, 0x7f70, 0x7f82, 0x7f93, 0x7fa4,
|
||||
0x7fb6, 0x7fc7, 0x7fd9, 0x7fea, 0x7ffb, 0x800d,
|
||||
0x801e, 0x8030, 0x8041, 0x8052, 0x8064, 0x8075,
|
||||
0x8086, 0x8098, 0x80a9, 0x80bb, 0x80cc, 0x80dd,
|
||||
0x80ef, 0x8100, 0x8111, 0x8123, 0x8134, 0x8145,
|
||||
0x8157, 0x8168, 0x8179, 0x818b, 0x819c, 0x81ad,
|
||||
0x81bf, 0x81d0, 0x81e1, 0x81f3, 0x8204, 0x8215,
|
||||
0x8226, 0x8238, 0x8249, 0x825a, 0x826c, 0x827d,
|
||||
0x828e, 0x829f, 0x82b1, 0x82c2, 0x82d3, 0x82e5,
|
||||
0x82f6, 0x8307, 0x8318, 0x832a, 0x833b, 0x834c,
|
||||
0x835d, 0x836f, 0x8380, 0x8391, 0x83a2, 0x83b3,
|
||||
0x83c5, 0x83d6, 0x83e7, 0x83f8, 0x840a, 0x841b,
|
||||
0x842c, 0x843d, 0x844e, 0x8460, 0x8471, 0x8482,
|
||||
0x8493, 0x84a4, 0x84b6, 0x84c7, 0x84d8, 0x84e9,
|
||||
0x84fa, 0x850b, 0x851d, 0x852e, 0x853f, 0x8550,
|
||||
0x8561, 0x8572, 0x8584, 0x8595, 0x85a6, 0x85b7,
|
||||
0x85c8, 0x85d9, 0x85ea, 0x85fb, 0x860d, 0x861e,
|
||||
0x862f, 0x8640, 0x8651, 0x8662, 0x8673, 0x8684,
|
||||
0x8695, 0x86a7, 0x86b8, 0x86c9, 0x86da, 0x86eb,
|
||||
0x86fc, 0x870d, 0x871e, 0x872f, 0x8740, 0x8751,
|
||||
0x8762, 0x8773, 0x8784, 0x8796, 0x87a7, 0x87b8,
|
||||
0x87c9, 0x87da, 0x87eb, 0x87fc, 0x880d, 0x881e,
|
||||
0x882f, 0x8840, 0x8851, 0x8862, 0x8873, 0x8884,
|
||||
0x8895, 0x88a6, 0x88b7, 0x88c8, 0x88d9, 0x88ea,
|
||||
0x88fb, 0x890c, 0x891d, 0x892e, 0x893f, 0x8950,
|
||||
0x8961, 0x8972, 0x8983, 0x8994, 0x89a5, 0x89b6,
|
||||
0x89c6, 0x89d7, 0x89e8, 0x89f9, 0x8a0a, 0x8a1b,
|
||||
0x8a2c, 0x8a3d, 0x8a4e, 0x8a5f, 0x8a70, 0x8a81,
|
||||
0x8a92, 0x8aa3, 0x8ab3, 0x8ac4, 0x8ad5, 0x8ae6,
|
||||
0x8af7, 0x8b08, 0x8b19, 0x8b2a, 0x8b3b, 0x8b4b,
|
||||
0x8b5c, 0x8b6d, 0x8b7e, 0x8b8f, 0x8ba0, 0x8bb1,
|
||||
0x8bc1, 0x8bd2, 0x8be3, 0x8bf4, 0x8c05, 0x8c16,
|
||||
0x8c27, 0x8c37, 0x8c48, 0x8c59, 0x8c6a, 0x8c7b,
|
||||
0x8c8c, 0x8c9c, 0x8cad, 0x8cbe, 0x8ccf, 0x8ce0,
|
||||
0x8cf0, 0x8d01, 0x8d12, 0x8d23, 0x8d34, 0x8d44,
|
||||
0x8d55, 0x8d66, 0x8d77, 0x8d87, 0x8d98, 0x8da9,
|
||||
0x8dba, 0x8dca, 0x8ddb, 0x8dec, 0x8dfd, 0x8e0d,
|
||||
0x8e1e, 0x8e2f, 0x8e40, 0x8e50, 0x8e61, 0x8e72,
|
||||
0x8e83, 0x8e93, 0x8ea4, 0x8eb5, 0x8ec5, 0x8ed6,
|
||||
0x8ee7, 0x8ef8, 0x8f08, 0x8f19, 0x8f2a, 0x8f3a,
|
||||
0x8f4b, 0x8f5c, 0x8f6c, 0x8f7d, 0x8f8e, 0x8f9e,
|
||||
0x8faf, 0x8fc0, 0x8fd0, 0x8fe1, 0x8ff2, 0x9002,
|
||||
0x9013, 0x9024, 0x9034, 0x9045, 0x9056, 0x9066,
|
||||
0x9077, 0x9088, 0x9098, 0x90a9, 0x90b9, 0x90ca,
|
||||
0x90db, 0x90eb, 0x90fc, 0x910c, 0x911d, 0x912e,
|
||||
0x913e, 0x914f, 0x915f, 0x9170, 0x9181, 0x9191,
|
||||
0x91a2, 0x91b2, 0x91c3, 0x91d3, 0x91e4, 0x91f5,
|
||||
0x9205, 0x9216, 0x9226, 0x9237, 0x9247, 0x9258,
|
||||
0x9268, 0x9279, 0x9289, 0x929a, 0x92aa, 0x92bb,
|
||||
0x92cc, 0x92dc, 0x92ed, 0x92fd, 0x930e, 0x931e,
|
||||
0x932f, 0x933f, 0x9350, 0x9360, 0x9370, 0x9381,
|
||||
0x9391, 0x93a2, 0x93b2, 0x93c3, 0x93d3, 0x93e4,
|
||||
0x93f4, 0x9405, 0x9415, 0x9426, 0x9436, 0x9447,
|
||||
0x9457, 0x9467, 0x9478, 0x9488, 0x9499, 0x94a9,
|
||||
0x94ba, 0x94ca, 0x94da, 0x94eb, 0x94fb, 0x950c,
|
||||
0x951c, 0x952c, 0x953d, 0x954d, 0x955e, 0x956e,
|
||||
0x957e, 0x958f, 0x959f, 0x95af, 0x95c0, 0x95d0,
|
||||
0x95e1, 0x95f1, 0x9601, 0x9612, 0x9622, 0x9632,
|
||||
0x9643, 0x9653, 0x9663, 0x9674, 0x9684, 0x9694,
|
||||
0x96a5, 0x96b5, 0x96c5, 0x96d6, 0x96e6, 0x96f6,
|
||||
0x9707, 0x9717, 0x9727, 0x9738, 0x9748, 0x9758,
|
||||
0x9768, 0x9779, 0x9789, 0x9799, 0x97aa, 0x97ba,
|
||||
0x97ca, 0x97da, 0x97eb, 0x97fb, 0x980b, 0x981b,
|
||||
0x982c, 0x983c, 0x984c, 0x985c, 0x986d, 0x987d,
|
||||
0x988d, 0x989d, 0x98ad, 0x98be, 0x98ce, 0x98de,
|
||||
0x98ee, 0x98ff, 0x990f, 0x991f, 0x992f, 0x993f,
|
||||
0x9950, 0x9960, 0x9970, 0x9980, 0x9990, 0x99a0,
|
||||
0x99b1, 0x99c1, 0x99d1, 0x99e1, 0x99f1, 0x9a01,
|
||||
0x9a12, 0x9a22, 0x9a32, 0x9a42, 0x9a52, 0x9a62,
|
||||
0x9a72, 0x9a83, 0x9a93, 0x9aa3, 0x9ab3, 0x9ac3,
|
||||
0x9ad3, 0x9ae3, 0x9af3, 0x9b04, 0x9b14, 0x9b24,
|
||||
0x9b34, 0x9b44, 0x9b54, 0x9b64, 0x9b74, 0x9b84,
|
||||
0x9b94, 0x9ba4, 0x9bb5, 0x9bc5, 0x9bd5, 0x9be5,
|
||||
0x9bf5, 0x9c05, 0x9c15, 0x9c25, 0x9c35, 0x9c45,
|
||||
0x9c55, 0x9c65, 0x9c75, 0x9c85, 0x9c95, 0x9ca5,
|
||||
0x9cb5, 0x9cc5, 0x9cd5, 0x9ce5, 0x9cf5, 0x9d05,
|
||||
0x9d15, 0x9d25, 0x9d35, 0x9d45, 0x9d55, 0x9d65,
|
||||
0x9d75, 0x9d85, 0x9d95, 0x9da5, 0x9db5, 0x9dc5,
|
||||
0x9dd5, 0x9de5, 0x9df5, 0x9e05, 0x9e15, 0x9e25,
|
||||
0x9e35, 0x9e45, 0x9e55, 0x9e65, 0x9e74, 0x9e84,
|
||||
0x9e94, 0x9ea4, 0x9eb4, 0x9ec4, 0x9ed4, 0x9ee4,
|
||||
0x9ef4, 0x9f04, 0x9f14, 0x9f23, 0x9f33, 0x9f43,
|
||||
0x9f53, 0x9f63, 0x9f73, 0x9f83, 0x9f93, 0x9fa3,
|
||||
0x9fb2, 0x9fc2, 0x9fd2, 0x9fe2, 0x9ff2, 0xa002,
|
||||
0xa012, 0xa021, 0xa031, 0xa041, 0xa051, 0xa061,
|
||||
0xa071, 0xa080, 0xa090, 0xa0a0, 0xa0b0, 0xa0c0,
|
||||
0xa0cf, 0xa0df, 0xa0ef, 0xa0ff, 0xa10f, 0xa11e,
|
||||
0xa12e, 0xa13e, 0xa14e, 0xa15e, 0xa16d, 0xa17d,
|
||||
0xa18d, 0xa19d, 0xa1ac, 0xa1bc, 0xa1cc, 0xa1dc,
|
||||
0xa1eb, 0xa1fb, 0xa20b, 0xa21b, 0xa22a, 0xa23a,
|
||||
0xa24a, 0xa25a, 0xa269, 0xa279, 0xa289, 0xa298,
|
||||
0xa2a8, 0xa2b8, 0xa2c8, 0xa2d7, 0xa2e7, 0xa2f7,
|
||||
0xa306, 0xa316, 0xa326, 0xa335, 0xa345, 0xa355,
|
||||
0xa364, 0xa374, 0xa384, 0xa393, 0xa3a3, 0xa3b3,
|
||||
0xa3c2, 0xa3d2, 0xa3e2, 0xa3f1, 0xa401, 0xa411,
|
||||
0xa420, 0xa430, 0xa440, 0xa44f, 0xa45f, 0xa46e,
|
||||
0xa47e, 0xa48e, 0xa49d, 0xa4ad, 0xa4bc, 0xa4cc,
|
||||
0xa4dc, 0xa4eb, 0xa4fb, 0xa50a, 0xa51a, 0xa52a,
|
||||
0xa539, 0xa549, 0xa558, 0xa568, 0xa577, 0xa587,
|
||||
0xa597, 0xa5a6, 0xa5b6, 0xa5c5, 0xa5d5, 0xa5e4,
|
||||
0xa5f4, 0xa603, 0xa613, 0xa622, 0xa632, 0xa641,
|
||||
0xa651, 0xa660, 0xa670, 0xa67f, 0xa68f, 0xa69e,
|
||||
0xa6ae, 0xa6bd, 0xa6cd, 0xa6dc, 0xa6ec, 0xa6fb,
|
||||
0xa70b, 0xa71a, 0xa72a, 0xa739, 0xa749, 0xa758,
|
||||
0xa768, 0xa777, 0xa787, 0xa796, 0xa7a5, 0xa7b5,
|
||||
0xa7c4, 0xa7d4, 0xa7e3, 0xa7f3, 0xa802, 0xa812,
|
||||
0xa821, 0xa830, 0xa840, 0xa84f, 0xa85f, 0xa86e,
|
||||
0xa87d, 0xa88d, 0xa89c, 0xa8ac, 0xa8bb, 0xa8ca,
|
||||
0xa8da, 0xa8e9, 0xa8f8, 0xa908, 0xa917, 0xa927,
|
||||
0xa936, 0xa945, 0xa955, 0xa964, 0xa973, 0xa983,
|
||||
0xa992, 0xa9a1, 0xa9b1, 0xa9c0, 0xa9cf, 0xa9df,
|
||||
0xa9ee, 0xa9fd, 0xaa0d, 0xaa1c, 0xaa2b, 0xaa3b,
|
||||
0xaa4a, 0xaa59, 0xaa69, 0xaa78, 0xaa87, 0xaa96,
|
||||
0xaaa6, 0xaab5, 0xaac4, 0xaad4, 0xaae3, 0xaaf2,
|
||||
0xab01, 0xab11, 0xab20, 0xab2f, 0xab3e, 0xab4e,
|
||||
0xab5d, 0xab6c, 0xab7b, 0xab8b, 0xab9a, 0xaba9,
|
||||
0xabb8, 0xabc7, 0xabd7, 0xabe6, 0xabf5, 0xac04,
|
||||
0xac14, 0xac23, 0xac32, 0xac41, 0xac50, 0xac60,
|
||||
0xac6f, 0xac7e, 0xac8d, 0xac9c, 0xacab, 0xacbb,
|
||||
0xacca, 0xacd9, 0xace8, 0xacf7, 0xad06, 0xad16,
|
||||
0xad25, 0xad34, 0xad43, 0xad52, 0xad61, 0xad70,
|
||||
0xad80, 0xad8f, 0xad9e, 0xadad, 0xadbc, 0xadcb,
|
||||
0xadda, 0xade9, 0xadf8, 0xae08, 0xae17, 0xae26,
|
||||
0xae35, 0xae44, 0xae53, 0xae62, 0xae71, 0xae80,
|
||||
0xae8f, 0xae9e, 0xaead, 0xaebd, 0xaecc, 0xaedb,
|
||||
0xaeea, 0xaef9, 0xaf08, 0xaf17, 0xaf26, 0xaf35,
|
||||
0xaf44, 0xaf53, 0xaf62, 0xaf71, 0xaf80, 0xaf8f,
|
||||
0xaf9e, 0xafad, 0xafbc, 0xafcb, 0xafda, 0xafe9,
|
||||
0xaff8, 0xb007, 0xb016, 0xb025, 0xb034, 0xb043,
|
||||
0xb052, 0xb061, 0xb070, 0xb07f, 0xb08e, 0xb09d,
|
||||
0xb0ac, 0xb0bb, 0xb0ca, 0xb0d9, 0xb0e8, 0xb0f6,
|
||||
0xb105, 0xb114, 0xb123, 0xb132, 0xb141, 0xb150,
|
||||
0xb15f, 0xb16e, 0xb17d, 0xb18c, 0xb19b, 0xb1aa,
|
||||
0xb1b8, 0xb1c7, 0xb1d6, 0xb1e5, 0xb1f4, 0xb203,
|
||||
0xb212, 0xb221, 0xb22f, 0xb23e, 0xb24d, 0xb25c,
|
||||
0xb26b, 0xb27a, 0xb289, 0xb297, 0xb2a6, 0xb2b5,
|
||||
0xb2c4, 0xb2d3, 0xb2e2, 0xb2f1, 0xb2ff, 0xb30e,
|
||||
0xb31d, 0xb32c, 0xb33b, 0xb349, 0xb358, 0xb367,
|
||||
0xb376, 0xb385, 0xb393, 0xb3a2, 0xb3b1, 0xb3c0,
|
||||
0xb3cf, 0xb3dd, 0xb3ec, 0xb3fb, 0xb40a, 0xb418,
|
||||
0xb427, 0xb436, 0xb445, 0xb453, 0xb462, 0xb471,
|
||||
0xb480, 0xb48e, 0xb49d, 0xb4ac, 0xb4bb, 0xb4c9,
|
||||
0xb4d8, 0xb4e7, 0xb4f6, 0xb504, 0xb513, 0xb522,
|
||||
0xb530, 0xb53f, 0xb54e, 0xb55c, 0xb56b, 0xb57a,
|
||||
0xb588, 0xb597, 0xb5a6, 0xb5b5, 0xb5c3, 0xb5d2,
|
||||
0xb5e1, 0xb5ef, 0xb5fe, 0xb60d, 0xb61b, 0xb62a,
|
||||
0xb638, 0xb647, 0xb656, 0xb664, 0xb673, 0xb682,
|
||||
0xb690, 0xb69f, 0xb6ae, 0xb6bc, 0xb6cb, 0xb6d9,
|
||||
0xb6e8, 0xb6f7, 0xb705, 0xb714, 0xb722, 0xb731,
|
||||
0xb740, 0xb74e, 0xb75d, 0xb76b, 0xb77a, 0xb788,
|
||||
0xb797, 0xb7a6, 0xb7b4, 0xb7c3, 0xb7d1, 0xb7e0,
|
||||
0xb7ee, 0xb7fd, 0xb80b, 0xb81a, 0xb829, 0xb837,
|
||||
0xb846, 0xb854, 0xb863, 0xb871, 0xb880, 0xb88e,
|
||||
0xb89d, 0xb8ab, 0xb8ba, 0xb8c8, 0xb8d7, 0xb8e5,
|
||||
0xb8f4, 0xb902, 0xb911, 0xb91f, 0xb92e, 0xb93c,
|
||||
0xb94b, 0xb959, 0xb968, 0xb976, 0xb984, 0xb993,
|
||||
0xb9a1, 0xb9b0, 0xb9be, 0xb9cd, 0xb9db, 0xb9ea,
|
||||
0xb9f8, 0xba06, 0xba15, 0xba23, 0xba32, 0xba40,
|
||||
0xba4f, 0xba5d, 0xba6b, 0xba7a, 0xba88, 0xba97,
|
||||
0xbaa5, 0xbab3, 0xbac2, 0xbad0, 0xbade, 0xbaed,
|
||||
0xbafb, 0xbb0a, 0xbb18, 0xbb26, 0xbb35, 0xbb43,
|
||||
0xbb51, 0xbb60, 0xbb6e, 0xbb7c, 0xbb8b, 0xbb99,
|
||||
0xbba8, 0xbbb6, 0xbbc4, 0xbbd3, 0xbbe1, 0xbbef,
|
||||
0xbbfd, 0xbc0c, 0xbc1a, 0xbc28, 0xbc37, 0xbc45,
|
||||
0xbc53, 0xbc62, 0xbc70, 0xbc7e, 0xbc8c, 0xbc9b,
|
||||
0xbca9, 0xbcb7, 0xbcc6, 0xbcd4, 0xbce2, 0xbcf0,
|
||||
0xbcff, 0xbd0d, 0xbd1b, 0xbd29, 0xbd38, 0xbd46,
|
||||
0xbd54, 0xbd62, 0xbd71, 0xbd7f, 0xbd8d, 0xbd9b,
|
||||
0xbdaa, 0xbdb8, 0xbdc6, 0xbdd4, 0xbde2, 0xbdf1,
|
||||
0xbdff, 0xbe0d, 0xbe1b, 0xbe29, 0xbe38, 0xbe46,
|
||||
0xbe54, 0xbe62, 0xbe70, 0xbe7f, 0xbe8d, 0xbe9b,
|
||||
0xbea9, 0xbeb7, 0xbec5, 0xbed4, 0xbee2, 0xbef0,
|
||||
0xbefe, 0xbf0c, 0xbf1a, 0xbf28, 0xbf37, 0xbf45,
|
||||
0xbf53, 0xbf61, 0xbf6f, 0xbf7d, 0xbf8b, 0xbf99,
|
||||
0xbfa7, 0xbfb6, 0xbfc4, 0xbfd2, 0xbfe0, 0xbfee,
|
||||
0xbffc, 0xc00a, 0xc018, 0xc026, 0xc034, 0xc042,
|
||||
0xc051, 0xc05f, 0xc06d, 0xc07b, 0xc089, 0xc097,
|
||||
0xc0a5, 0xc0b3, 0xc0c1, 0xc0cf, 0xc0dd, 0xc0eb,
|
||||
0xc0f9, 0xc107, 0xc115, 0xc123, 0xc131, 0xc13f,
|
||||
0xc14d, 0xc15b, 0xc169, 0xc177, 0xc185, 0xc193,
|
||||
0xc1a1, 0xc1af, 0xc1bd, 0xc1cb, 0xc1d9, 0xc1e7,
|
||||
0xc1f5, 0xc203, 0xc211, 0xc21f, 0xc22d, 0xc23b,
|
||||
0xc249, 0xc257, 0xc265, 0xc273, 0xc281, 0xc28f,
|
||||
0xc29d, 0xc2ab, 0xc2b8, 0xc2c6, 0xc2d4, 0xc2e2,
|
||||
0xc2f0, 0xc2fe, 0xc30c, 0xc31a, 0xc328, 0xc336,
|
||||
0xc344, 0xc352, 0xc35f, 0xc36d, 0xc37b, 0xc389,
|
||||
0xc397, 0xc3a5, 0xc3b3, 0xc3c1, 0xc3ce, 0xc3dc,
|
||||
0xc3ea, 0xc3f8, 0xc406, 0xc414, 0xc422, 0xc42f,
|
||||
0xc43d, 0xc44b, 0xc459, 0xc467, 0xc475, 0xc482,
|
||||
0xc490, 0xc49e, 0xc4ac, 0xc4ba, 0xc4c7, 0xc4d5,
|
||||
0xc4e3, 0xc4f1, 0xc4ff, 0xc50d, 0xc51a, 0xc528,
|
||||
0xc536, 0xc544, 0xc551, 0xc55f, 0xc56d, 0xc57b,
|
||||
0xc589, 0xc596, 0xc5a4, 0xc5b2, 0xc5c0, 0xc5cd,
|
||||
0xc5db, 0xc5e9, 0xc5f7, 0xc604, 0xc612, 0xc620,
|
||||
0xc62d, 0xc63b, 0xc649, 0xc657, 0xc664, 0xc672,
|
||||
0xc680, 0xc68d, 0xc69b, 0xc6a9, 0xc6b7, 0xc6c4,
|
||||
0xc6d2, 0xc6e0, 0xc6ed, 0xc6fb, 0xc709, 0xc716,
|
||||
0xc724, 0xc732, 0xc73f, 0xc74d, 0xc75b, 0xc768,
|
||||
0xc776, 0xc784, 0xc791, 0xc79f, 0xc7ad, 0xc7ba,
|
||||
0xc7c8, 0xc7d6, 0xc7e3, 0xc7f1, 0xc7fe, 0xc80c,
|
||||
0xc81a, 0xc827, 0xc835, 0xc842, 0xc850, 0xc85e,
|
||||
0xc86b, 0xc879, 0xc886, 0xc894, 0xc8a2, 0xc8af,
|
||||
0xc8bd, 0xc8ca, 0xc8d8, 0xc8e5, 0xc8f3, 0xc901,
|
||||
0xc90e, 0xc91c, 0xc929, 0xc937, 0xc944, 0xc952,
|
||||
0xc95f, 0xc96d, 0xc97b, 0xc988, 0xc996, 0xc9a3,
|
||||
0xc9b1, 0xc9be, 0xc9cc, 0xc9d9, 0xc9e7, 0xc9f4,
|
||||
0xca02, 0xca0f, 0xca1d, 0xca2a, 0xca38, 0xca45,
|
||||
0xca53, 0xca60, 0xca6e, 0xca7b, 0xca89, 0xca96,
|
||||
0xcaa4, 0xcab1, 0xcabe, 0xcacc, 0xcad9, 0xcae7,
|
||||
0xcaf4, 0xcb02, 0xcb0f, 0xcb1d, 0xcb2a, 0xcb37,
|
||||
0xcb45, 0xcb52, 0xcb60, 0xcb6d, 0xcb7b, 0xcb88,
|
||||
0xcb95, 0xcba3, 0xcbb0, 0xcbbe, 0xcbcb, 0xcbd8,
|
||||
0xcbe6, 0xcbf3, 0xcc01, 0xcc0e, 0xcc1b, 0xcc29,
|
||||
0xcc36, 0xcc43, 0xcc51, 0xcc5e, 0xcc6c, 0xcc79,
|
||||
0xcc86, 0xcc94, 0xcca1, 0xccae, 0xccbc, 0xccc9,
|
||||
0xccd6, 0xcce4, 0xccf1, 0xccfe, 0xcd0c, 0xcd19,
|
||||
0xcd26, 0xcd34, 0xcd41, 0xcd4e, 0xcd5b, 0xcd69,
|
||||
0xcd76, 0xcd83, 0xcd91, 0xcd9e, 0xcdab, 0xcdb9,
|
||||
0xcdc6, 0xcdd3, 0xcde0, 0xcdee, 0xcdfb, 0xce08,
|
||||
0xce15, 0xce23, 0xce30, 0xce3d, 0xce4a, 0xce58,
|
||||
0xce65, 0xce72, 0xce7f, 0xce8d, 0xce9a, 0xcea7,
|
||||
0xceb4, 0xcec2, 0xcecf, 0xcedc, 0xcee9, 0xcef6,
|
||||
0xcf04, 0xcf11, 0xcf1e, 0xcf2b, 0xcf38, 0xcf46,
|
||||
0xcf53, 0xcf60, 0xcf6d, 0xcf7a, 0xcf87, 0xcf95,
|
||||
0xcfa2, 0xcfaf, 0xcfbc, 0xcfc9, 0xcfd6, 0xcfe4,
|
||||
0xcff1, 0xcffe, 0xd00b, 0xd018, 0xd025, 0xd032,
|
||||
0xd040, 0xd04d, 0xd05a, 0xd067, 0xd074, 0xd081,
|
||||
0xd08e, 0xd09b, 0xd0a9, 0xd0b6, 0xd0c3, 0xd0d0,
|
||||
0xd0dd, 0xd0ea, 0xd0f7, 0xd104, 0xd111, 0xd11e,
|
||||
0xd12b, 0xd139, 0xd146, 0xd153, 0xd160, 0xd16d,
|
||||
0xd17a, 0xd187, 0xd194, 0xd1a1, 0xd1ae, 0xd1bb,
|
||||
0xd1c8, 0xd1d5, 0xd1e2, 0xd1ef, 0xd1fc, 0xd209,
|
||||
0xd216, 0xd223, 0xd230, 0xd23d, 0xd24a, 0xd257,
|
||||
0xd264, 0xd271, 0xd27e, 0xd28b, 0xd298, 0xd2a5,
|
||||
0xd2b2, 0xd2bf, 0xd2cc, 0xd2d9, 0xd2e6, 0xd2f3,
|
||||
0xd300, 0xd30d, 0xd31a, 0xd327, 0xd334, 0xd341,
|
||||
0xd34e, 0xd35b, 0xd368, 0xd375, 0xd382, 0xd38f,
|
||||
0xd39c, 0xd3a8, 0xd3b5, 0xd3c2, 0xd3cf, 0xd3dc,
|
||||
0xd3e9, 0xd3f6, 0xd403, 0xd410, 0xd41d, 0xd42a,
|
||||
0xd436, 0xd443, 0xd450, 0xd45d, 0xd46a, 0xd477,
|
||||
0xd484, 0xd491, 0xd49e, 0xd4aa, 0xd4b7, 0xd4c4,
|
||||
0xd4d1, 0xd4de, 0xd4eb, 0xd4f8, 0xd504, 0xd511,
|
||||
0xd51e, 0xd52b, 0xd538, 0xd545, 0xd551, 0xd55e,
|
||||
0xd56b, 0xd578, 0xd585, 0xd591, 0xd59e, 0xd5ab,
|
||||
0xd5b8, 0xd5c5, 0xd5d1, 0xd5de, 0xd5eb, 0xd5f8,
|
||||
0xd605, 0xd611, 0xd61e, 0xd62b, 0xd638, 0xd645,
|
||||
0xd651, 0xd65e, 0xd66b, 0xd678, 0xd684, 0xd691,
|
||||
0xd69e, 0xd6ab, 0xd6b7, 0xd6c4, 0xd6d1, 0xd6de,
|
||||
0xd6ea, 0xd6f7, 0xd704, 0xd710, 0xd71d, 0xd72a,
|
||||
0xd737, 0xd743, 0xd750, 0xd75d, 0xd769, 0xd776,
|
||||
0xd783, 0xd78f, 0xd79c, 0xd7a9, 0xd7b6, 0xd7c2,
|
||||
0xd7cf, 0xd7dc, 0xd7e8, 0xd7f5, 0xd802, 0xd80e,
|
||||
0xd81b, 0xd828, 0xd834, 0xd841, 0xd84e, 0xd85a,
|
||||
0xd867, 0xd873, 0xd880, 0xd88d, 0xd899, 0xd8a6,
|
||||
0xd8b3, 0xd8bf, 0xd8cc, 0xd8d8, 0xd8e5, 0xd8f2,
|
||||
0xd8fe, 0xd90b, 0xd917, 0xd924, 0xd931, 0xd93d,
|
||||
0xd94a, 0xd956, 0xd963, 0xd970, 0xd97c, 0xd989,
|
||||
0xd995, 0xd9a2, 0xd9ae, 0xd9bb, 0xd9c8, 0xd9d4,
|
||||
0xd9e1, 0xd9ed, 0xd9fa, 0xda06, 0xda13, 0xda1f,
|
||||
0xda2c, 0xda38, 0xda45, 0xda51, 0xda5e, 0xda6a,
|
||||
0xda77, 0xda84, 0xda90, 0xda9d, 0xdaa9, 0xdab6,
|
||||
0xdac2, 0xdacf, 0xdadb, 0xdae7, 0xdaf4, 0xdb00,
|
||||
0xdb0d, 0xdb19, 0xdb26, 0xdb32, 0xdb3f, 0xdb4b,
|
||||
0xdb58, 0xdb64, 0xdb71, 0xdb7d, 0xdb8a, 0xdb96,
|
||||
0xdba2, 0xdbaf, 0xdbbb, 0xdbc8, 0xdbd4, 0xdbe1,
|
||||
0xdbed, 0xdbf9, 0xdc06, 0xdc12, 0xdc1f, 0xdc2b,
|
||||
0xdc38, 0xdc44, 0xdc50, 0xdc5d, 0xdc69, 0xdc76,
|
||||
0xdc82, 0xdc8e, 0xdc9b, 0xdca7, 0xdcb3, 0xdcc0,
|
||||
0xdccc, 0xdcd9, 0xdce5, 0xdcf1, 0xdcfe, 0xdd0a,
|
||||
0xdd16, 0xdd23, 0xdd2f, 0xdd3b, 0xdd48, 0xdd54,
|
||||
0xdd60, 0xdd6d, 0xdd79, 0xdd85, 0xdd92, 0xdd9e,
|
||||
0xddaa, 0xddb7, 0xddc3, 0xddcf, 0xdddc, 0xdde8,
|
||||
0xddf4, 0xde01, 0xde0d, 0xde19, 0xde25, 0xde32,
|
||||
0xde3e, 0xde4a, 0xde57, 0xde63, 0xde6f, 0xde7b,
|
||||
0xde88, 0xde94, 0xdea0, 0xdeac, 0xdeb9, 0xdec5,
|
||||
0xded1, 0xdedd, 0xdeea, 0xdef6, 0xdf02, 0xdf0e,
|
||||
0xdf1b, 0xdf27, 0xdf33, 0xdf3f, 0xdf4c, 0xdf58,
|
||||
0xdf64, 0xdf70, 0xdf7c, 0xdf89, 0xdf95, 0xdfa1,
|
||||
0xdfad, 0xdfb9, 0xdfc6, 0xdfd2, 0xdfde, 0xdfea,
|
||||
0xdff6, 0xe003, 0xe00f, 0xe01b, 0xe027, 0xe033,
|
||||
0xe03f, 0xe04c, 0xe058, 0xe064, 0xe070, 0xe07c,
|
||||
0xe088, 0xe094, 0xe0a1, 0xe0ad, 0xe0b9, 0xe0c5,
|
||||
0xe0d1, 0xe0dd, 0xe0e9, 0xe0f5, 0xe102, 0xe10e,
|
||||
0xe11a, 0xe126, 0xe132, 0xe13e, 0xe14a, 0xe156,
|
||||
0xe162, 0xe16e, 0xe17b, 0xe187, 0xe193, 0xe19f,
|
||||
0xe1ab, 0xe1b7, 0xe1c3, 0xe1cf, 0xe1db, 0xe1e7,
|
||||
0xe1f3, 0xe1ff, 0xe20b, 0xe217, 0xe223, 0xe22f,
|
||||
0xe23c, 0xe248, 0xe254, 0xe260, 0xe26c, 0xe278,
|
||||
0xe284, 0xe290, 0xe29c, 0xe2a8, 0xe2b4, 0xe2c0,
|
||||
0xe2cc, 0xe2d8, 0xe2e4, 0xe2f0, 0xe2fc, 0xe308,
|
||||
0xe314, 0xe320, 0xe32c, 0xe338, 0xe344, 0xe350,
|
||||
0xe35c, 0xe368, 0xe374, 0xe380, 0xe38b, 0xe397,
|
||||
0xe3a3, 0xe3af, 0xe3bb, 0xe3c7, 0xe3d3, 0xe3df,
|
||||
0xe3eb, 0xe3f7, 0xe403, 0xe40f, 0xe41b, 0xe427,
|
||||
0xe433, 0xe43f, 0xe44a, 0xe456, 0xe462, 0xe46e,
|
||||
0xe47a, 0xe486, 0xe492, 0xe49e, 0xe4aa, 0xe4b6,
|
||||
0xe4c1, 0xe4cd, 0xe4d9, 0xe4e5, 0xe4f1, 0xe4fd,
|
||||
0xe509, 0xe515, 0xe520, 0xe52c, 0xe538, 0xe544,
|
||||
0xe550, 0xe55c, 0xe567, 0xe573, 0xe57f, 0xe58b,
|
||||
0xe597, 0xe5a3, 0xe5af, 0xe5ba, 0xe5c6, 0xe5d2,
|
||||
0xe5de, 0xe5ea, 0xe5f5, 0xe601, 0xe60d, 0xe619,
|
||||
0xe625, 0xe630, 0xe63c, 0xe648, 0xe654, 0xe660,
|
||||
0xe66b, 0xe677, 0xe683, 0xe68f, 0xe69a, 0xe6a6,
|
||||
0xe6b2, 0xe6be, 0xe6ca, 0xe6d5, 0xe6e1, 0xe6ed,
|
||||
0xe6f9, 0xe704, 0xe710, 0xe71c, 0xe727, 0xe733,
|
||||
0xe73f, 0xe74b, 0xe756, 0xe762, 0xe76e, 0xe77a,
|
||||
0xe785, 0xe791, 0xe79d, 0xe7a8, 0xe7b4, 0xe7c0,
|
||||
0xe7cb, 0xe7d7, 0xe7e3, 0xe7ef, 0xe7fa, 0xe806,
|
||||
0xe812, 0xe81d, 0xe829, 0xe835, 0xe840, 0xe84c,
|
||||
0xe858, 0xe863, 0xe86f, 0xe87b, 0xe886, 0xe892,
|
||||
0xe89e, 0xe8a9, 0xe8b5, 0xe8c0, 0xe8cc, 0xe8d8,
|
||||
0xe8e3, 0xe8ef, 0xe8fb, 0xe906, 0xe912, 0xe91d,
|
||||
0xe929, 0xe935, 0xe940, 0xe94c, 0xe958, 0xe963,
|
||||
0xe96f, 0xe97a, 0xe986, 0xe991, 0xe99d, 0xe9a9,
|
||||
0xe9b4, 0xe9c0, 0xe9cb, 0xe9d7, 0xe9e3, 0xe9ee,
|
||||
0xe9fa, 0xea05, 0xea11, 0xea1c, 0xea28, 0xea33,
|
||||
0xea3f, 0xea4a, 0xea56, 0xea62, 0xea6d, 0xea79,
|
||||
0xea84, 0xea90, 0xea9b, 0xeaa7, 0xeab2, 0xeabe,
|
||||
0xeac9, 0xead5, 0xeae0, 0xeaec, 0xeaf7, 0xeb03,
|
||||
0xeb0e, 0xeb1a, 0xeb25, 0xeb31, 0xeb3c, 0xeb48,
|
||||
0xeb53, 0xeb5f, 0xeb6a, 0xeb76, 0xeb81, 0xeb8d,
|
||||
0xeb98, 0xeba3, 0xebaf, 0xebba, 0xebc6, 0xebd1,
|
||||
0xebdd, 0xebe8, 0xebf4, 0xebff, 0xec0a, 0xec16,
|
||||
0xec21, 0xec2d, 0xec38, 0xec44, 0xec4f, 0xec5a,
|
||||
0xec66, 0xec71, 0xec7d, 0xec88, 0xec93, 0xec9f,
|
||||
0xecaa, 0xecb6, 0xecc1, 0xeccc, 0xecd8, 0xece3,
|
||||
0xecef, 0xecfa, 0xed05, 0xed11, 0xed1c, 0xed27,
|
||||
0xed33, 0xed3e, 0xed4a, 0xed55, 0xed60, 0xed6c,
|
||||
0xed77, 0xed82, 0xed8e, 0xed99, 0xeda4, 0xedb0,
|
||||
0xedbb, 0xedc6, 0xedd2, 0xeddd, 0xede8, 0xedf4,
|
||||
0xedff, 0xee0a, 0xee15, 0xee21, 0xee2c, 0xee37,
|
||||
0xee43, 0xee4e, 0xee59, 0xee65, 0xee70, 0xee7b,
|
||||
0xee86, 0xee92, 0xee9d, 0xeea8, 0xeeb3, 0xeebf,
|
||||
0xeeca, 0xeed5, 0xeee1, 0xeeec, 0xeef7, 0xef02,
|
||||
0xef0e, 0xef19, 0xef24, 0xef2f, 0xef3a, 0xef46,
|
||||
0xef51, 0xef5c, 0xef67, 0xef73, 0xef7e, 0xef89,
|
||||
0xef94, 0xef9f, 0xefab, 0xefb6, 0xefc1, 0xefcc,
|
||||
0xefd7, 0xefe3, 0xefee, 0xeff9, 0xf004, 0xf00f,
|
||||
0xf01b, 0xf026, 0xf031, 0xf03c, 0xf047, 0xf052,
|
||||
0xf05e, 0xf069, 0xf074, 0xf07f, 0xf08a, 0xf095,
|
||||
0xf0a1, 0xf0ac, 0xf0b7, 0xf0c2, 0xf0cd, 0xf0d8,
|
||||
0xf0e3, 0xf0ef, 0xf0fa, 0xf105, 0xf110, 0xf11b,
|
||||
0xf126, 0xf131, 0xf13c, 0xf147, 0xf153, 0xf15e,
|
||||
0xf169, 0xf174, 0xf17f, 0xf18a, 0xf195, 0xf1a0,
|
||||
0xf1ab, 0xf1b6, 0xf1c2, 0xf1cd, 0xf1d8, 0xf1e3,
|
||||
0xf1ee, 0xf1f9, 0xf204, 0xf20f, 0xf21a, 0xf225,
|
||||
0xf230, 0xf23b, 0xf246, 0xf251, 0xf25c, 0xf267,
|
||||
0xf272, 0xf27d, 0xf288, 0xf293, 0xf29f, 0xf2aa,
|
||||
0xf2b5, 0xf2c0, 0xf2cb, 0xf2d6, 0xf2e1, 0xf2ec,
|
||||
0xf2f7, 0xf302, 0xf30d, 0xf318, 0xf323, 0xf32e,
|
||||
0xf339, 0xf344, 0xf34f, 0xf35a, 0xf364, 0xf36f,
|
||||
0xf37a, 0xf385, 0xf390, 0xf39b, 0xf3a6, 0xf3b1,
|
||||
0xf3bc, 0xf3c7, 0xf3d2, 0xf3dd, 0xf3e8, 0xf3f3,
|
||||
0xf3fe, 0xf409, 0xf414, 0xf41f, 0xf42a, 0xf435,
|
||||
0xf43f, 0xf44a, 0xf455, 0xf460, 0xf46b, 0xf476,
|
||||
0xf481, 0xf48c, 0xf497, 0xf4a2, 0xf4ad, 0xf4b7,
|
||||
0xf4c2, 0xf4cd, 0xf4d8, 0xf4e3, 0xf4ee, 0xf4f9,
|
||||
0xf504, 0xf50f, 0xf519, 0xf524, 0xf52f, 0xf53a,
|
||||
0xf545, 0xf550, 0xf55b, 0xf565, 0xf570, 0xf57b,
|
||||
0xf586, 0xf591, 0xf59c, 0xf5a6, 0xf5b1, 0xf5bc,
|
||||
0xf5c7, 0xf5d2, 0xf5dd, 0xf5e7, 0xf5f2, 0xf5fd,
|
||||
0xf608, 0xf613, 0xf61d, 0xf628, 0xf633, 0xf63e,
|
||||
0xf649, 0xf653, 0xf65e, 0xf669, 0xf674, 0xf67f,
|
||||
0xf689, 0xf694, 0xf69f, 0xf6aa, 0xf6b4, 0xf6bf,
|
||||
0xf6ca, 0xf6d5, 0xf6e0, 0xf6ea, 0xf6f5, 0xf700,
|
||||
0xf70b, 0xf715, 0xf720, 0xf72b, 0xf736, 0xf740,
|
||||
0xf74b, 0xf756, 0xf760, 0xf76b, 0xf776, 0xf781,
|
||||
0xf78b, 0xf796, 0xf7a1, 0xf7ab, 0xf7b6, 0xf7c1,
|
||||
0xf7cc, 0xf7d6, 0xf7e1, 0xf7ec, 0xf7f6, 0xf801,
|
||||
0xf80c, 0xf816, 0xf821, 0xf82c, 0xf836, 0xf841,
|
||||
0xf84c, 0xf856, 0xf861, 0xf86c, 0xf876, 0xf881,
|
||||
0xf88c, 0xf896, 0xf8a1, 0xf8ac, 0xf8b6, 0xf8c1,
|
||||
0xf8cc, 0xf8d6, 0xf8e1, 0xf8ec, 0xf8f6, 0xf901,
|
||||
0xf90b, 0xf916, 0xf921, 0xf92b, 0xf936, 0xf941,
|
||||
0xf94b, 0xf956, 0xf960, 0xf96b, 0xf976, 0xf980,
|
||||
0xf98b, 0xf995, 0xf9a0, 0xf9aa, 0xf9b5, 0xf9c0,
|
||||
0xf9ca, 0xf9d5, 0xf9df, 0xf9ea, 0xf9f4, 0xf9ff,
|
||||
0xfa0a, 0xfa14, 0xfa1f, 0xfa29, 0xfa34, 0xfa3e,
|
||||
0xfa49, 0xfa53, 0xfa5e, 0xfa69, 0xfa73, 0xfa7e,
|
||||
0xfa88, 0xfa93, 0xfa9d, 0xfaa8, 0xfab2, 0xfabd,
|
||||
0xfac7, 0xfad2, 0xfadc, 0xfae7, 0xfaf1, 0xfafc,
|
||||
0xfb06, 0xfb11, 0xfb1b, 0xfb26, 0xfb30, 0xfb3b,
|
||||
0xfb45, 0xfb50, 0xfb5a, 0xfb65, 0xfb6f, 0xfb7a,
|
||||
0xfb84, 0xfb8f, 0xfb99, 0xfba4, 0xfbae, 0xfbb8,
|
||||
0xfbc3, 0xfbcd, 0xfbd8, 0xfbe2, 0xfbed, 0xfbf7,
|
||||
0xfc02, 0xfc0c, 0xfc16, 0xfc21, 0xfc2b, 0xfc36,
|
||||
0xfc40, 0xfc4b, 0xfc55, 0xfc5f, 0xfc6a, 0xfc74,
|
||||
0xfc7f, 0xfc89, 0xfc93, 0xfc9e, 0xfca8, 0xfcb3,
|
||||
0xfcbd, 0xfcc7, 0xfcd2, 0xfcdc, 0xfce7, 0xfcf1,
|
||||
0xfcfb, 0xfd06, 0xfd10, 0xfd1a, 0xfd25, 0xfd2f,
|
||||
0xfd3a, 0xfd44, 0xfd4e, 0xfd59, 0xfd63, 0xfd6d,
|
||||
0xfd78, 0xfd82, 0xfd8c, 0xfd97, 0xfda1, 0xfdab,
|
||||
0xfdb6, 0xfdc0, 0xfdca, 0xfdd5, 0xfddf, 0xfde9,
|
||||
0xfdf4, 0xfdfe, 0xfe08, 0xfe13, 0xfe1d, 0xfe27,
|
||||
0xfe32, 0xfe3c, 0xfe46, 0xfe50, 0xfe5b, 0xfe65,
|
||||
0xfe6f, 0xfe7a, 0xfe84, 0xfe8e, 0xfe98, 0xfea3,
|
||||
0xfead, 0xfeb7, 0xfec1, 0xfecc, 0xfed6, 0xfee0,
|
||||
0xfeeb, 0xfef5, 0xfeff, 0xff09, 0xff14, 0xff1e,
|
||||
0xff28, 0xff32, 0xff3c, 0xff47, 0xff51, 0xff5b,
|
||||
0xff65, 0xff70, 0xff7a, 0xff84, 0xff8e, 0xff98,
|
||||
0xffa3, 0xffad, 0xffb7, 0xffc1, 0xffcc, 0xffd6,
|
||||
0xffe0, 0xffea, 0xfff4, 0xffff
|
||||
};
|
||||
|
||||
// max value is pi/4
|
||||
constexpr double SCALING_FACTOR = 4. / M_PI * 0xFFFF;
|
||||
|
||||
inline double atan2_lookup(double y, double x)
|
||||
{
|
||||
if (std::abs(x) < std::numeric_limits<double>::epsilon())
|
||||
{
|
||||
if (y >= 0.)
|
||||
{
|
||||
return M_PI / 2.;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -M_PI / 2.;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned octant = 0;
|
||||
|
||||
if (x < 0.)
|
||||
{
|
||||
octant = 1;
|
||||
x = -x;
|
||||
}
|
||||
if (y < 0.)
|
||||
{
|
||||
octant |= 2;
|
||||
y = -y;
|
||||
}
|
||||
|
||||
double t = y / x;
|
||||
if (t > 1.0)
|
||||
{
|
||||
octant |= 4;
|
||||
t = 1.0 / t;
|
||||
}
|
||||
|
||||
double angle = atan_table[(unsigned)(t * 4095)] / SCALING_FACTOR;
|
||||
|
||||
switch (octant)
|
||||
{
|
||||
case 0:
|
||||
break;
|
||||
case 1:
|
||||
angle = M_PI - angle;
|
||||
break;
|
||||
case 2:
|
||||
angle = -angle;
|
||||
break;
|
||||
case 3:
|
||||
angle = -M_PI + angle;
|
||||
break;
|
||||
case 4:
|
||||
angle = M_PI / 2.0 - angle;
|
||||
break;
|
||||
case 5:
|
||||
angle = M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 6:
|
||||
angle = -M_PI / 2.0 + angle;
|
||||
break;
|
||||
case 7:
|
||||
angle = -M_PI / 2.0 - angle;
|
||||
break;
|
||||
}
|
||||
return angle;
|
||||
}
|
||||
|
||||
#endif // TRIGONOMETRY_TABLES_H
|
@ -30,6 +30,34 @@ Feature: Car - Turn restrictions
|
||||
| s | n | sj,nj |
|
||||
| s | e | sj,ej |
|
||||
|
||||
@no_turning
|
||||
Scenario: Car - No straight on
|
||||
Given the node map
|
||||
| a | b | j | d | e |
|
||||
| v | | | | z |
|
||||
| | w | x | y | |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
| ab | no |
|
||||
| bj | no |
|
||||
| jd | no |
|
||||
| de | no |
|
||||
| av | yes |
|
||||
| vw | yes |
|
||||
| wx | yes |
|
||||
| xy | yes |
|
||||
| yz | yes |
|
||||
| ze | yes |
|
||||
|
||||
And the relations
|
||||
| type | way:from | way:to | node:via | restriction |
|
||||
| restriction | bj | jd | j | no_straight_on |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| a | e | av,vw,wx,xy,yz,ze |
|
||||
|
||||
@no_turning
|
||||
Scenario: Car - No right turn
|
||||
Given the node map
|
||||
@ -248,4 +276,4 @@ Feature: Car - Turn restrictions
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
| s | a | sj,aj |
|
||||
| s | b | sj,bj |
|
||||
| s | b | sj,bj |
|
||||
|
@ -15,5 +15,5 @@ Feature: osrm-routed command line options: invalid options
|
||||
When I run "osrm-routed over-the-rainbow.osrm"
|
||||
Then stdout should contain "over-the-rainbow.osrm"
|
||||
And stderr should contain "exception"
|
||||
And stderr should contain "does not exist"
|
||||
And stderr should contain "not found"
|
||||
And it should exit with code 1
|
||||
|
@ -93,10 +93,12 @@ def route_status response
|
||||
end
|
||||
|
||||
def extract_instruction_list instructions, index, postfix=nil
|
||||
instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
|
||||
map { |r| r[index] }.
|
||||
map { |r| (r=="" || r==nil) ? '""' : "#{r}#{postfix}" }.
|
||||
join(',')
|
||||
if instructions
|
||||
instructions.reject { |r| r[0].to_s=="#{DESTINATION_REACHED}" }.
|
||||
map { |r| r[index] }.
|
||||
map { |r| (r=="" || r==nil) ? '""' : "#{r}#{postfix}" }.
|
||||
join(',')
|
||||
end
|
||||
end
|
||||
|
||||
def way_list instructions
|
||||
@ -112,33 +114,35 @@ def bearing_list instructions
|
||||
end
|
||||
|
||||
def turn_list instructions
|
||||
types = {
|
||||
0 => :none,
|
||||
1 => :straight,
|
||||
2 => :slight_right,
|
||||
3 => :right,
|
||||
4 => :sharp_right,
|
||||
5 => :u_turn,
|
||||
6 => :sharp_left,
|
||||
7 => :left,
|
||||
8 => :slight_left,
|
||||
9 => :via,
|
||||
10 => :head,
|
||||
11 => :enter_roundabout,
|
||||
12 => :leave_roundabout,
|
||||
13 => :stay_roundabout,
|
||||
14 => :start_end_of_street,
|
||||
15 => :destination,
|
||||
16 => :enter_contraflow,
|
||||
17 => :leave_contraflow
|
||||
}
|
||||
# replace instructions codes with strings
|
||||
# "11-3" (enter roundabout and leave a 3rd exit) gets converted to "enter_roundabout-3"
|
||||
instructions.map do |r|
|
||||
r[0].to_s.gsub(/^\d*/) do |match|
|
||||
types[match.to_i].to_s
|
||||
end
|
||||
end.join(',')
|
||||
if instructions
|
||||
types = {
|
||||
0 => :none,
|
||||
1 => :straight,
|
||||
2 => :slight_right,
|
||||
3 => :right,
|
||||
4 => :sharp_right,
|
||||
5 => :u_turn,
|
||||
6 => :sharp_left,
|
||||
7 => :left,
|
||||
8 => :slight_left,
|
||||
9 => :via,
|
||||
10 => :head,
|
||||
11 => :enter_roundabout,
|
||||
12 => :leave_roundabout,
|
||||
13 => :stay_roundabout,
|
||||
14 => :start_end_of_street,
|
||||
15 => :destination,
|
||||
16 => :enter_contraflow,
|
||||
17 => :leave_contraflow
|
||||
}
|
||||
# replace instructions codes with strings
|
||||
# "11-3" (enter roundabout and leave a 3rd exit) gets converted to "enter_roundabout-3"
|
||||
instructions.map do |r|
|
||||
r[0].to_s.gsub(/^\d*/) do |match|
|
||||
types[match.to_i].to_s
|
||||
end
|
||||
end.join(',')
|
||||
end
|
||||
end
|
||||
|
||||
def mode_list instructions
|
||||
@ -151,4 +155,4 @@ end
|
||||
|
||||
def distance_list instructions
|
||||
extract_instruction_list instructions, 2, "m"
|
||||
end
|
||||
end
|
||||
|
@ -6,10 +6,11 @@ Feature: Testbot - oneways
|
||||
|
||||
Scenario: Routing on a oneway roundabout
|
||||
Given the node map
|
||||
| | d | c | |
|
||||
| e | | | b |
|
||||
| f | | | a |
|
||||
| | g | h | |
|
||||
| x | | | v | | |
|
||||
| | | d | c | | |
|
||||
| | e | | | b | |
|
||||
| | f | | | a | |
|
||||
| | | g | h | | |
|
||||
|
||||
And the ways
|
||||
| nodes | oneway |
|
||||
@ -21,6 +22,7 @@ Feature: Testbot - oneways
|
||||
| fg | yes |
|
||||
| gh | yes |
|
||||
| ha | yes |
|
||||
| vx | yes |
|
||||
|
||||
When I route I should get
|
||||
| from | to | route |
|
||||
@ -39,4 +41,4 @@ Feature: Testbot - oneways
|
||||
| f | e | fg,gh,ha,ab,bc,cd,de |
|
||||
| g | f | gh,ha,ab,bc,cd,de,ef |
|
||||
| h | g | ha,ab,bc,cd,de,ef,fg |
|
||||
| a | h | ab,bc,cd,de,ef,fg,gh |
|
||||
| a | h | ab,bc,cd,de,ef,fg,gh |
|
||||
|
@ -29,7 +29,7 @@ Feature: Projection to nearest point on road
|
||||
| a | d | abc | NE | 45 | 1000m +-7 |
|
||||
| d | a | abc | SW | 225 | 1000m +-7 |
|
||||
| c | d | abc | SW | 225 | 1000m +-7 |
|
||||
| d | c | abc | NE | 45 +-1 | 1000m +-7 |
|
||||
| d | c | abc | NE | 45 +-2 | 1000m +-7 |
|
||||
|
||||
Scenario: Projection onto way at high latitudes, no distance
|
||||
When I route I should get
|
||||
|
@ -35,7 +35,6 @@ Feature: Roundabout Instructions
|
||||
| v | t | vd,tb | head,enter_roundabout-2,destination |
|
||||
| v | u | vd,uc | head,enter_roundabout-3,destination |
|
||||
|
||||
@bug
|
||||
Scenario: Testbot - Roundabout with oneway links
|
||||
Given the node map
|
||||
| | | p | o | | |
|
||||
@ -74,4 +73,4 @@ Feature: Roundabout Instructions
|
||||
| p | i | ph,ai | head,enter_roundabout-1,destination |
|
||||
| p | k | ph,ck | head,enter_roundabout-2,destination |
|
||||
| p | m | ph,em | head,enter_roundabout-3,destination |
|
||||
| p | o | ph,go | head,enter_roundabout-4,destination |
|
||||
| p | o | ph,go | head,enter_roundabout-4,destination |
|
||||
|
@ -27,7 +27,7 @@ Feature: Status messages
|
||||
| nodes |
|
||||
| ab |
|
||||
| cd |
|
||||
|
||||
|
||||
When I route I should get
|
||||
| from | to | route | status | message |
|
||||
| a | b | ab | 0 | Found route between points |
|
||||
@ -64,4 +64,4 @@ Feature: Status messages
|
||||
| viaroute/loc=1,1&loc=1,1 | 400 | Query string malformed close to position 9 |
|
||||
| viaroute/loc=1,1&loc=1,1,1 | 400 | Query string malformed close to position 9 |
|
||||
| viaroute/loc=1,1&loc=x | 400 | Query string malformed close to position 9 |
|
||||
| viaroute/loc=1,1&loc=x,y | 400 | Query string malformed close to position 9 |
|
||||
| viaroute/loc=1,1&loc=x,y | 400 | Query string malformed close to position 9 |
|
||||
|
@ -438,6 +438,7 @@ int main(int argc, char *argv[])
|
||||
|
||||
// every target needs to be valid
|
||||
BOOST_ASSERT(current_edge.target < max_used_node_id);
|
||||
#ifndef NDEBUG
|
||||
if (current_edge.data.distance <= 0)
|
||||
{
|
||||
SimpleLogger().Write(logWARNING)
|
||||
@ -450,6 +451,7 @@ int main(int argc, char *argv[])
|
||||
<< node_array.size() - 1;
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
hsgr_output_stream.write((char *)¤t_edge,
|
||||
sizeof(StaticGraph<EdgeData>::EdgeArrayEntry));
|
||||
++number_of_used_edges;
|
||||
|
Loading…
Reference in New Issue
Block a user