mirror of
https://github.com/Threnklyn/pebble-directions.git
synced 2026-05-18 21:03:27 +02:00
updates to summary and api usage, added real time routing
* the summary now respects unit preferences from the watch default settings (read from the health measurement system display) * added more specific fields for public transit api * added real time routing (in progress) * added setting to disable real time routing * added api attribution and feedback link in the settings page
This commit is contained in:
+2
-1
@@ -35,7 +35,8 @@
|
||||
"DISTANCE",
|
||||
"TIME",
|
||||
"INSTRUCTION_ICONS",
|
||||
"INSTRUCTION_LIST"
|
||||
"INSTRUCTION_LIST",
|
||||
"CURRENT"
|
||||
],
|
||||
"resources": {
|
||||
"media": [
|
||||
|
||||
+16
-6
@@ -42,13 +42,23 @@ void directions_draw_summary(GContext *ctx, GRect bounds, GColor color, int dist
|
||||
// Get the strings
|
||||
char string_distance[16];
|
||||
char string_time[16];
|
||||
if (distance < 1000) {
|
||||
// Use meters
|
||||
snprintf(string_distance, sizeof(string_distance), "%i m", distance);
|
||||
} else {
|
||||
// Convert to kilometeres with one place after the point
|
||||
snprintf(string_distance, sizeof(string_distance), "%i.%i km", distance / 1000, (distance % 1000) / 100);
|
||||
// Disance string
|
||||
switch (health_service_get_measurement_system_for_display(HealthMetricWalkedDistanceMeters)) {
|
||||
// Imperial (miles)
|
||||
case MeasurementSystemImperial:
|
||||
snprintf(string_distance, sizeof(string_distance), "%i.%i mi", distance / 1609, ((distance % 1609) * 10) / 1609);
|
||||
break;
|
||||
// Metric (meters & kilometers)
|
||||
default:
|
||||
if (distance < 1000) {
|
||||
// Use meters
|
||||
snprintf(string_distance, sizeof(string_distance), "%i m", distance);
|
||||
} else {
|
||||
// Convert to kilometeres with one place after the point
|
||||
snprintf(string_distance, sizeof(string_distance), "%i.%i km", distance / 1000, (distance % 1000) / 100);
|
||||
}
|
||||
}
|
||||
// Time required string
|
||||
if (time < 60) {
|
||||
// Use minutes
|
||||
snprintf(string_time, sizeof(string_time), "%i min", time);
|
||||
|
||||
@@ -16,6 +16,9 @@
|
||||
|
||||
// The RouteData struct
|
||||
struct RouteData {
|
||||
// Meta fields
|
||||
bool complete;
|
||||
int current;
|
||||
// Data fields
|
||||
int distance;
|
||||
int time;
|
||||
@@ -56,6 +59,7 @@ int message_number = -1;
|
||||
static void app_message_send_search_data();
|
||||
void window_display_error(enum ErrorType err);
|
||||
static void window_update_data();
|
||||
static void window_update_step();
|
||||
|
||||
|
||||
// ******************************
|
||||
@@ -168,6 +172,7 @@ static void app_message_inbox_recived_callback(DictionaryIterator *iter, void *c
|
||||
switch (success_response) {
|
||||
// Success
|
||||
case 0:
|
||||
route_data->complete = true;
|
||||
window_update_data();
|
||||
break;
|
||||
// Route not found / api error
|
||||
@@ -221,6 +226,17 @@ static void app_message_inbox_recived_callback(DictionaryIterator *iter, void *c
|
||||
// Increment the number of recived steps
|
||||
route_data->count += 1;
|
||||
}
|
||||
|
||||
// Test if the recived message is for key CURRENT
|
||||
message = dict_find(iter, MESSAGE_KEY_CURRENT);
|
||||
if (message) {
|
||||
// Set the current and update the ui if the data is already complete
|
||||
int new_step = (int)message->value->int32;
|
||||
if (route_data->complete && new_step < route_data->count) {
|
||||
route_data->current = new_step;
|
||||
window_update_step();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Respond with error, if any data is lost
|
||||
@@ -272,6 +288,9 @@ static void app_message_start() {
|
||||
// Set up the data
|
||||
route_data = malloc(sizeof(struct RouteData));
|
||||
|
||||
// Set meta values
|
||||
route_data->complete = false;
|
||||
route_data->current = 0;
|
||||
// Set initial values
|
||||
route_data->distance = 0;
|
||||
route_data->time = 0;
|
||||
@@ -323,6 +342,18 @@ static void window_update_data() {
|
||||
progress_layer_remove(progress_layer);
|
||||
}
|
||||
|
||||
// Update the window display to reflrect the new current step and vibrate
|
||||
static void window_update_step() {
|
||||
// Update the position of the step list
|
||||
#ifdef PBL_ROUND
|
||||
menu_layer_set_selected_index(directions_list, (MenuIndex){ .section = 0, .row = route_data->current + 1 }, MenuRowAlignCenter, true);
|
||||
#else
|
||||
menu_layer_set_selected_index(directions_list, (MenuIndex){ .section = 0, .row = route_data->current + 1 }, MenuRowAlignTop, true);
|
||||
#endif
|
||||
// Play a short vibration
|
||||
vibes_long_pulse();
|
||||
}
|
||||
|
||||
// Window unload handler
|
||||
static void window_unload() {
|
||||
// Destroy the menu layer
|
||||
|
||||
@@ -27,6 +27,11 @@
|
||||
* –––
|
||||
* Chars map to the following icons: type: 'a', forward: 'b', right: 'c', left: 'd', uRight: 'e', uLeft: 'f', attr: 'g', final: 'h'
|
||||
*
|
||||
* About the automatic navigation
|
||||
* –––
|
||||
* The automatic navigation can be toggled in the settings. If enabled, the JS part will listen to location updates and send the
|
||||
* current step-index to the watch in case it changes.
|
||||
*
|
||||
* About the config of 'named addresses'
|
||||
* –––
|
||||
* The config stores an array of these name / address pairs, every time a search request hits the phone the
|
||||
@@ -45,6 +50,12 @@ var messagePadding = 10;
|
||||
var locationService = require('./location.js');
|
||||
// Configuration
|
||||
var config = require('./config.js');
|
||||
// Route data
|
||||
var routeData = {
|
||||
stepPositionList: [],
|
||||
currentStep: 0,
|
||||
watchId: null,
|
||||
};
|
||||
|
||||
|
||||
// App Message functions
|
||||
@@ -116,6 +127,55 @@ function sendRoute(success, distance, time, stepList, stepIconsString, messageNu
|
||||
}
|
||||
}
|
||||
|
||||
// Send the new current index
|
||||
function sendCurrentStep(index, shouldRetry) {
|
||||
// Build the message
|
||||
var keyCurrent = keys.CURRENT;
|
||||
var dict = {};
|
||||
dict[keyCurrent] = +index;
|
||||
|
||||
// Transmit
|
||||
Pebble.sendAppMessage(dict, function() {
|
||||
// Success!
|
||||
console.log('Current step send:', index);
|
||||
}, function() {
|
||||
// Error, retry if allowed
|
||||
if (shouldRetry === true) {
|
||||
sendCurrentStep(index, false);
|
||||
} else {
|
||||
console.log('Transmission of current step failed');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Start sending current step information
|
||||
function startCurrentStepUpdates(stepPositionList) {
|
||||
// Store the current route data
|
||||
routeData.stepPositionList = stepPositionList;
|
||||
routeData.currentStep = 0;
|
||||
// Register the location updates
|
||||
routeData.watchId = navigator.geolocation.watchPosition(function(pos) {
|
||||
// New position was recived
|
||||
var lat = pos.coords.latitude;
|
||||
var lon = pos.coords.longitude;
|
||||
var newStep = locationService.getCurrentStepIndex(routeData.stepPositionList, lat, lon, routeData.currentStep);
|
||||
if (newStep != routeData.currentStep) {
|
||||
sendCurrentStep(newStep, true);
|
||||
routeData.currentStep = newStep;
|
||||
}
|
||||
},
|
||||
function() {
|
||||
// Error while reciving location update
|
||||
console.log('Error while reciving location update');
|
||||
}, { enableHighAccuracy: true, timeout: 5000, maximumAge: 0 });
|
||||
}
|
||||
|
||||
// Stop sending current step information
|
||||
function stopCurrentStepUpdates() {
|
||||
// Clear the watch and stop receiving updates
|
||||
navigator.geolocation.clearWatch(routeData.watchId);
|
||||
}
|
||||
|
||||
// Fetch a route from the here api and send it to the pebble
|
||||
function fetchAndSendRoute(routeType, searchText, messageNumber) {
|
||||
// Log the recived data
|
||||
@@ -130,8 +190,14 @@ function fetchAndSendRoute(routeType, searchText, messageNumber) {
|
||||
});
|
||||
// Load a route from here api. Data format: { distance, time, stepList[string], stepIconsString }
|
||||
locationService.createRoute(routeType, searchText, function(success, data) {
|
||||
// Log the route data
|
||||
console.log('Will send:', success, data.distance, data.time, data.stepList.length, data.stepIconsString, messageNumber);
|
||||
// Send the route data to the watch
|
||||
sendRoute(success, data.distance, data.time, data.stepList, data.stepIconsString, messageNumber);
|
||||
// If the loading was successfull, start watching the position (if enabled in the config)
|
||||
if (success && config.getNavigationSettings().auto) {
|
||||
startCurrentStepUpdates(data.stepPositionList);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -147,5 +213,7 @@ Pebble.addEventListener('appmessage', function(e) {
|
||||
currentMessageNumber ++;
|
||||
console.log('Message number send:', messageNumber);
|
||||
fetchAndSendRoute(dict['SEARCH'].substr(0, 1), dict['SEARCH'].substr(1), messageNumber);
|
||||
// Stop watching the position for automatic step updates if a new search is recived
|
||||
stopCurrentStepUpdates();
|
||||
}
|
||||
});
|
||||
|
||||
+124
-117
@@ -1,5 +1,25 @@
|
||||
// The config page (without the already stored name / addess pairs)
|
||||
module.exports = [
|
||||
// Navigation settings
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
// Description
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Navigation settings',
|
||||
},
|
||||
// Enable / disable real time navigation
|
||||
{
|
||||
type: 'toggle',
|
||||
messageKey: 'navigationAutoEnable',
|
||||
label: 'Enable automatic navigation',
|
||||
defaultValue: true,
|
||||
description: 'Automatic navigation tells you when to take a turn in real time based on the GPS of your phone. This feature does not require an active internet connection, once the route has been loaded. Disable this feature if you want to reduce battery usage on your phone.',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// The named addessses section
|
||||
{
|
||||
type: 'section',
|
||||
@@ -17,143 +37,130 @@ module.exports = [
|
||||
|
||||
// Address #1
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Address 1',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_0',
|
||||
label: 'Name',
|
||||
description: 'Use a name that makes sense to you, such as \'home\', \'my college\' or \'mom\'.',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_0',
|
||||
label: 'Address',
|
||||
description: 'The address should be as specific as possible. Something like \'Schleusenufer Kreuzberg, 10997 Berlin\'.',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
]
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_0',
|
||||
label: 'Name #1',
|
||||
description: 'Use a name that makes sense to you, such as \'home\', \'my college\' or \'mom\'.',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_0',
|
||||
label: 'Address #1',
|
||||
description: 'The address should be as specific as possible. Something like \'Schleusenufer Kreuzberg, 10997 Berlin\'.',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
// Address #2
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Address 2',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_1',
|
||||
label: 'Name',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_1',
|
||||
label: 'Address',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
]
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_1',
|
||||
label: 'Name #2',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_1',
|
||||
label: 'Address #2',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
// Address #3
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Address 3',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_2',
|
||||
label: 'Name',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_2',
|
||||
label: 'Address',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
]
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_2',
|
||||
label: 'Name #3',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_2',
|
||||
label: 'Address #3',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
// Address #4
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Address 4',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_3',
|
||||
label: 'Name',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_3',
|
||||
label: 'Address',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
]
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_3',
|
||||
label: 'Name #4',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_3',
|
||||
label: 'Address #4',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
|
||||
|
||||
// Address #4
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Address 5',
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_4',
|
||||
label: 'Name',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_4',
|
||||
label: 'Address',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
]
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressName_4',
|
||||
label: 'Name #5',
|
||||
attributes: {
|
||||
placeholder: 'e.g. home',
|
||||
},
|
||||
},
|
||||
{
|
||||
type: 'input',
|
||||
messageKey: 'namedAddressAddress_4',
|
||||
label: 'Address #5',
|
||||
attributes: {
|
||||
placeholder: 'e.g. Schleusenufer',
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Support / feedback stuff
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
// Description
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Feedback',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
defaultValue: 'To submit your feedback, please use this form: <a href="http://goo.gl/forms/KeN3q0oVqg9h4rWf1">FEEDBACK FORM</a> (save your preferences, before clicking the link).',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Api attribution stuff
|
||||
{
|
||||
type: 'section',
|
||||
items: [
|
||||
// Description
|
||||
{
|
||||
type: 'heading',
|
||||
defaultValue: 'Navigation data',
|
||||
},
|
||||
{
|
||||
type: 'text',
|
||||
defaultValue: 'The data is provided by the HERE API (https://developer.here.com).',
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
+44
-1
@@ -1,4 +1,6 @@
|
||||
// Functions to handle storing / retriving of the values
|
||||
|
||||
// Store the named addresses data
|
||||
function storeNamedAddresses(configDict) {
|
||||
// This array will hold the raw named addesses
|
||||
var namedAddressesNamesRaw = [];
|
||||
@@ -37,9 +39,10 @@ function storeNamedAddresses(configDict) {
|
||||
// Store the named addresses
|
||||
try {
|
||||
localStorage.setItem('namedAddresses', JSON.stringify(namedAddresses));
|
||||
} catch(e) {}
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Get the named addresses data (exposed)
|
||||
function getNamedAddresses() {
|
||||
// Load the stored data
|
||||
data = localStorage.getItem('namedAddresses');
|
||||
@@ -72,6 +75,44 @@ function getNamedAddresses() {
|
||||
return [];
|
||||
}
|
||||
|
||||
// Store the navigation settings
|
||||
function storeNavigationSettings(configDict) {
|
||||
// Settings object with default values
|
||||
var navigationSettings = {
|
||||
auto: true,
|
||||
};
|
||||
|
||||
// Automatic turn by turn navigation
|
||||
if (configDict.hasOwnProperty('navigationAutoEnable')) {
|
||||
navigationSettings.auto = !!configDict.navigationAutoEnable.value;
|
||||
}
|
||||
|
||||
// Store the settings
|
||||
try {
|
||||
localStorage.setItem('navigationSettings', JSON.stringify(navigationSettings));
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
// Get the navigation settings (exposed)
|
||||
function getNavigationSettings() {
|
||||
// Settings object with default values
|
||||
var navigationSettings = {
|
||||
auto: true,
|
||||
};
|
||||
|
||||
// Load the settings
|
||||
try {
|
||||
var navigationSettingsData = JSON.parse(localStorage.getItem('navigationSettings'));
|
||||
// Automatic turn by turn navigation
|
||||
if (navigationSettingsData.hasOwnProperty('navigationAutoEnable')) {
|
||||
navigationSettings.auto = !!navigationSettingsData.navigationAutoEnable;
|
||||
}
|
||||
} catch (e) {}
|
||||
|
||||
// Return the settings
|
||||
return navigationSettings;
|
||||
}
|
||||
|
||||
|
||||
// Clay things
|
||||
var Clay = require('pebble-clay');
|
||||
@@ -94,8 +135,10 @@ Pebble.addEventListener('webviewclosed', function(e) {
|
||||
// Store the addresses returned by the config page
|
||||
var configDict = clay.getSettings(e.response, false);
|
||||
storeNamedAddresses(configDict);
|
||||
storeNavigationSettings(configDict);
|
||||
});
|
||||
|
||||
|
||||
// Exports for use in the app.js
|
||||
module.exports.getNamedAddresses = getNamedAddresses;
|
||||
module.exports.getNavigationSettings = getNavigationSettings;
|
||||
|
||||
+43
-2
@@ -111,8 +111,14 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
|
||||
url = url.concat('&waypoint0=geo!').concat(fromLat).concat(',').concat(fromLon);
|
||||
url = url.concat('&waypoint1=geo!').concat(toLat).concat(',').concat(toLon);
|
||||
url = url.concat('&mode=fastest;').concat(modes[routeType]); /* selectes the transit method, e.g. teleportation / car / ... */
|
||||
if (modes[routeType] == 'publicTransport') {
|
||||
// Special url params for public transport routes
|
||||
url = url.concat('&departure=now&combineChange=true');
|
||||
}
|
||||
// Format the response
|
||||
url = url.concat('&routeattributes=none,summary,legs&routelegattributes=none,maneuvers&maneuverattributes=none,direction&instructionformat=text');
|
||||
url = url.concat('&routeattributes=none,summary,legs&routelegattributes=none,maneuvers&maneuverattributes=none,direction,position&instructionformat=text');
|
||||
// Log the final url (for rare use)
|
||||
//console.log(url);
|
||||
// Perform the request
|
||||
makeJsonHttpGetRequest(url, function(success, res) {
|
||||
if (success) {
|
||||
@@ -125,10 +131,16 @@ function loadRouteData(routeType, fromLat, fromLon, toLat, toLon, callback) {
|
||||
routeData.time = Math.ceil(res.response.route[0].summary.travelTime / 60); /* in minutes */
|
||||
// Get the steps
|
||||
routeData.stepList = [];
|
||||
routeData.stepPositionList = [];
|
||||
routeData.stepIconsString = '';
|
||||
res.response.route[0].leg[0].maneuver.forEach(function(step, index) {
|
||||
// Add the text
|
||||
routeData.stepList[index] = step.instruction;
|
||||
// Add the position
|
||||
routeData.stepPositionList[index] = {
|
||||
lat: step.position.latitude,
|
||||
lon: step.position.longitude,
|
||||
};
|
||||
// Add the icon
|
||||
if (res.response.route[0].leg[0].maneuver.length == index + 1) {
|
||||
// This is the last step, add the finished icon
|
||||
@@ -187,9 +199,38 @@ function createRoute(routeType, searchText, callback) {
|
||||
}
|
||||
// Helper function to define createRoute error callback all in one place
|
||||
function routeErrorCallback(callback) {
|
||||
callback(false, { distance: 0, time: 0, stepList: [], stepIconsString: '' });
|
||||
callback(false, { distance: 0, time: 0, stepList: [], stepPositionList: [], stepIconsString: '' });
|
||||
}
|
||||
|
||||
// Calculates the distance of two sets of coordinates (in meters)
|
||||
function getApproxDistance(fromLat, fromLon, toLat, toLon) {
|
||||
var p = 0.017453292519943295; // Math.PI / 180
|
||||
var c = Math.cos;
|
||||
var a = 0.5 - c((fromLat - toLat) * p)/2 +
|
||||
c(toLat * p) * c(fromLat * p) *
|
||||
(1 - c((fromLon - toLon) * p))/2;
|
||||
|
||||
return 12742000 * Math.asin(Math.sqrt(a)); // 2 * R; R = 6371000 m
|
||||
}
|
||||
|
||||
// Determine the current waypoint index, based on a list of waypoint coords [{lat,lon},...], the current position, and the current index
|
||||
function getCurrentStepIndex(steps, lat, lon, currentIndex) {
|
||||
if (steps instanceof Array && typeof lat === 'number' && typeof lon === 'number' && typeof currentIndex === 'number') {
|
||||
// Test is the distance to the next waypoint is smaller or equal to 10 m
|
||||
if (steps.length > currentIndex + 1 && getApproxDistance(lat, lon, steps[currentIndex + 1].lat, steps[currentIndex + 1].lon) <= 10) {
|
||||
// Move on to the next waypoint
|
||||
return currentIndex + 1;
|
||||
} else {
|
||||
// The current waypoint is either the last one or the next one is too far away
|
||||
return currentIndex;
|
||||
}
|
||||
}
|
||||
|
||||
// In case of an error, return 0 or the current index if it is a number
|
||||
return typeof currentIndex === 'number' ? currentIndex : 0;
|
||||
}
|
||||
|
||||
|
||||
// Exports
|
||||
module.exports.createRoute = createRoute;
|
||||
module.exports.getCurrentStepIndex = getCurrentStepIndex;
|
||||
|
||||
Reference in New Issue
Block a user