void LoadNodeAndEdgeInformation(const boost::filesystem::path &nodes_file, const boost::filesystem::path &edges_file) { boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary); QueryNode current_node; unsigned number_of_coordinates = 0; nodes_input_stream.read((char *)&number_of_coordinates, sizeof(unsigned)); m_coordinate_list = std::make_shared<std::vector<FixedPointCoordinate>>(number_of_coordinates); for (unsigned i = 0; i < number_of_coordinates; ++i) { nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode)); m_coordinate_list->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon); BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lat) >> 30) == 0); BOOST_ASSERT((std::abs(m_coordinate_list->at(i).lon) >> 30) == 0); } nodes_input_stream.close(); boost::filesystem::ifstream edges_input_stream(edges_file, std::ios::binary); unsigned number_of_edges = 0; edges_input_stream.read((char *)&number_of_edges, sizeof(unsigned)); m_via_node_list.resize(number_of_edges); m_name_ID_list.resize(number_of_edges); m_turn_instruction_list.resize(number_of_edges); m_travel_mode_list.resize(number_of_edges); m_edge_is_compressed.resize(number_of_edges); unsigned compressed = 0; OriginalEdgeData current_edge_data; for (unsigned i = 0; i < number_of_edges; ++i) { edges_input_stream.read((char *)&(current_edge_data), sizeof(OriginalEdgeData)); m_via_node_list[i] = current_edge_data.via_node; m_name_ID_list[i] = current_edge_data.name_id; m_turn_instruction_list[i] = current_edge_data.turn_instruction; m_travel_mode_list[i] = current_edge_data.travel_mode; m_edge_is_compressed[i] = current_edge_data.compressed_geometry; if (m_edge_is_compressed[i]) { ++compressed; } } edges_input_stream.close(); }
FixedPointCoordinateListPtr LoadCoordinates(const boost::filesystem::path &nodes_file) { boost::filesystem::ifstream nodes_input_stream(nodes_file, std::ios::binary); QueryNode current_node; unsigned coordinate_count = 0; nodes_input_stream.read((char *)&coordinate_count, sizeof(unsigned)); auto coords = std::make_shared<std::vector<FixedPointCoordinate>>(coordinate_count); for (unsigned i = 0; i < coordinate_count; ++i) { nodes_input_stream.read((char *)¤t_node, sizeof(QueryNode)); coords->at(i) = FixedPointCoordinate(current_node.lat, current_node.lon); BOOST_ASSERT((std::abs(coords->at(i).lat) >> 30) == 0); BOOST_ASSERT((std::abs(coords->at(i).lon) >> 30) == 0); } nodes_input_stream.close(); return coords; }
SegmentInformation getTestInfo(int lat, int lon, bool necessary) { return SegmentInformation(FixedPointCoordinate(lat, lon), 0, 0, 0, TurnInstruction::HeadOn, necessary, false, 0); }
Handle<Value> Query::New(Arguments const& args) { HandleScope scope; if (!args.IsConstructCall()) { return ThrowException(Exception::Error(String::New("Cannot call constructor as function, you need to use 'new' keyword"))); } try { if (args.Length() != 1) { return ThrowException(Exception::TypeError(String::New("please provide an object of options for the first argument"))); } if (!args[0]->IsObject()) { return ThrowException(Exception::TypeError(String::New("first argument must be an object"))); } Local<Object> obj = args[0]->ToObject(); if (obj->IsNull() || obj->IsUndefined()) { return ThrowException(Exception::TypeError(String::New("first arg must be an object"))); } if (!obj->Has(String::NewSymbol("coordinates"))) { return ThrowException(Exception::TypeError(String::New("must provide a coordinates property"))); } Local<Value> coordinates = obj->Get(String::New("coordinates")); if (!coordinates->IsArray()) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } Local<Array> coordinates_array = Local<Array>::Cast(coordinates); if (coordinates_array->Length() < 2) { return ThrowException(Exception::TypeError(String::New("at least two coordinates must be provided"))); } Query* q = new Query(); q->this_->zoomLevel = 18; //no generalization q->this_->printInstructions = true; //turn by turn instructions q->this_->alternateRoute = true; //get an alternate route, too q->this_->geometry = true; //retrieve geometry of route q->this_->compression = true; //polyline encoding q->this_->checkSum = UINT_MAX; //see wiki q->this_->service = "viaroute"; //that's routing q->this_->outputFormat = "json"; q->this_->jsonpParameter = ""; //set for jsonp wrapping q->this_->language = ""; //unused atm if (obj->Has(String::NewSymbol("alternateRoute"))) { q->this_->alternateRoute = obj->Get(String::New("alternateRoute"))->BooleanValue(); } for (uint32_t i = 0; i < coordinates_array->Length(); ++i) { Local<Value> coordinate = coordinates_array->Get(i); if (!coordinate->IsArray()) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } Local<Array> coordinate_array = Local<Array>::Cast(coordinate); if (coordinate_array->Length() != 2) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } q->this_->coordinates.push_back( FixedPointCoordinate(coordinate_array->Get(0)->NumberValue()*COORDINATE_PRECISION, coordinate_array->Get(1)->NumberValue()*COORDINATE_PRECISION)); } q->Wrap(args.This()); return args.This(); } catch (std::exception const& ex) { return ThrowException(Exception::TypeError(String::New(ex.what()))); } return Undefined(); }
void Benchmark(BenchStaticRTree &rtree, unsigned num_queries) { std::mt19937 mt_rand(RANDOM_SEED); std::uniform_int_distribution<> lat_udist(WORLD_MIN_LAT, WORLD_MAX_LAT); std::uniform_int_distribution<> lon_udist(WORLD_MIN_LON, WORLD_MAX_LON); std::vector<FixedPointCoordinate> queries; for (unsigned i = 0; i < num_queries; i++) { queries.emplace_back(FixedPointCoordinate(lat_udist(mt_rand), lon_udist(mt_rand))); } { const unsigned num_results = 5; std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results << " phantom nodes" << "\n"; TIMER_START(query_phantom); std::vector<PhantomNode> phantom_node_vector; for (const auto &q : queries) { phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### LocateClosestEndPointForCoordinate" << "\n"; } TIMER_START(query_endpoint); FixedPointCoordinate result; for (const auto &q : queries) { rtree.LocateClosestEndPointForCoordinate(q, result, 3); } TIMER_STOP(query_endpoint); std::cout << "Took " << TIMER_MSEC(query_endpoint) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_endpoint) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### FindPhantomNodeForCoordinate" << "\n"; TIMER_START(query_node); for (const auto &q : queries) { PhantomNode phantom; rtree.FindPhantomNodeForCoordinate(q, phantom, 3); } TIMER_STOP(query_node); std::cout << "Took " << TIMER_MSEC(query_node) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_node) / ((double)num_queries) << " msec/query." << "\n"; { const unsigned num_results = 1; std::cout << "#### IncrementalFindPhantomNodeForCoordinate : " << num_results << " phantom nodes" << "\n"; TIMER_START(query_phantom); std::vector<PhantomNode> phantom_node_vector; for (const auto &q : queries) { phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 3, num_results); phantom_node_vector.clear(); rtree.IncrementalFindPhantomNodeForCoordinate(q, phantom_node_vector, 17, num_results); } TIMER_STOP(query_phantom); std::cout << "Took " << TIMER_MSEC(query_phantom) << " msec for " << num_queries << " queries." << "\n"; std::cout << TIMER_MSEC(query_phantom) / ((double)num_queries) << " msec/query." << "\n"; std::cout << "#### LocateClosestEndPointForCoordinate" << "\n"; } }
inline float GetMinDist(const FixedPointCoordinate &location) const { const bool is_contained = Contains(location); if (is_contained) { return 0.0f; } enum Direction { INVALID = 0, NORTH = 1, SOUTH = 2, EAST = 4, NORTH_EAST = 5, SOUTH_EAST = 6, WEST = 8, NORTH_WEST = 9, SOUTH_WEST = 10 }; Direction d = INVALID; if (location.lat > max_lat) d = (Direction) (d | NORTH); else if (location.lat < min_lat) d = (Direction) (d | SOUTH); if (location.lon > max_lon) d = (Direction) (d | EAST); else if (location.lon < min_lon) d = (Direction) (d | WEST); BOOST_ASSERT(d != INVALID); float min_dist = std::numeric_limits<float>::max(); switch (d) { case NORTH: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, location.lon)); break; case SOUTH: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, location.lon)); break; case WEST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, min_lon)); break; case EAST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(location.lat, max_lon)); break; case NORTH_EAST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, max_lon)); break; case NORTH_WEST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(max_lat, min_lon)); break; case SOUTH_EAST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, max_lon)); break; case SOUTH_WEST: min_dist = FixedPointCoordinate::ApproximateEuclideanDistance(location, FixedPointCoordinate(min_lat, min_lon)); break; default: break; } BOOST_ASSERT(min_dist != std::numeric_limits<float>::max()); return min_dist; }
Handle<Value> Query::New(Arguments const& args) { HandleScope scope; if (!args.IsConstructCall()) { return ThrowException(Exception::Error(String::New("Cannot call constructor as function, you need to use 'new' keyword"))); } try { if (args.Length() != 1) { return ThrowException(Exception::TypeError(String::New("please provide an object of options for the first argument"))); } if (!args[0]->IsObject()) { return ThrowException(Exception::TypeError(String::New("first argument must be an object"))); } Local<Object> obj = args[0]->ToObject(); if (obj->IsNull() || obj->IsUndefined()) { return ThrowException(Exception::TypeError(String::New("first arg must be an object"))); } if (!obj->Has(String::New("coordinates"))) { return ThrowException(Exception::TypeError(String::New("must provide a coordinates property"))); } Local<Value> coordinates = obj->Get(String::New("coordinates")); if (!coordinates->IsArray()) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } // Handle scenario in which caller explicitly specified service std::string service; if (obj->Has(String::New("service"))) { Local<Value> serviceValue = obj->Get(String::New("service")); v8::String::Utf8Value serviceUtf8Value(serviceValue->ToString()); service = std::string(*serviceUtf8Value); } // Handle 'nearest', otherwise assume 'viaroute' service. if (service == "nearest" || service == "locate") { Local<Array> coordinates_array = Local<Array>::Cast(coordinates); if (coordinates_array->Length() != 1) { return ThrowException(Exception::TypeError(String::New("coordinates array should only have one lat/long pair for 'nearest' or 'locate' queries"))); } Local<Value> coordinate = coordinates_array->Get(0); if (!coordinate->IsArray()) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } Local<Array> coordinate_array = Local<Array>::Cast(coordinate); if (coordinate_array->Length() != 2) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } Query* q = new Query(); q->this_->service = service; q->this_->coordinates.push_back( FixedPointCoordinate(coordinate_array->Get(0)->NumberValue()*COORDINATE_PRECISION, coordinate_array->Get(1)->NumberValue()*COORDINATE_PRECISION)); q->Wrap(args.This()); return args.This(); } Local<Array> coordinates_array = Local<Array>::Cast(coordinates); if (coordinates_array->Length() < 2) { return ThrowException(Exception::TypeError(String::New("at least two coordinates must be provided"))); } Query* q = new Query(); q->this_->zoomLevel = 18; //no generalization q->this_->printInstructions = false; //turn by turn instructions q->this_->alternateRoute = true; //get an alternate route, too q->this_->geometry = true; //retrieve geometry of route q->this_->compression = true; //polyline encoding q->this_->checkSum = UINT_MAX; //see wiki q->this_->service = "viaroute"; //that's routing q->this_->outputFormat = "json"; q->this_->jsonpParameter = ""; //set for jsonp wrapping q->this_->language = ""; //unused atm if (obj->Has(String::New("alternateRoute"))) { q->this_->alternateRoute = obj->Get(String::New("alternateRoute"))->BooleanValue(); } if (obj->Has(String::New("checksum"))) { q->this_->checkSum = static_cast<unsigned>(obj->Get(String::New("checksum"))->Uint32Value()); } if (obj->Has(String::New("zoomLevel"))) { q->this_->zoomLevel = static_cast<short>(obj->Get(String::New("zoomLevel"))->Int32Value()); } if (obj->Has(String::New("printInstructions"))) { q->this_->printInstructions = obj->Get(String::New("printInstructions"))->BooleanValue(); } if (obj->Has(String::New("jsonpParameter"))) { q->this_->jsonpParameter = *v8::String::Utf8Value(obj->Get(String::New("jsonpParameter"))); } if (obj->Has(String::New("hints"))) { Local<Value> hints = obj->Get(String::New("hints")); if (!hints->IsArray()) { return ThrowException(Exception::TypeError(String::New("hints must be an array of strings/null"))); } Local<Array> hints_array = Local<Array>::Cast(hints); for (uint32_t i = 0; i < hints_array->Length(); ++i) { Local<Value> hint = hints_array->Get(i); if (hint->IsString()) { q->this_->hints.push_back(*v8::String::Utf8Value(hint)); } else if(hint->IsNull()){ q->this_->hints.push_back(""); }else{ return ThrowException(Exception::TypeError(String::New("hint must be null or string"))); } } } for (uint32_t i = 0; i < coordinates_array->Length(); ++i) { Local<Value> coordinate = coordinates_array->Get(i); if (!coordinate->IsArray()) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } Local<Array> coordinate_array = Local<Array>::Cast(coordinate); if (coordinate_array->Length() != 2) { return ThrowException(Exception::TypeError(String::New("coordinates must be an array of (lat/long) pairs"))); } q->this_->coordinates.push_back( FixedPointCoordinate(coordinate_array->Get(0)->NumberValue()*COORDINATE_PRECISION, coordinate_array->Get(1)->NumberValue()*COORDINATE_PRECISION)); } q->Wrap(args.This()); return args.This(); } catch (std::exception const& ex) { return ThrowException(Exception::TypeError(String::New(ex.what()))); } return Undefined(); }