2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/extraction_containers.hpp"
|
2016-05-12 12:50:10 -04:00
|
|
|
#include "extractor/extraction_segment.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "extractor/extraction_way.hpp"
|
|
|
|
|
|
|
|
#include "util/coordinate_calculation.hpp"
|
|
|
|
|
2016-01-28 08:27:05 -05:00
|
|
|
#include "util/exception.hpp"
|
2016-12-06 15:30:46 -05:00
|
|
|
#include "util/exception_utils.hpp"
|
2016-01-02 11:13:44 -05:00
|
|
|
#include "util/fingerprint.hpp"
|
2016-12-06 15:30:46 -05:00
|
|
|
#include "util/log.hpp"
|
2017-01-19 09:14:30 -05:00
|
|
|
#include "util/name_table.hpp"
|
2016-05-27 15:05:04 -04:00
|
|
|
#include "util/timing_util.hpp"
|
2014-01-09 10:13:35 -05:00
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
#include "storage/io.hpp"
|
|
|
|
|
2014-01-09 10:13:35 -05:00
|
|
|
#include <boost/assert.hpp>
|
|
|
|
#include <boost/filesystem.hpp>
|
|
|
|
#include <boost/filesystem/fstream.hpp>
|
2015-11-24 19:33:19 -05:00
|
|
|
#include <boost/numeric/conversion/cast.hpp>
|
2016-01-03 12:55:42 -05:00
|
|
|
#include <boost/ref.hpp>
|
2015-05-29 20:28:29 -04:00
|
|
|
|
2014-01-09 10:13:35 -05:00
|
|
|
#include <stxxl/sort>
|
|
|
|
|
2014-05-06 12:48:18 -04:00
|
|
|
#include <chrono>
|
2014-05-09 13:26:37 -04:00
|
|
|
#include <limits>
|
2016-10-11 17:02:20 -04:00
|
|
|
#include <mutex>
|
2016-12-06 15:30:46 -05:00
|
|
|
#include <sstream>
|
2014-05-06 12:48:18 -04:00
|
|
|
|
2016-01-21 06:52:35 -05:00
|
|
|
namespace
|
|
|
|
{
|
2016-07-05 14:08:21 -04:00
|
|
|
namespace oe = osrm::extractor;
|
|
|
|
|
2016-01-21 06:52:35 -05:00
|
|
|
// Needed for STXXL comparison - STXXL requires max_value(), min_value(), so we can not use
|
|
|
|
// std::less<OSMNodeId>{}. Anonymous namespace to keep translation unit local.
|
|
|
|
struct OSMNodeIDSTXXLLess
|
|
|
|
{
|
|
|
|
using value_type = OSMNodeID;
|
|
|
|
bool operator()(const value_type left, const value_type right) const { return left < right; }
|
|
|
|
value_type max_value() { return MAX_OSM_NODEID; }
|
|
|
|
value_type min_value() { return MIN_OSM_NODEID; }
|
|
|
|
};
|
2016-07-05 14:08:21 -04:00
|
|
|
|
|
|
|
struct CmpEdgeByOSMStartID
|
|
|
|
{
|
|
|
|
using value_type = oe::InternalExtractorEdge;
|
|
|
|
bool operator()(const value_type &lhs, const value_type &rhs) const
|
|
|
|
{
|
|
|
|
return lhs.result.osm_source_id < rhs.result.osm_source_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_type max_value() { return value_type::max_osm_value(); }
|
|
|
|
value_type min_value() { return value_type::min_osm_value(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CmpEdgeByOSMTargetID
|
|
|
|
{
|
|
|
|
using value_type = oe::InternalExtractorEdge;
|
|
|
|
bool operator()(const value_type &lhs, const value_type &rhs) const
|
|
|
|
{
|
|
|
|
return lhs.result.osm_target_id < rhs.result.osm_target_id;
|
|
|
|
}
|
|
|
|
|
|
|
|
value_type max_value() { return value_type::max_osm_value(); }
|
|
|
|
value_type min_value() { return value_type::min_osm_value(); }
|
|
|
|
};
|
|
|
|
|
|
|
|
struct CmpEdgeByInternalSourceTargetAndName
|
|
|
|
{
|
|
|
|
using value_type = oe::InternalExtractorEdge;
|
|
|
|
bool operator()(const value_type &lhs, const value_type &rhs) const
|
|
|
|
{
|
|
|
|
if (lhs.result.source != rhs.result.source)
|
|
|
|
return lhs.result.source < rhs.result.source;
|
|
|
|
|
2016-10-11 17:02:20 -04:00
|
|
|
if (lhs.result.source == SPECIAL_NODEID)
|
|
|
|
return false;
|
|
|
|
|
2016-07-05 14:08:21 -04:00
|
|
|
if (lhs.result.target != rhs.result.target)
|
|
|
|
return lhs.result.target < rhs.result.target;
|
|
|
|
|
2016-10-11 17:02:20 -04:00
|
|
|
if (lhs.result.target == SPECIAL_NODEID)
|
2016-07-05 14:08:21 -04:00
|
|
|
return false;
|
|
|
|
|
|
|
|
if (lhs.result.name_id == rhs.result.name_id)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (lhs.result.name_id == EMPTY_NAMEID)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
if (rhs.result.name_id == EMPTY_NAMEID)
|
|
|
|
return true;
|
|
|
|
|
2016-10-11 17:02:20 -04:00
|
|
|
std::lock_guard<std::mutex> lock(mutex);
|
2016-07-05 14:08:21 -04:00
|
|
|
BOOST_ASSERT(!name_offsets.empty() && name_offsets.back() == name_data.size());
|
|
|
|
const oe::ExtractionContainers::STXXLNameCharData::const_iterator data = name_data.begin();
|
|
|
|
return std::lexicographical_compare(data + name_offsets[lhs.result.name_id],
|
|
|
|
data + name_offsets[lhs.result.name_id + 1],
|
|
|
|
data + name_offsets[rhs.result.name_id],
|
|
|
|
data + name_offsets[rhs.result.name_id + 1]);
|
|
|
|
}
|
|
|
|
|
|
|
|
value_type max_value() { return value_type::max_internal_value(); }
|
|
|
|
value_type min_value() { return value_type::min_internal_value(); }
|
|
|
|
|
2016-10-28 17:45:05 -04:00
|
|
|
std::mutex &mutex;
|
2016-07-05 14:08:21 -04:00
|
|
|
const oe::ExtractionContainers::STXXLNameCharData &name_data;
|
|
|
|
const oe::ExtractionContainers::STXXLNameOffsets &name_offsets;
|
|
|
|
};
|
2016-01-21 06:52:35 -05:00
|
|
|
}
|
|
|
|
|
2016-01-05 10:51:13 -05:00
|
|
|
namespace osrm
|
|
|
|
{
|
|
|
|
namespace extractor
|
|
|
|
{
|
|
|
|
|
2014-05-09 10:17:31 -04:00
|
|
|
ExtractionContainers::ExtractionContainers()
|
|
|
|
{
|
|
|
|
// Check if stxxl can be instantiated
|
2014-01-09 10:13:35 -05:00
|
|
|
stxxl::vector<unsigned> dummy_vector;
|
2016-07-05 14:08:21 -04:00
|
|
|
|
2016-09-13 10:22:22 -04:00
|
|
|
// Insert four empty strings offsets for name, ref, destination and pronunciation
|
2016-09-13 07:45:09 -04:00
|
|
|
name_offsets.push_back(0);
|
2016-07-05 14:08:21 -04:00
|
|
|
name_offsets.push_back(0);
|
|
|
|
name_offsets.push_back(0);
|
|
|
|
name_offsets.push_back(0);
|
|
|
|
// Insert the total length sentinel (corresponds to the next name string offset)
|
|
|
|
name_offsets.push_back(0);
|
2014-01-09 10:13:35 -05:00
|
|
|
}
|
|
|
|
|
2016-11-10 18:24:02 -05:00
|
|
|
void ExtractionContainers::FlushVectors()
|
|
|
|
{
|
|
|
|
used_node_id_list.flush();
|
|
|
|
all_nodes_list.flush();
|
|
|
|
all_edges_list.flush();
|
|
|
|
name_char_data.flush();
|
|
|
|
name_offsets.flush();
|
|
|
|
restrictions_list.flush();
|
|
|
|
way_start_end_id_list.flush();
|
|
|
|
}
|
|
|
|
|
2015-04-10 10:10:00 -04:00
|
|
|
/**
|
|
|
|
* Processes the collected data and serializes it.
|
|
|
|
* At this point nodes are still referenced by their OSM id.
|
|
|
|
*
|
|
|
|
* - map start-end nodes of ways to ways used int restrictions to compute compressed
|
|
|
|
* trippe representation
|
|
|
|
* - filter nodes list to nodes that are referenced by ways
|
|
|
|
* - merge edges with nodes to include location of start/end points and serialize
|
|
|
|
*
|
|
|
|
*/
|
2016-07-11 11:44:58 -04:00
|
|
|
void ExtractionContainers::PrepareData(ScriptingEnvironment &scripting_environment,
|
|
|
|
const std::string &output_file_name,
|
2015-05-09 11:21:36 -04:00
|
|
|
const std::string &restrictions_file_name,
|
2016-06-30 03:31:08 -04:00
|
|
|
const std::string &name_file_name)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-03-04 05:52:40 -05:00
|
|
|
storage::io::FileWriter file_out(output_file_name,
|
|
|
|
storage::io::FileWriter::GenerateFingerprint);
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-11-10 18:24:02 -05:00
|
|
|
FlushVectors();
|
|
|
|
|
2016-07-19 07:13:52 -04:00
|
|
|
PrepareNodes();
|
2017-03-04 05:52:40 -05:00
|
|
|
WriteNodes(file_out);
|
2016-07-19 07:13:52 -04:00
|
|
|
PrepareEdges(scripting_environment);
|
2017-03-04 05:52:40 -05:00
|
|
|
WriteEdges(file_out);
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-07-19 07:13:52 -04:00
|
|
|
PrepareRestrictions();
|
|
|
|
WriteRestrictions(restrictions_file_name);
|
|
|
|
WriteCharData(name_file_name);
|
2016-06-21 04:41:08 -04:00
|
|
|
}
|
|
|
|
|
2016-07-05 14:08:21 -04:00
|
|
|
void ExtractionContainers::WriteCharData(const std::string &file_name)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "writing street name index ... ";
|
2016-05-13 13:18:00 -04:00
|
|
|
TIMER_START(write_index);
|
2017-01-19 09:14:30 -05:00
|
|
|
boost::filesystem::ofstream file(file_name, std::ios::binary);
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2017-04-08 08:18:20 -04:00
|
|
|
// TODO wrap this in a FileWriter
|
|
|
|
const auto fingerprint = util::FingerPrint::GetValid();
|
|
|
|
file.write(reinterpret_cast<const char *>(&fingerprint), sizeof(util::FingerPrint));
|
|
|
|
|
2017-01-19 09:14:30 -05:00
|
|
|
const util::NameTable::IndexedData indexed_data;
|
|
|
|
indexed_data.write(file, name_offsets.begin(), name_offsets.end(), name_char_data.begin());
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-05-13 13:18:00 -04:00
|
|
|
TIMER_STOP(write_index);
|
2016-12-06 15:30:46 -05:00
|
|
|
log << "ok, after " << TIMER_SEC(write_index) << "s";
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
void ExtractionContainers::PrepareNodes()
|
|
|
|
{
|
2015-09-10 06:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting used nodes ... " << std::flush;
|
|
|
|
TIMER_START(sorting_used_nodes);
|
|
|
|
stxxl::sort(
|
|
|
|
used_node_id_list.begin(), used_node_id_list.end(), OSMNodeIDSTXXLLess(), stxxl_memory);
|
|
|
|
TIMER_STOP(sorting_used_nodes);
|
|
|
|
log << "ok, after " << TIMER_SEC(sorting_used_nodes) << "s";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Erasing duplicate nodes ... " << std::flush;
|
|
|
|
TIMER_START(erasing_dups);
|
|
|
|
auto new_end = std::unique(used_node_id_list.begin(), used_node_id_list.end());
|
|
|
|
used_node_id_list.resize(new_end - used_node_id_list.begin());
|
|
|
|
TIMER_STOP(erasing_dups);
|
|
|
|
log << "ok, after " << TIMER_SEC(erasing_dups) << "s";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting all nodes ... " << std::flush;
|
|
|
|
TIMER_START(sorting_nodes);
|
|
|
|
stxxl::sort(all_nodes_list.begin(),
|
|
|
|
all_nodes_list.end(),
|
|
|
|
ExternalMemoryNodeSTXXLCompare(),
|
|
|
|
stxxl_memory);
|
|
|
|
TIMER_STOP(sorting_nodes);
|
|
|
|
log << "ok, after " << TIMER_SEC(sorting_nodes) << "s";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Building node id map ... " << std::flush;
|
|
|
|
TIMER_START(id_map);
|
|
|
|
external_to_internal_node_id_map.reserve(used_node_id_list.size());
|
|
|
|
auto node_iter = all_nodes_list.begin();
|
|
|
|
auto ref_iter = used_node_id_list.begin();
|
|
|
|
const auto all_nodes_list_end = all_nodes_list.end();
|
|
|
|
const auto used_node_id_list_end = used_node_id_list.end();
|
|
|
|
// Note: despite being able to handle 64 bit OSM node ids, we can't
|
|
|
|
// handle > uint32_t actual usable nodes. This should be OK for a while
|
|
|
|
// because we usually route on a *lot* less than 2^32 of the OSM
|
|
|
|
// graph nodes.
|
|
|
|
std::uint64_t internal_id = 0;
|
|
|
|
|
|
|
|
// compute the intersection of nodes that were referenced and nodes we actually have
|
|
|
|
while (node_iter != all_nodes_list_end && ref_iter != used_node_id_list_end)
|
2015-09-10 06:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
if (node_iter->node_id < *ref_iter)
|
|
|
|
{
|
|
|
|
node_iter++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (node_iter->node_id > *ref_iter)
|
|
|
|
{
|
|
|
|
ref_iter++;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
BOOST_ASSERT(node_iter->node_id == *ref_iter);
|
|
|
|
external_to_internal_node_id_map[*ref_iter] = static_cast<NodeID>(internal_id++);
|
2015-09-10 06:21:36 -04:00
|
|
|
node_iter++;
|
2016-12-06 15:30:46 -05:00
|
|
|
ref_iter++;
|
2015-09-10 06:21:36 -04:00
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
if (internal_id > std::numeric_limits<NodeID>::max())
|
2015-09-10 06:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
throw util::exception("There are too many nodes remaining after filtering, OSRM only "
|
|
|
|
"supports 2^32 unique nodes, but there were " +
|
|
|
|
std::to_string(internal_id) + SOURCE_REF);
|
2015-09-10 06:21:36 -04:00
|
|
|
}
|
2017-04-08 10:06:34 -04:00
|
|
|
max_internal_node_id = boost::numeric_cast<std::uint64_t>(internal_id);
|
2016-12-06 15:30:46 -05:00
|
|
|
TIMER_STOP(id_map);
|
|
|
|
log << "ok, after " << TIMER_SEC(id_map) << "s";
|
2015-09-10 06:21:36 -04:00
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
|
|
|
|
2016-07-11 11:44:58 -04:00
|
|
|
void ExtractionContainers::PrepareEdges(ScriptingEnvironment &scripting_environment)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
|
|
|
// Sort edges by start.
|
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting edges by start ... " << std::flush;
|
|
|
|
TIMER_START(sort_edges_by_start);
|
|
|
|
stxxl::sort(
|
|
|
|
all_edges_list.begin(), all_edges_list.end(), CmpEdgeByOSMStartID(), stxxl_memory);
|
|
|
|
TIMER_STOP(sort_edges_by_start);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_edges_by_start) << "s";
|
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Setting start coords ... " << std::flush;
|
|
|
|
TIMER_START(set_start_coords);
|
|
|
|
// Traverse list of edges and nodes in parallel and set start coord
|
|
|
|
auto node_iterator = all_nodes_list.begin();
|
|
|
|
auto edge_iterator = all_edges_list.begin();
|
2015-05-24 11:25:38 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
const auto all_edges_list_end = all_edges_list.end();
|
|
|
|
const auto all_nodes_list_end = all_nodes_list.end();
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
while (edge_iterator != all_edges_list_end && node_iterator != all_nodes_list_end)
|
|
|
|
{
|
|
|
|
if (edge_iterator->result.osm_source_id < node_iterator->node_id)
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Found invalid node reference "
|
|
|
|
<< edge_iterator->result.source;
|
|
|
|
edge_iterator->result.source = SPECIAL_NODEID;
|
|
|
|
++edge_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (edge_iterator->result.osm_source_id > node_iterator->node_id)
|
|
|
|
{
|
|
|
|
node_iterator++;
|
|
|
|
continue;
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
// remove loops
|
|
|
|
if (edge_iterator->result.osm_source_id == edge_iterator->result.osm_target_id)
|
|
|
|
{
|
|
|
|
edge_iterator->result.source = SPECIAL_NODEID;
|
|
|
|
edge_iterator->result.target = SPECIAL_NODEID;
|
|
|
|
++edge_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2015-10-02 11:03:35 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
BOOST_ASSERT(edge_iterator->result.osm_source_id == node_iterator->node_id);
|
2015-05-24 11:25:38 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
// assign new node id
|
|
|
|
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
|
|
|
|
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
|
|
|
|
edge_iterator->result.source = id_iter->second;
|
|
|
|
|
|
|
|
edge_iterator->source_coordinate.lat = node_iterator->lat;
|
|
|
|
edge_iterator->source_coordinate.lon = node_iterator->lon;
|
2013-11-13 15:23:44 -05:00
|
|
|
++edge_iterator;
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2015-05-24 11:25:38 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
// Remove all remaining edges. They are invalid because there are no corresponding nodes for
|
|
|
|
// them. This happens when using osmosis with bbox or polygon to extract smaller areas.
|
|
|
|
auto markSourcesInvalid = [](InternalExtractorEdge &edge) {
|
|
|
|
util::Log(logDEBUG) << "Found invalid node reference " << edge.result.source;
|
|
|
|
edge.result.source = SPECIAL_NODEID;
|
|
|
|
edge.result.osm_source_id = SPECIAL_OSM_NODEID;
|
|
|
|
};
|
|
|
|
std::for_each(edge_iterator, all_edges_list_end, markSourcesInvalid);
|
|
|
|
TIMER_STOP(set_start_coords);
|
|
|
|
log << "ok, after " << TIMER_SEC(set_start_coords) << "s";
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
// Sort Edges by target
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting edges by target ... " << std::flush;
|
|
|
|
TIMER_START(sort_edges_by_target);
|
|
|
|
stxxl::sort(
|
|
|
|
all_edges_list.begin(), all_edges_list.end(), CmpEdgeByOSMTargetID(), stxxl_memory);
|
|
|
|
TIMER_STOP(sort_edges_by_target);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_edges_by_target) << "s";
|
|
|
|
}
|
2015-05-29 20:28:29 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
// Compute edge weights
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Computing edge weights ... " << std::flush;
|
|
|
|
TIMER_START(compute_weights);
|
|
|
|
auto node_iterator = all_nodes_list.begin();
|
|
|
|
auto edge_iterator = all_edges_list.begin();
|
|
|
|
const auto all_edges_list_end_ = all_edges_list.end();
|
|
|
|
const auto all_nodes_list_end_ = all_nodes_list.end();
|
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
const auto weight_multiplier =
|
2017-01-17 03:24:52 -05:00
|
|
|
scripting_environment.GetProfileProperties().GetWeightMultiplier();
|
2016-05-12 12:50:10 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
while (edge_iterator != all_edges_list_end_ && node_iterator != all_nodes_list_end_)
|
|
|
|
{
|
|
|
|
// skip all invalid edges
|
|
|
|
if (edge_iterator->result.source == SPECIAL_NODEID)
|
2015-05-24 11:25:38 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
++edge_iterator;
|
|
|
|
continue;
|
2015-05-12 19:26:54 -04:00
|
|
|
}
|
2015-05-24 11:25:38 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
if (edge_iterator->result.osm_target_id < node_iterator->node_id)
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Found invalid node reference "
|
|
|
|
<< static_cast<uint64_t>(edge_iterator->result.osm_target_id);
|
|
|
|
edge_iterator->result.target = SPECIAL_NODEID;
|
|
|
|
++edge_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (edge_iterator->result.osm_target_id > node_iterator->node_id)
|
|
|
|
{
|
|
|
|
++node_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2015-05-24 11:25:38 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
BOOST_ASSERT(edge_iterator->result.osm_target_id == node_iterator->node_id);
|
|
|
|
BOOST_ASSERT(edge_iterator->source_coordinate.lat !=
|
|
|
|
util::FixedLatitude{std::numeric_limits<std::int32_t>::min()});
|
|
|
|
BOOST_ASSERT(edge_iterator->source_coordinate.lon !=
|
|
|
|
util::FixedLongitude{std::numeric_limits<std::int32_t>::min()});
|
|
|
|
|
2017-03-29 04:33:49 -04:00
|
|
|
util::Coordinate source_coord(edge_iterator->source_coordinate);
|
|
|
|
util::Coordinate target_coord{node_iterator->lon, node_iterator->lat};
|
2016-05-12 12:50:10 -04:00
|
|
|
|
2017-03-29 04:33:49 -04:00
|
|
|
// flip source and target coordinates if segment is in backward direction only
|
|
|
|
if (!edge_iterator->result.forward && edge_iterator->result.backward)
|
|
|
|
std::swap(source_coord, target_coord);
|
2016-05-12 12:50:10 -04:00
|
|
|
|
2017-03-29 04:33:49 -04:00
|
|
|
const auto distance =
|
|
|
|
util::coordinate_calculation::greatCircleDistance(source_coord, target_coord);
|
|
|
|
const auto weight = edge_iterator->weight_data(distance);
|
|
|
|
const auto duration = edge_iterator->duration_data(distance);
|
|
|
|
|
|
|
|
ExtractionSegment segment(source_coord, target_coord, distance, weight, duration);
|
|
|
|
scripting_environment.ProcessSegment(segment);
|
2016-12-06 15:30:46 -05:00
|
|
|
|
|
|
|
auto &edge = edge_iterator->result;
|
2017-03-29 04:33:49 -04:00
|
|
|
edge.weight = std::max<EdgeWeight>(1, std::round(segment.weight * weight_multiplier));
|
|
|
|
edge.duration = std::max<EdgeWeight>(1, std::round(segment.duration * 10.));
|
2016-12-06 15:30:46 -05:00
|
|
|
|
|
|
|
// assign new node id
|
|
|
|
auto id_iter = external_to_internal_node_id_map.find(node_iterator->node_id);
|
|
|
|
BOOST_ASSERT(id_iter != external_to_internal_node_id_map.end());
|
|
|
|
edge.target = id_iter->second;
|
|
|
|
|
|
|
|
// orient edges consistently: source id < target id
|
|
|
|
// important for multi-edge removal
|
|
|
|
if (edge.source > edge.target)
|
|
|
|
{
|
|
|
|
std::swap(edge.source, edge.target);
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
// std::swap does not work with bit-fields
|
|
|
|
bool temp = edge.forward;
|
|
|
|
edge.forward = edge.backward;
|
|
|
|
edge.backward = temp;
|
|
|
|
}
|
|
|
|
++edge_iterator;
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2015-10-02 11:03:35 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
// Remove all remaining edges. They are invalid because there are no corresponding nodes for
|
|
|
|
// them. This happens when using osmosis with bbox or polygon to extract smaller areas.
|
|
|
|
auto markTargetsInvalid = [](InternalExtractorEdge &edge) {
|
|
|
|
util::Log(logDEBUG) << "Found invalid node reference " << edge.result.target;
|
|
|
|
edge.result.target = SPECIAL_NODEID;
|
|
|
|
};
|
|
|
|
std::for_each(edge_iterator, all_edges_list_end_, markTargetsInvalid);
|
|
|
|
TIMER_STOP(compute_weights);
|
|
|
|
log << "ok, after " << TIMER_SEC(compute_weights) << "s";
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
|
|
|
// Sort edges by start.
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting edges by renumbered start ... ";
|
|
|
|
TIMER_START(sort_edges_by_renumbered_start);
|
|
|
|
std::mutex name_data_mutex;
|
|
|
|
stxxl::sort(
|
|
|
|
all_edges_list.begin(),
|
|
|
|
all_edges_list.end(),
|
|
|
|
CmpEdgeByInternalSourceTargetAndName{name_data_mutex, name_char_data, name_offsets},
|
|
|
|
stxxl_memory);
|
|
|
|
TIMER_STOP(sort_edges_by_renumbered_start);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_edges_by_renumbered_start) << "s";
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
|
|
|
BOOST_ASSERT(all_edges_list.size() > 0);
|
2016-05-12 12:50:10 -04:00
|
|
|
for (std::size_t i = 0; i < all_edges_list.size();)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
|
|
|
// only invalid edges left
|
|
|
|
if (all_edges_list[i].result.source == SPECIAL_NODEID)
|
|
|
|
{
|
|
|
|
break;
|
|
|
|
}
|
2015-05-24 11:25:38 -04:00
|
|
|
// skip invalid edges
|
|
|
|
if (all_edges_list[i].result.target == SPECIAL_NODEID)
|
|
|
|
{
|
2015-06-29 18:22:40 -04:00
|
|
|
++i;
|
2015-05-24 11:25:38 -04:00
|
|
|
continue;
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
std::size_t start_idx = i;
|
2015-05-12 19:26:54 -04:00
|
|
|
NodeID source = all_edges_list[i].result.source;
|
|
|
|
NodeID target = all_edges_list[i].result.target;
|
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
auto min_forward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
|
|
|
std::numeric_limits<EdgeWeight>::max());
|
|
|
|
auto min_backward = std::make_pair(std::numeric_limits<EdgeWeight>::max(),
|
|
|
|
std::numeric_limits<EdgeWeight>::max());
|
|
|
|
std::size_t min_forward_idx = std::numeric_limits<std::size_t>::max();
|
|
|
|
std::size_t min_backward_idx = std::numeric_limits<std::size_t>::max();
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2015-05-24 11:25:38 -04:00
|
|
|
// find minimal edge in both directions
|
2016-05-12 12:50:10 -04:00
|
|
|
while (i < all_edges_list.size() && all_edges_list[i].result.source == source &&
|
2015-05-12 19:26:54 -04:00
|
|
|
all_edges_list[i].result.target == target)
|
|
|
|
{
|
2016-05-12 12:50:10 -04:00
|
|
|
const auto &result = all_edges_list[i].result;
|
|
|
|
const auto value = std::make_pair(result.weight, result.duration);
|
|
|
|
if (result.forward && value < min_forward)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
|
|
|
min_forward_idx = i;
|
2016-05-12 12:50:10 -04:00
|
|
|
min_forward = value;
|
2015-05-12 19:26:54 -04:00
|
|
|
}
|
2016-05-12 12:50:10 -04:00
|
|
|
if (result.backward && value < min_backward)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
|
|
|
min_backward_idx = i;
|
2016-05-12 12:50:10 -04:00
|
|
|
min_backward = value;
|
2015-05-12 19:26:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// this also increments the outer loop counter!
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(min_forward_idx == std::numeric_limits<std::size_t>::max() ||
|
2016-01-05 06:04:04 -05:00
|
|
|
min_forward_idx < i);
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(min_backward_idx == std::numeric_limits<std::size_t>::max() ||
|
2016-01-05 06:04:04 -05:00
|
|
|
min_backward_idx < i);
|
2016-05-12 12:50:10 -04:00
|
|
|
BOOST_ASSERT(min_backward_idx != std::numeric_limits<std::size_t>::max() ||
|
|
|
|
min_forward_idx != std::numeric_limits<std::size_t>::max());
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2015-05-24 11:25:38 -04:00
|
|
|
if (min_backward_idx == min_forward_idx)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
2015-05-24 11:25:38 -04:00
|
|
|
all_edges_list[min_forward_idx].result.is_split = false;
|
|
|
|
all_edges_list[min_forward_idx].result.forward = true;
|
|
|
|
all_edges_list[min_forward_idx].result.backward = true;
|
2015-05-12 19:26:54 -04:00
|
|
|
}
|
2015-05-24 11:25:38 -04:00
|
|
|
else
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
2016-05-12 12:50:10 -04:00
|
|
|
bool has_forward = min_forward_idx != std::numeric_limits<std::size_t>::max();
|
|
|
|
bool has_backward = min_backward_idx != std::numeric_limits<std::size_t>::max();
|
2015-05-24 11:25:38 -04:00
|
|
|
if (has_forward)
|
|
|
|
{
|
|
|
|
all_edges_list[min_forward_idx].result.forward = true;
|
|
|
|
all_edges_list[min_forward_idx].result.backward = false;
|
|
|
|
all_edges_list[min_forward_idx].result.is_split = has_backward;
|
|
|
|
}
|
|
|
|
if (has_backward)
|
|
|
|
{
|
|
|
|
std::swap(all_edges_list[min_backward_idx].result.source,
|
|
|
|
all_edges_list[min_backward_idx].result.target);
|
|
|
|
all_edges_list[min_backward_idx].result.forward = true;
|
|
|
|
all_edges_list[min_backward_idx].result.backward = false;
|
|
|
|
all_edges_list[min_backward_idx].result.is_split = has_forward;
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
// invalidate all unused edges
|
2016-05-12 12:50:10 -04:00
|
|
|
for (std::size_t j = start_idx; j < i; j++)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
|
|
|
if (j == min_forward_idx || j == min_backward_idx)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
all_edges_list[j].result.source = SPECIAL_NODEID;
|
|
|
|
all_edges_list[j].result.target = SPECIAL_NODEID;
|
|
|
|
}
|
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2014-08-11 08:07:00 -04:00
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
void ExtractionContainers::WriteEdges(storage::io::FileWriter &file_out) const
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2017-03-04 05:52:40 -05:00
|
|
|
std::vector<NodeBasedEdge> normal_edges;
|
|
|
|
normal_edges.reserve(all_edges_list.size());
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Writing used edges ... " << std::flush;
|
|
|
|
TIMER_START(write_edges);
|
|
|
|
// Traverse list of edges and nodes in parallel and set target coord
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
for (const auto &edge : all_edges_list)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
if (edge.result.source == SPECIAL_NODEID || edge.result.target == SPECIAL_NODEID)
|
|
|
|
{
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// IMPORTANT: here, we're using slicing to only write the data from the base
|
|
|
|
// class of NodeBasedEdgeWithOSM
|
2017-03-04 05:52:40 -05:00
|
|
|
normal_edges.push_back(edge.result);
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
if (normal_edges.size() > std::numeric_limits<uint32_t>::max())
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
throw util::exception("There are too many edges, OSRM only supports 2^32" + SOURCE_REF);
|
|
|
|
}
|
2015-11-24 19:33:19 -05:00
|
|
|
|
2017-04-08 10:06:34 -04:00
|
|
|
file_out.WriteElementCount64(normal_edges.size());
|
2017-03-04 05:52:40 -05:00
|
|
|
file_out.WriteFrom(normal_edges.data(), normal_edges.size());
|
2015-12-09 13:01:45 -05:00
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
TIMER_STOP(write_edges);
|
|
|
|
log << "ok, after " << TIMER_SEC(write_edges) << "s";
|
|
|
|
log << "Processed " << normal_edges.size() << " edges";
|
2016-12-06 15:30:46 -05:00
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
void ExtractionContainers::WriteNodes(storage::io::FileWriter &file_out) const
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
// write dummy value, will be overwritten later
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "setting number of nodes ... " << std::flush;
|
2017-04-08 10:06:34 -04:00
|
|
|
file_out.WriteElementCount64(max_internal_node_id);
|
2016-12-06 15:30:46 -05:00
|
|
|
log << "ok";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Confirming/Writing used nodes ... ";
|
|
|
|
TIMER_START(write_nodes);
|
|
|
|
// identify all used nodes by a merging step of two sorted lists
|
|
|
|
auto node_iterator = all_nodes_list.begin();
|
|
|
|
auto node_id_iterator = used_node_id_list.begin();
|
|
|
|
const auto used_node_id_list_end = used_node_id_list.end();
|
|
|
|
const auto all_nodes_list_end = all_nodes_list.end();
|
|
|
|
|
|
|
|
while (node_id_iterator != used_node_id_list_end && node_iterator != all_nodes_list_end)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
if (*node_id_iterator < node_iterator->node_id)
|
|
|
|
{
|
|
|
|
++node_id_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
if (*node_id_iterator > node_iterator->node_id)
|
|
|
|
{
|
|
|
|
++node_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
BOOST_ASSERT(*node_id_iterator == node_iterator->node_id);
|
|
|
|
|
2017-03-04 05:52:40 -05:00
|
|
|
file_out.WriteOne((*node_iterator));
|
2016-12-06 15:30:46 -05:00
|
|
|
|
2015-05-09 11:21:36 -04:00
|
|
|
++node_id_iterator;
|
|
|
|
++node_iterator;
|
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
TIMER_STOP(write_nodes);
|
|
|
|
log << "ok, after " << TIMER_SEC(write_nodes) << "s";
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2013-08-20 11:05:36 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log() << "Processed " << max_internal_node_id << " nodes";
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
|
|
|
|
2016-01-05 06:04:04 -05:00
|
|
|
void ExtractionContainers::WriteRestrictions(const std::string &path) const
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
|
|
|
// serialize restrictions
|
2017-04-08 10:06:34 -04:00
|
|
|
std::uint64_t written_restriction_count = 0;
|
2017-03-04 05:52:40 -05:00
|
|
|
storage::io::FileWriter restrictions_out_file(path,
|
|
|
|
storage::io::FileWriter::GenerateFingerprint);
|
|
|
|
|
2017-04-08 10:06:34 -04:00
|
|
|
restrictions_out_file.WriteElementCount64(written_restriction_count);
|
2015-05-09 11:21:36 -04:00
|
|
|
|
|
|
|
for (const auto &restriction_container : restrictions_list)
|
|
|
|
{
|
|
|
|
if (SPECIAL_NODEID != restriction_container.restriction.from.node &&
|
2015-05-12 19:26:54 -04:00
|
|
|
SPECIAL_NODEID != restriction_container.restriction.via.node &&
|
2015-05-09 11:21:36 -04:00
|
|
|
SPECIAL_NODEID != restriction_container.restriction.to.node)
|
2014-05-09 10:17:31 -04:00
|
|
|
{
|
2017-03-04 05:52:40 -05:00
|
|
|
restrictions_out_file.WriteOne(restriction_container.restriction);
|
2015-05-09 11:21:36 -04:00
|
|
|
++written_restriction_count;
|
2013-09-26 12:19:51 -04:00
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2017-03-04 05:52:40 -05:00
|
|
|
restrictions_out_file.SkipToBeginning();
|
2017-04-08 10:06:34 -04:00
|
|
|
restrictions_out_file.WriteElementCount64(written_restriction_count);
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log() << "usable restrictions: " << written_restriction_count;
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2014-06-07 11:50:02 -04:00
|
|
|
|
2015-05-09 11:21:36 -04:00
|
|
|
void ExtractionContainers::PrepareRestrictions()
|
|
|
|
{
|
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting used ways ... ";
|
|
|
|
TIMER_START(sort_ways);
|
|
|
|
stxxl::sort(way_start_end_id_list.begin(),
|
|
|
|
way_start_end_id_list.end(),
|
|
|
|
FirstAndLastSegmentOfWayStxxlCompare(),
|
|
|
|
stxxl_memory);
|
|
|
|
TIMER_STOP(sort_ways);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_ways) << "s";
|
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting " << restrictions_list.size() << " restriction. by from... ";
|
|
|
|
TIMER_START(sort_restrictions);
|
|
|
|
stxxl::sort(restrictions_list.begin(),
|
|
|
|
restrictions_list.end(),
|
|
|
|
CmpRestrictionContainerByFrom(),
|
|
|
|
stxxl_memory);
|
|
|
|
TIMER_STOP(sort_restrictions);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_restrictions) << "s";
|
|
|
|
}
|
2014-05-06 12:15:45 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Fixing restriction starts ... " << std::flush;
|
|
|
|
TIMER_START(fix_restriction_starts);
|
|
|
|
auto restrictions_iterator = restrictions_list.begin();
|
|
|
|
auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
|
|
|
|
const auto restrictions_list_end = restrictions_list.end();
|
|
|
|
const auto way_start_end_id_list_end = way_start_end_id_list.cend();
|
|
|
|
|
|
|
|
while (way_start_and_end_iterator != way_start_end_id_list_end &&
|
|
|
|
restrictions_iterator != restrictions_list_end)
|
2015-05-12 19:26:54 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
if (way_start_and_end_iterator->way_id <
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.from.way)})
|
|
|
|
{
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
if (way_start_and_end_iterator->way_id >
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.from.way)})
|
2016-03-08 14:59:11 -05:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log(logDEBUG) << "Restriction references invalid way: "
|
|
|
|
<< restrictions_iterator->restriction.from.way;
|
2016-03-08 14:59:11 -05:00
|
|
|
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
|
|
|
|
BOOST_ASSERT(
|
|
|
|
way_start_and_end_iterator->way_id ==
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.from.way)});
|
|
|
|
// we do not remap the via id yet, since we will need it for the to node as well
|
|
|
|
const OSMNodeID via_node_id = OSMNodeID{restrictions_iterator->restriction.via.node};
|
|
|
|
|
|
|
|
// check if via is actually valid, if not invalidate
|
|
|
|
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
|
|
|
|
if (via_id_iter == external_to_internal_node_id_map.end())
|
2016-03-08 14:59:11 -05:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
util::Log(logDEBUG) << "Restriction references invalid node: "
|
|
|
|
<< restrictions_iterator->restriction.via.node;
|
|
|
|
restrictions_iterator->restriction.via.node = SPECIAL_NODEID;
|
2016-03-08 14:59:11 -05:00
|
|
|
++restrictions_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
|
|
|
{
|
|
|
|
// assign new from node id
|
|
|
|
auto id_iter = external_to_internal_node_id_map.find(
|
|
|
|
way_start_and_end_iterator->first_segment_target_id);
|
|
|
|
if (id_iter == external_to_internal_node_id_map.end())
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Way references invalid node: "
|
|
|
|
<< way_start_and_end_iterator->first_segment_target_id;
|
|
|
|
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
restrictions_iterator->restriction.from.node = id_iter->second;
|
|
|
|
}
|
|
|
|
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
|
|
|
{
|
|
|
|
// assign new from node id
|
|
|
|
auto id_iter = external_to_internal_node_id_map.find(
|
|
|
|
way_start_and_end_iterator->last_segment_source_id);
|
|
|
|
if (id_iter == external_to_internal_node_id_map.end())
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Way references invalid node: "
|
|
|
|
<< way_start_and_end_iterator->last_segment_target_id;
|
|
|
|
restrictions_iterator->restriction.from.node = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
restrictions_iterator->restriction.from.node = id_iter->second;
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
++restrictions_iterator;
|
|
|
|
}
|
2015-05-09 11:21:36 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
TIMER_STOP(fix_restriction_starts);
|
|
|
|
log << "ok, after " << TIMER_SEC(fix_restriction_starts) << "s";
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Sorting restrictions. by to ... " << std::flush;
|
|
|
|
TIMER_START(sort_restrictions_to);
|
|
|
|
stxxl::sort(restrictions_list.begin(),
|
|
|
|
restrictions_list.end(),
|
|
|
|
CmpRestrictionContainerByTo(),
|
|
|
|
stxxl_memory);
|
|
|
|
TIMER_STOP(sort_restrictions_to);
|
|
|
|
log << "ok, after " << TIMER_SEC(sort_restrictions_to) << "s";
|
|
|
|
}
|
2015-05-12 19:26:54 -04:00
|
|
|
|
2016-12-06 15:30:46 -05:00
|
|
|
{
|
|
|
|
util::UnbufferedLog log;
|
|
|
|
log << "Fixing restriction ends ... " << std::flush;
|
|
|
|
TIMER_START(fix_restriction_ends);
|
|
|
|
auto restrictions_iterator = restrictions_list.begin();
|
|
|
|
auto way_start_and_end_iterator = way_start_end_id_list.cbegin();
|
|
|
|
const auto way_start_end_id_list_end_ = way_start_end_id_list.cend();
|
|
|
|
const auto restrictions_list_end_ = restrictions_list.end();
|
|
|
|
|
|
|
|
while (way_start_and_end_iterator != way_start_end_id_list_end_ &&
|
|
|
|
restrictions_iterator != restrictions_list_end_)
|
2015-05-09 11:21:36 -04:00
|
|
|
{
|
2016-12-06 15:30:46 -05:00
|
|
|
if (way_start_and_end_iterator->way_id <
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.to.way)})
|
2016-03-08 14:59:11 -05:00
|
|
|
{
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
if (restrictions_iterator->restriction.from.node == SPECIAL_NODEID ||
|
|
|
|
restrictions_iterator->restriction.via.node == SPECIAL_NODEID)
|
2016-03-08 14:59:11 -05:00
|
|
|
{
|
|
|
|
++restrictions_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
if (way_start_and_end_iterator->way_id >
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.to.way)})
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Restriction references invalid way: "
|
|
|
|
<< restrictions_iterator->restriction.to.way;
|
|
|
|
restrictions_iterator->restriction.to.way = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
BOOST_ASSERT(
|
|
|
|
way_start_and_end_iterator->way_id ==
|
|
|
|
OSMWayID{static_cast<std::uint32_t>(restrictions_iterator->restriction.to.way)});
|
|
|
|
const OSMNodeID via_node_id = OSMNodeID{restrictions_iterator->restriction.via.node};
|
|
|
|
|
|
|
|
// assign new via node id
|
|
|
|
auto via_id_iter = external_to_internal_node_id_map.find(via_node_id);
|
|
|
|
BOOST_ASSERT(via_id_iter != external_to_internal_node_id_map.end());
|
|
|
|
restrictions_iterator->restriction.via.node = via_id_iter->second;
|
|
|
|
|
|
|
|
if (way_start_and_end_iterator->first_segment_source_id == via_node_id)
|
|
|
|
{
|
|
|
|
auto to_id_iter = external_to_internal_node_id_map.find(
|
|
|
|
way_start_and_end_iterator->first_segment_target_id);
|
|
|
|
if (to_id_iter == external_to_internal_node_id_map.end())
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Way references invalid node: "
|
|
|
|
<< way_start_and_end_iterator->first_segment_source_id;
|
|
|
|
restrictions_iterator->restriction.to.node = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
restrictions_iterator->restriction.to.node = to_id_iter->second;
|
|
|
|
}
|
|
|
|
else if (way_start_and_end_iterator->last_segment_target_id == via_node_id)
|
|
|
|
{
|
|
|
|
auto to_id_iter = external_to_internal_node_id_map.find(
|
|
|
|
way_start_and_end_iterator->last_segment_source_id);
|
|
|
|
if (to_id_iter == external_to_internal_node_id_map.end())
|
|
|
|
{
|
|
|
|
util::Log(logDEBUG) << "Way references invalid node: "
|
|
|
|
<< way_start_and_end_iterator->last_segment_source_id;
|
|
|
|
restrictions_iterator->restriction.to.node = SPECIAL_NODEID;
|
|
|
|
++restrictions_iterator;
|
|
|
|
++way_start_and_end_iterator;
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
restrictions_iterator->restriction.to.node = to_id_iter->second;
|
|
|
|
}
|
|
|
|
++restrictions_iterator;
|
2015-05-09 11:21:36 -04:00
|
|
|
}
|
2016-12-06 15:30:46 -05:00
|
|
|
TIMER_STOP(fix_restriction_ends);
|
|
|
|
log << "ok, after " << TIMER_SEC(fix_restriction_ends) << "s";
|
2015-01-22 06:19:11 -05:00
|
|
|
}
|
2012-08-29 12:33:18 -04:00
|
|
|
}
|
2016-01-05 10:51:13 -05:00
|
|
|
}
|
|
|
|
}
|