mirror of https://github.com/espruino/BangleApps
gipy: elevation
parent
3a6eb8b2ad
commit
df46cd643e
|
@ -28,6 +28,7 @@ It provides the following features :
|
||||||
- toilets
|
- toilets
|
||||||
- artwork
|
- artwork
|
||||||
- bakeries
|
- bakeries
|
||||||
|
- display elevation data if available in the trace
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
@ -95,6 +96,12 @@ The distance to next point displayed corresponds to the length of the black segm
|
||||||
If you click the button you'll reach a menu where you can currently zoom out to see more of the map
|
If you click the button you'll reach a menu where you can currently zoom out to see more of the map
|
||||||
(with a slower refresh rate), reverse the path direction and disable power saving (keeping backlight on).
|
(with a slower refresh rate), reverse the path direction and disable power saving (keeping backlight on).
|
||||||
|
|
||||||
|
### Elevation
|
||||||
|
|
||||||
|
If you touch the screen you will switch between display modes.
|
||||||
|
The first one displays the map, the second one the nearby elevation and the last one the elevation
|
||||||
|
for the whole path.
|
||||||
|
|
||||||
### Settings
|
### Settings
|
||||||
|
|
||||||
Few settings for now (feel free to suggest me more) :
|
Few settings for now (feel free to suggest me more) :
|
||||||
|
|
|
@ -45,9 +45,6 @@ JIT: array declaration in jit is buggy
|
||||||
+ when lost we still get powersaving
|
+ when lost we still get powersaving
|
||||||
+ try disabling gps for more powersaving
|
+ try disabling gps for more powersaving
|
||||||
|
|
||||||
+ add heights
|
|
||||||
-> have two views: zoomed in and zoomed out
|
|
||||||
|
|
||||||
+ remove "lost" indicator and change position point's color instead
|
+ remove "lost" indicator and change position point's color instead
|
||||||
|
|
||||||
+ when you walk the direction still has a tendency to shift
|
+ when you walk the direction still has a tendency to shift
|
||||||
|
|
291
apps/gipy/app.js
291
apps/gipy/app.js
|
@ -15,9 +15,16 @@ let interests_colors = [
|
||||||
];
|
];
|
||||||
|
|
||||||
let Y_OFFSET = 20;
|
let Y_OFFSET = 20;
|
||||||
|
|
||||||
|
// some constants for screen types
|
||||||
|
let MAP = 0;
|
||||||
|
let HEIGHTS_ZOOMED_IN = 1;
|
||||||
|
let HEIGHTS_FULL = 2;
|
||||||
|
|
||||||
let s = require("Storage");
|
let s = require("Storage");
|
||||||
|
|
||||||
var settings = Object.assign({
|
var settings = Object.assign(
|
||||||
|
{
|
||||||
lost_distance: 50,
|
lost_distance: 50,
|
||||||
brightness: 0.5,
|
brightness: 0.5,
|
||||||
buzz_on_turns: false,
|
buzz_on_turns: false,
|
||||||
|
@ -141,7 +148,14 @@ class TilesOffsets {
|
||||||
|
|
||||||
// this function is not inlined to avoid array declaration in jit
|
// this function is not inlined to avoid array declaration in jit
|
||||||
function center_points(points, scaled_current_x, scaled_current_y) {
|
function center_points(points, scaled_current_x, scaled_current_y) {
|
||||||
return g.transformVertices(points, [1, 0, 0, 1, -scaled_current_x, -scaled_current_y]);
|
return g.transformVertices(points, [
|
||||||
|
1,
|
||||||
|
0,
|
||||||
|
0,
|
||||||
|
1,
|
||||||
|
-scaled_current_x,
|
||||||
|
-scaled_current_y,
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
// this function is not inlined to avoid array declaration in jit
|
// this function is not inlined to avoid array declaration in jit
|
||||||
|
@ -334,8 +348,10 @@ class Map {
|
||||||
let tile_center_y = (tile_y + 0.5) * side;
|
let tile_center_y = (tile_y + 0.5) * side;
|
||||||
let scaled_center_x = (tile_center_x - current_x) * scale_factor;
|
let scaled_center_x = (tile_center_x - current_x) * scale_factor;
|
||||||
let scaled_center_y = (tile_center_y - current_y) * scale_factor;
|
let scaled_center_y = (tile_center_y - current_y) * scale_factor;
|
||||||
let rotated_center_x = scaled_center_x * cos_direction - scaled_center_y * sin_direction;
|
let rotated_center_x =
|
||||||
let rotated_center_y = scaled_center_x * sin_direction + scaled_center_y * cos_direction;
|
scaled_center_x * cos_direction - scaled_center_y * sin_direction;
|
||||||
|
let rotated_center_y =
|
||||||
|
scaled_center_x * sin_direction + scaled_center_y * cos_direction;
|
||||||
let on_screen_center_x = center_x - rotated_center_x;
|
let on_screen_center_x = center_x - rotated_center_x;
|
||||||
let on_screen_center_y = center_y + rotated_center_y;
|
let on_screen_center_y = center_y + rotated_center_y;
|
||||||
|
|
||||||
|
@ -410,11 +426,24 @@ class Map {
|
||||||
let points = this.fetch_points(tile_x, tile_y, this.side * scale_factor);
|
let points = this.fetch_points(tile_x, tile_y, this.side * scale_factor);
|
||||||
let scaled_current_x = current_x * scale_factor;
|
let scaled_current_x = current_x * scale_factor;
|
||||||
let scaled_current_y = current_y * scale_factor;
|
let scaled_current_y = current_y * scale_factor;
|
||||||
let recentered_points = center_points(points, scaled_current_x, scaled_current_y);
|
let recentered_points = center_points(
|
||||||
let screen_points = rotate_points(recentered_points, cos_direction, sin_direction);
|
points,
|
||||||
|
scaled_current_x,
|
||||||
|
scaled_current_y
|
||||||
|
);
|
||||||
|
let screen_points = rotate_points(
|
||||||
|
recentered_points,
|
||||||
|
cos_direction,
|
||||||
|
sin_direction
|
||||||
|
);
|
||||||
|
|
||||||
for (let i = 0; i < screen_points.length; i += 4) {
|
for (let i = 0; i < screen_points.length; i += 4) {
|
||||||
g.drawLine(screen_points[i], screen_points[i + 1], screen_points[i + 2], screen_points[i + 3]);
|
g.drawLine(
|
||||||
|
screen_points[i],
|
||||||
|
screen_points[i + 1],
|
||||||
|
screen_points[i + 2],
|
||||||
|
screen_points[i + 3]
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,8 +461,16 @@ class Map {
|
||||||
let points = this.fetch_points(tile_x, tile_y, this.side * scale_factor);
|
let points = this.fetch_points(tile_x, tile_y, this.side * scale_factor);
|
||||||
let scaled_current_x = current_x * scale_factor;
|
let scaled_current_x = current_x * scale_factor;
|
||||||
let scaled_current_y = current_y * scale_factor;
|
let scaled_current_y = current_y * scale_factor;
|
||||||
let recentered_points = center_points(points, scaled_current_x, scaled_current_y);
|
let recentered_points = center_points(
|
||||||
let screen_points = rotate_points(recentered_points, cos_direction, sin_direction);
|
points,
|
||||||
|
scaled_current_x,
|
||||||
|
scaled_current_y
|
||||||
|
);
|
||||||
|
let screen_points = rotate_points(
|
||||||
|
recentered_points,
|
||||||
|
cos_direction,
|
||||||
|
sin_direction
|
||||||
|
);
|
||||||
|
|
||||||
for (let i = 0; i < screen_points.length; i += 4) {
|
for (let i = 0; i < screen_points.length; i += 4) {
|
||||||
let final_x = screen_points[i];
|
let final_x = screen_points[i];
|
||||||
|
@ -601,6 +638,7 @@ class Status {
|
||||||
this.maps = maps;
|
this.maps = maps;
|
||||||
this.interests = interests;
|
this.interests = interests;
|
||||||
this.heights = heights;
|
this.heights = heights;
|
||||||
|
this.screen = MAP;
|
||||||
let half_screen_width = g.getWidth() / 2;
|
let half_screen_width = g.getWidth() / 2;
|
||||||
let half_screen_height = g.getHeight() / 2;
|
let half_screen_height = g.getHeight() / 2;
|
||||||
let half_screen_diagonal = Math.sqrt(
|
let half_screen_diagonal = Math.sqrt(
|
||||||
|
@ -762,7 +800,6 @@ class Status {
|
||||||
});
|
});
|
||||||
Bangle.setPollInterval(2000); // disable accelerometer as much as we can (a value of 4000 seem to cause hard reboot crashes (segfaults ?) so keep 2000)
|
Bangle.setPollInterval(2000); // disable accelerometer as much as we can (a value of 4000 seem to cause hard reboot crashes (segfaults ?) so keep 2000)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
this.check_activity(); // if we don't move or are in menu we should stay on
|
this.check_activity(); // if we don't move or are in menu we should stay on
|
||||||
|
|
||||||
|
@ -954,6 +991,171 @@ class Status {
|
||||||
}
|
}
|
||||||
displaying = true;
|
displaying = true;
|
||||||
g.clear();
|
g.clear();
|
||||||
|
if (this.screen == MAP) {
|
||||||
|
this.display_map();
|
||||||
|
} else {
|
||||||
|
let current_position = 0;
|
||||||
|
if (this.current_segment !== null) {
|
||||||
|
current_position =
|
||||||
|
this.remaining_distances[0] - this.remaining_distance();
|
||||||
|
}
|
||||||
|
if (this.screen == HEIGHTS_FULL) {
|
||||||
|
this.display_heights(0, current_position, this.remaining_distances[0]);
|
||||||
|
} else {
|
||||||
|
// only display 2500m
|
||||||
|
let start;
|
||||||
|
if (go_backwards) {
|
||||||
|
start = Math.max(0, current_position - 2000);
|
||||||
|
} else {
|
||||||
|
start = Math.max(0, current_position - 500);
|
||||||
|
}
|
||||||
|
let length = Math.min(2500, this.remaining_distances[0] - start);
|
||||||
|
this.display_heights(start, current_position, length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Bangle.drawWidgets();
|
||||||
|
displaying = false;
|
||||||
|
}
|
||||||
|
display_heights(display_start, current_position, displayed_length) {
|
||||||
|
let path_length = this.remaining_distances[0];
|
||||||
|
let widgets_height = 24;
|
||||||
|
let graph_width = g.getWidth();
|
||||||
|
let graph_height = g.getHeight() - 20 - widgets_height;
|
||||||
|
|
||||||
|
let distance_per_pixel = displayed_length / graph_width;
|
||||||
|
|
||||||
|
let start_point_index = 0;
|
||||||
|
let end_point_index = this.remaining_distances.length - 1;
|
||||||
|
for (let i = 0; i < this.remaining_distances.length; i++) {
|
||||||
|
let point_distance = path_length - this.remaining_distances[i];
|
||||||
|
if (point_distance <= display_start) {
|
||||||
|
start_point_index = i;
|
||||||
|
}
|
||||||
|
if (point_distance >= display_start + displayed_length) {
|
||||||
|
end_point_index = i;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let max_height = Number.NEGATIVE_INFINITY;
|
||||||
|
let min_height = Number.POSITIVE_INFINITY;
|
||||||
|
for (let i = start_point_index; i <= end_point_index; i++) {
|
||||||
|
let height = this.heights[i];
|
||||||
|
max_height = Math.max(max_height, height);
|
||||||
|
min_height = Math.min(min_height, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
let displayed_height = max_height - min_height;
|
||||||
|
let height_per_pixel = displayed_height / graph_height;
|
||||||
|
// g.setColor(0, 0, 0).drawRect(0, widgets_height, graph_width, graph_height + widgets_height);
|
||||||
|
|
||||||
|
let previous_x = null;
|
||||||
|
let previous_y = null;
|
||||||
|
let previous_height = null;
|
||||||
|
let previous_distance = null;
|
||||||
|
let current_x;
|
||||||
|
let current_y;
|
||||||
|
for (let i = start_point_index; i < end_point_index; i++) {
|
||||||
|
let point_distance = path_length - this.remaining_distances[i];
|
||||||
|
let height = this.heights[i];
|
||||||
|
let x = Math.round((point_distance - display_start) / distance_per_pixel);
|
||||||
|
if (go_backwards) {
|
||||||
|
x = graph_width - x;
|
||||||
|
}
|
||||||
|
let y =
|
||||||
|
widgets_height +
|
||||||
|
graph_height -
|
||||||
|
Math.round((height - min_height) / height_per_pixel);
|
||||||
|
if (x != previous_x) {
|
||||||
|
if (previous_x !== null) {
|
||||||
|
let steepness =
|
||||||
|
(height - previous_height) / (point_distance - previous_distance);
|
||||||
|
if (go_backwards) {
|
||||||
|
steepness *= -1;
|
||||||
|
}
|
||||||
|
let color;
|
||||||
|
if (steepness > 0.15) {
|
||||||
|
color = "#ff0000";
|
||||||
|
} else if (steepness > 0.8) {
|
||||||
|
color = "#aa0000";
|
||||||
|
} else if (steepness > 0.03) {
|
||||||
|
color = "#ffff00";
|
||||||
|
} else if (steepness > -0.03) {
|
||||||
|
color = "#00ff00";
|
||||||
|
} else if (steepness > -0.08) {
|
||||||
|
color = "#00aa44";
|
||||||
|
} else if (steepness > -0.015) {
|
||||||
|
color = "#0044aa";
|
||||||
|
} else {
|
||||||
|
color = "#0000ff";
|
||||||
|
}
|
||||||
|
g.setColor(color);
|
||||||
|
g.fillPoly([
|
||||||
|
previous_x,
|
||||||
|
previous_y,
|
||||||
|
x,
|
||||||
|
y,
|
||||||
|
x,
|
||||||
|
widgets_height + graph_height,
|
||||||
|
previous_x,
|
||||||
|
widgets_height + graph_height,
|
||||||
|
]);
|
||||||
|
if (
|
||||||
|
current_position >= previous_distance &&
|
||||||
|
current_position < point_distance
|
||||||
|
) {
|
||||||
|
let current_height =
|
||||||
|
previous_height +
|
||||||
|
((current_position - previous_distance) /
|
||||||
|
(point_distance - previous_distance)) *
|
||||||
|
(height - previous_height);
|
||||||
|
current_x = Math.round(
|
||||||
|
(current_position - display_start) / distance_per_pixel
|
||||||
|
);
|
||||||
|
if (go_backwards) {
|
||||||
|
current_x = graph_width - current_x;
|
||||||
|
}
|
||||||
|
current_y =
|
||||||
|
widgets_height +
|
||||||
|
graph_height -
|
||||||
|
Math.round((current_height - min_height) / height_per_pixel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
previous_distance = point_distance;
|
||||||
|
previous_height = height;
|
||||||
|
previous_x = x;
|
||||||
|
previous_y = y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.setColor(0, 0, 0);
|
||||||
|
g.fillCircle(current_x, current_y, 5);
|
||||||
|
|
||||||
|
// display min dist/max dist and min height/max height
|
||||||
|
g.setColor(g.theme.fg);
|
||||||
|
g.setFont("6x8:2");
|
||||||
|
g.setFontAlign(-1, 1, 0).drawString(
|
||||||
|
Math.ceil(display_start / 100) / 10,
|
||||||
|
0,
|
||||||
|
g.getHeight()
|
||||||
|
);
|
||||||
|
|
||||||
|
g.setFontAlign(1, 1, 0).drawString(
|
||||||
|
Math.ceil((display_start + displayed_length) / 100) / 10,
|
||||||
|
g.getWidth(),
|
||||||
|
g.getHeight()
|
||||||
|
);
|
||||||
|
|
||||||
|
g.setFontAlign(1, 1, 0).drawString(
|
||||||
|
min_height,
|
||||||
|
g.getWidth(),
|
||||||
|
widgets_height + graph_height
|
||||||
|
);
|
||||||
|
g.setFontAlign(1, -1, 0).drawString(
|
||||||
|
max_height,
|
||||||
|
g.getWidth(),
|
||||||
|
widgets_height
|
||||||
|
);
|
||||||
|
}
|
||||||
|
display_map() {
|
||||||
let scale_factor = this.scale_factor;
|
let scale_factor = this.scale_factor;
|
||||||
if (!zoomed) {
|
if (!zoomed) {
|
||||||
scale_factor /= 2;
|
scale_factor /= 2;
|
||||||
|
@ -985,8 +1187,6 @@ class Status {
|
||||||
|
|
||||||
this.display_direction();
|
this.display_direction();
|
||||||
this.display_stats();
|
this.display_stats();
|
||||||
Bangle.drawWidgets();
|
|
||||||
displaying = false;
|
|
||||||
}
|
}
|
||||||
display_stats() {
|
display_stats() {
|
||||||
let now = new Date();
|
let now = new Date();
|
||||||
|
@ -1007,19 +1207,11 @@ class Status {
|
||||||
if (this.old_times.length > 0) {
|
if (this.old_times.length > 0) {
|
||||||
let point_time = this.old_times[this.old_times.length - 1];
|
let point_time = this.old_times[this.old_times.length - 1];
|
||||||
let done_in = point_time - this.starting_time;
|
let done_in = point_time - this.starting_time;
|
||||||
approximate_speed = Math.round(
|
approximate_speed = Math.round((this.advanced_distance * 3.6) / done_in);
|
||||||
(this.advanced_distance * 3.6) / done_in
|
|
||||||
);
|
|
||||||
let approximate_instant_speed = Math.round(this.instant_speed * 3.6);
|
let approximate_instant_speed = Math.round(this.instant_speed * 3.6);
|
||||||
g.setFont("6x8:2")
|
g.setFont("6x8:2")
|
||||||
.setFontAlign(-1, -1, 0)
|
.setFontAlign(-1, -1, 0)
|
||||||
.drawString(
|
.drawString("" + approximate_speed + "km/h", 0, g.getHeight() - 15);
|
||||||
"" +
|
|
||||||
approximate_speed +
|
|
||||||
"km/h",
|
|
||||||
0,
|
|
||||||
g.getHeight() - 15
|
|
||||||
);
|
|
||||||
|
|
||||||
g.setFont("6x8:3")
|
g.setFont("6x8:3")
|
||||||
.setFontAlign(1, -1, 0)
|
.setFontAlign(1, -1, 0)
|
||||||
|
@ -1191,8 +1383,8 @@ function load_gps(filename) {
|
||||||
} else if (block_type == 4) {
|
} else if (block_type == 4) {
|
||||||
console.log("loading heights");
|
console.log("loading heights");
|
||||||
let heights_number = path.points.length / 2;
|
let heights_number = path.points.length / 2;
|
||||||
heights = Float64Array(buffer, offset, heights_number);
|
heights = Int16Array(buffer, offset, heights_number);
|
||||||
offset += 8 * heights_number;
|
offset += 2 * heights_number;
|
||||||
} else {
|
} else {
|
||||||
console.log("todo : block type", block_type);
|
console.log("todo : block type", block_type);
|
||||||
}
|
}
|
||||||
|
@ -1202,7 +1394,7 @@ function load_gps(filename) {
|
||||||
if (offset != file_size) {
|
if (offset != file_size) {
|
||||||
console.log("invalid file size", file_size, "expected", offset);
|
console.log("invalid file size", file_size, "expected", offset);
|
||||||
let msg = "invalid file\nsize " + file_size + "\ninstead of" + offset;
|
let msg = "invalid file\nsize " + file_size + "\ninstead of" + offset;
|
||||||
E.showAlert(msg).then(function() {
|
E.showAlert(msg).then(function () {
|
||||||
E.showAlert();
|
E.showAlert();
|
||||||
start_gipy(path, maps, interests, heights);
|
start_gipy(path, maps, interests, heights);
|
||||||
});
|
});
|
||||||
|
@ -1377,18 +1569,17 @@ class Point {
|
||||||
|
|
||||||
let fake_gps_point = 0;
|
let fake_gps_point = 0;
|
||||||
|
|
||||||
|
|
||||||
function drawMenu() {
|
function drawMenu() {
|
||||||
const menu = {
|
const menu = {
|
||||||
"": {
|
"": {
|
||||||
title: "choose trace"
|
title: "choose trace",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
var files = s.list(".gps");
|
var files = s.list(".gps");
|
||||||
for (var i = 0; i < files.length; ++i) {
|
for (var i = 0; i < files.length; ++i) {
|
||||||
menu[files[i]] = start.bind(null, files[i]);
|
menu[files[i]] = start.bind(null, files[i]);
|
||||||
}
|
}
|
||||||
menu["Exit"] = function() {
|
menu["Exit"] = function () {
|
||||||
load();
|
load();
|
||||||
};
|
};
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
|
@ -1411,7 +1602,7 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
status = new Status(path, maps, interests, heights);
|
status = new Status(path, maps, interests, heights);
|
||||||
|
|
||||||
setWatch(
|
setWatch(
|
||||||
function() {
|
function () {
|
||||||
status.activate();
|
status.activate();
|
||||||
if (in_menu) {
|
if (in_menu) {
|
||||||
return;
|
return;
|
||||||
|
@ -1419,7 +1610,7 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
in_menu = true;
|
in_menu = true;
|
||||||
const menu = {
|
const menu = {
|
||||||
"": {
|
"": {
|
||||||
title: "choose action"
|
title: "choose action",
|
||||||
},
|
},
|
||||||
"Go Backward": {
|
"Go Backward": {
|
||||||
value: go_backwards,
|
value: go_backwards,
|
||||||
|
@ -1437,13 +1628,13 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
/*LANG*/
|
/*LANG*/
|
||||||
"powersaving": {
|
powersaving: {
|
||||||
value: powersaving,
|
value: powersaving,
|
||||||
onchange: (v) => {
|
onchange: (v) => {
|
||||||
powersaving = v;
|
powersaving = v;
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"back to map": function() {
|
},
|
||||||
|
"back to map": function () {
|
||||||
in_menu = false;
|
in_menu = false;
|
||||||
E.showMenu();
|
E.showMenu();
|
||||||
g.clear();
|
g.clear();
|
||||||
|
@ -1455,12 +1646,12 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
};
|
};
|
||||||
E.showMenu(menu);
|
E.showMenu(menu);
|
||||||
},
|
},
|
||||||
BTN1, {
|
BTN1,
|
||||||
repeat: true
|
{
|
||||||
|
repeat: true,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
if (status.path !== null) {
|
if (status.path !== null) {
|
||||||
let start = status.path.point(0);
|
let start = status.path.point(0);
|
||||||
status.displayed_position = start;
|
status.displayed_position = start;
|
||||||
|
@ -1470,10 +1661,22 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
first_map.start_coordinates[0] +
|
first_map.start_coordinates[0] +
|
||||||
(first_map.side * first_map.grid_size[0]) / 2,
|
(first_map.side * first_map.grid_size[0]) / 2,
|
||||||
first_map.start_coordinates[1] +
|
first_map.start_coordinates[1] +
|
||||||
(first_map.side * first_map.grid_size[1]) / 2);
|
(first_map.side * first_map.grid_size[1]) / 2
|
||||||
|
);
|
||||||
}
|
}
|
||||||
status.display();
|
status.display();
|
||||||
|
|
||||||
|
Bangle.on("touch", () => {
|
||||||
|
status.activate();
|
||||||
|
if (in_menu) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (status.heights !== null) {
|
||||||
|
status.screen = (status.screen + 1) % 3;
|
||||||
|
status.display();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
Bangle.on("stroke", (o) => {
|
Bangle.on("stroke", (o) => {
|
||||||
status.activate();
|
status.activate();
|
||||||
if (in_menu) {
|
if (in_menu) {
|
||||||
|
@ -1491,8 +1694,8 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
let s = status.adjusted_sin_direction;
|
let s = status.adjusted_sin_direction;
|
||||||
let rotated_x = xdiff * c - ydiff * s;
|
let rotated_x = xdiff * c - ydiff * s;
|
||||||
let rotated_y = xdiff * s + ydiff * c;
|
let rotated_y = xdiff * s + ydiff * c;
|
||||||
status.displayed_position.lon += 1.3 * rotated_x / status.scale_factor;
|
status.displayed_position.lon += (1.3 * rotated_x) / status.scale_factor;
|
||||||
status.displayed_position.lat -= 1.3 * rotated_y / status.scale_factor;
|
status.displayed_position.lat -= (1.3 * rotated_y) / status.scale_factor;
|
||||||
status.display();
|
status.display();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -1503,7 +1706,6 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
Bangle.setLCDPower(1);
|
Bangle.setLCDPower(1);
|
||||||
Bangle.loadWidgets(); // i don't know why i cannot load them at start : they would display on splash screen
|
Bangle.loadWidgets(); // i don't know why i cannot load them at start : they would display on splash screen
|
||||||
|
|
||||||
|
|
||||||
function simulate_gps(status) {
|
function simulate_gps(status) {
|
||||||
if (status.path === null) {
|
if (status.path === null) {
|
||||||
let map = status.maps[0];
|
let map = status.maps[0];
|
||||||
|
@ -1534,9 +1736,9 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
let pos = p1.times(1 - alpha).plus(p2.times(alpha));
|
let pos = p1.times(1 - alpha).plus(p2.times(alpha));
|
||||||
|
|
||||||
if (go_backwards) {
|
if (go_backwards) {
|
||||||
fake_gps_point -= 0.05; // advance simulation
|
fake_gps_point -= 0.2; // advance simulation
|
||||||
} else {
|
} else {
|
||||||
fake_gps_point += 0.05; // advance simulation
|
fake_gps_point += 0.2; // advance simulation
|
||||||
}
|
}
|
||||||
status.update_position(pos);
|
status.update_position(pos);
|
||||||
}
|
}
|
||||||
|
@ -1547,10 +1749,11 @@ function start_gipy(path, maps, interests, heights) {
|
||||||
status.activate();
|
status.activate();
|
||||||
|
|
||||||
let frame = 0;
|
let frame = 0;
|
||||||
let set_coordinates = function(data) {
|
let set_coordinates = function (data) {
|
||||||
frame += 1;
|
frame += 1;
|
||||||
// 0,0 coordinates are considered invalid since we sometimes receive them out of nowhere
|
// 0,0 coordinates are considered invalid since we sometimes receive them out of nowhere
|
||||||
let valid_coordinates = !isNaN(data.lat) &&
|
let valid_coordinates =
|
||||||
|
!isNaN(data.lat) &&
|
||||||
!isNaN(data.lon) &&
|
!isNaN(data.lon) &&
|
||||||
(data.lat != 0.0 || data.lon != 0.0);
|
(data.lat != 0.0 || data.lon != 0.0);
|
||||||
if (valid_coordinates) {
|
if (valid_coordinates) {
|
||||||
|
|
|
@ -12,6 +12,11 @@ export function get_gps_map_svg(gps: Gps): string;
|
||||||
export function get_polygon(gps: Gps): Float64Array;
|
export function get_polygon(gps: Gps): Float64Array;
|
||||||
/**
|
/**
|
||||||
* @param {Gps} gps
|
* @param {Gps} gps
|
||||||
|
* @returns {boolean}
|
||||||
|
*/
|
||||||
|
export function has_heights(gps: Gps): boolean;
|
||||||
|
/**
|
||||||
|
* @param {Gps} gps
|
||||||
* @returns {Float64Array}
|
* @returns {Float64Array}
|
||||||
*/
|
*/
|
||||||
export function get_polyline(gps: Gps): Float64Array;
|
export function get_polyline(gps: Gps): Float64Array;
|
||||||
|
@ -51,46 +56,3 @@ export function gps_from_area(xmin: number, ymin: number, xmax: number, ymax: nu
|
||||||
export class Gps {
|
export class Gps {
|
||||||
free(): void;
|
free(): void;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembly.Module;
|
|
||||||
|
|
||||||
export interface InitOutput {
|
|
||||||
readonly memory: WebAssembly.Memory;
|
|
||||||
readonly __wbg_gps_free: (a: number) => void;
|
|
||||||
readonly get_gps_map_svg: (a: number, b: number) => void;
|
|
||||||
readonly get_polygon: (a: number, b: number) => void;
|
|
||||||
readonly get_polyline: (a: number, b: number) => void;
|
|
||||||
readonly get_gps_content: (a: number, b: number) => void;
|
|
||||||
readonly request_map: (a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number) => number;
|
|
||||||
readonly load_gps_from_string: (a: number, b: number) => number;
|
|
||||||
readonly gps_from_area: (a: number, b: number, c: number, d: number) => number;
|
|
||||||
readonly __wbindgen_malloc: (a: number) => number;
|
|
||||||
readonly __wbindgen_realloc: (a: number, b: number, c: number) => number;
|
|
||||||
readonly __wbindgen_export_2: WebAssembly.Table;
|
|
||||||
readonly _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__heb2f4d39a212d7d1: (a: number, b: number, c: number) => void;
|
|
||||||
readonly __wbindgen_add_to_stack_pointer: (a: number) => number;
|
|
||||||
readonly __wbindgen_free: (a: number, b: number) => void;
|
|
||||||
readonly __wbindgen_exn_store: (a: number) => void;
|
|
||||||
readonly wasm_bindgen__convert__closures__invoke2_mut__h362f82c7669db137: (a: number, b: number, c: number, d: number) => void;
|
|
||||||
}
|
|
||||||
|
|
||||||
export type SyncInitInput = BufferSource | WebAssembly.Module;
|
|
||||||
/**
|
|
||||||
* Instantiates the given `module`, which can either be bytes or
|
|
||||||
* a precompiled `WebAssembly.Module`.
|
|
||||||
*
|
|
||||||
* @param {SyncInitInput} module
|
|
||||||
*
|
|
||||||
* @returns {InitOutput}
|
|
||||||
*/
|
|
||||||
export function initSync(module: SyncInitInput): InitOutput;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* If `module_or_path` is {RequestInfo} or {URL}, makes a request and
|
|
||||||
* for everything else, calls `WebAssembly.instantiate` directly.
|
|
||||||
*
|
|
||||||
* @param {InitInput | Promise<InitInput>} module_or_path
|
|
||||||
*
|
|
||||||
* @returns {Promise<InitOutput>}
|
|
||||||
*/
|
|
||||||
export default function init (module_or_path?: InitInput | Promise<InitInput>): Promise<InitOutput>;
|
|
||||||
|
|
|
@ -1,733 +1,2 @@
|
||||||
|
import * as wasm from "./gps_bg.wasm";
|
||||||
let wasm;
|
export * from "./gps_bg.js";
|
||||||
|
|
||||||
const heap = new Array(32).fill(undefined);
|
|
||||||
|
|
||||||
heap.push(undefined, null, true, false);
|
|
||||||
|
|
||||||
function getObject(idx) { return heap[idx]; }
|
|
||||||
|
|
||||||
let WASM_VECTOR_LEN = 0;
|
|
||||||
|
|
||||||
let cachedUint8Memory0 = new Uint8Array();
|
|
||||||
|
|
||||||
function getUint8Memory0() {
|
|
||||||
if (cachedUint8Memory0.byteLength === 0) {
|
|
||||||
cachedUint8Memory0 = new Uint8Array(wasm.memory.buffer);
|
|
||||||
}
|
|
||||||
return cachedUint8Memory0;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cachedTextEncoder = new TextEncoder('utf-8');
|
|
||||||
|
|
||||||
const encodeString = (typeof cachedTextEncoder.encodeInto === 'function'
|
|
||||||
? function (arg, view) {
|
|
||||||
return cachedTextEncoder.encodeInto(arg, view);
|
|
||||||
}
|
|
||||||
: function (arg, view) {
|
|
||||||
const buf = cachedTextEncoder.encode(arg);
|
|
||||||
view.set(buf);
|
|
||||||
return {
|
|
||||||
read: arg.length,
|
|
||||||
written: buf.length
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
function passStringToWasm0(arg, malloc, realloc) {
|
|
||||||
|
|
||||||
if (realloc === undefined) {
|
|
||||||
const buf = cachedTextEncoder.encode(arg);
|
|
||||||
const ptr = malloc(buf.length);
|
|
||||||
getUint8Memory0().subarray(ptr, ptr + buf.length).set(buf);
|
|
||||||
WASM_VECTOR_LEN = buf.length;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
let len = arg.length;
|
|
||||||
let ptr = malloc(len);
|
|
||||||
|
|
||||||
const mem = getUint8Memory0();
|
|
||||||
|
|
||||||
let offset = 0;
|
|
||||||
|
|
||||||
for (; offset < len; offset++) {
|
|
||||||
const code = arg.charCodeAt(offset);
|
|
||||||
if (code > 0x7F) break;
|
|
||||||
mem[ptr + offset] = code;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset !== len) {
|
|
||||||
if (offset !== 0) {
|
|
||||||
arg = arg.slice(offset);
|
|
||||||
}
|
|
||||||
ptr = realloc(ptr, len, len = offset + arg.length * 3);
|
|
||||||
const view = getUint8Memory0().subarray(ptr + offset, ptr + len);
|
|
||||||
const ret = encodeString(arg, view);
|
|
||||||
|
|
||||||
offset += ret.written;
|
|
||||||
}
|
|
||||||
|
|
||||||
WASM_VECTOR_LEN = offset;
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
function isLikeNone(x) {
|
|
||||||
return x === undefined || x === null;
|
|
||||||
}
|
|
||||||
|
|
||||||
let cachedInt32Memory0 = new Int32Array();
|
|
||||||
|
|
||||||
function getInt32Memory0() {
|
|
||||||
if (cachedInt32Memory0.byteLength === 0) {
|
|
||||||
cachedInt32Memory0 = new Int32Array(wasm.memory.buffer);
|
|
||||||
}
|
|
||||||
return cachedInt32Memory0;
|
|
||||||
}
|
|
||||||
|
|
||||||
let heap_next = heap.length;
|
|
||||||
|
|
||||||
function dropObject(idx) {
|
|
||||||
if (idx < 36) return;
|
|
||||||
heap[idx] = heap_next;
|
|
||||||
heap_next = idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
function takeObject(idx) {
|
|
||||||
const ret = getObject(idx);
|
|
||||||
dropObject(idx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
const cachedTextDecoder = new TextDecoder('utf-8', { ignoreBOM: true, fatal: true });
|
|
||||||
|
|
||||||
cachedTextDecoder.decode();
|
|
||||||
|
|
||||||
function getStringFromWasm0(ptr, len) {
|
|
||||||
return cachedTextDecoder.decode(getUint8Memory0().subarray(ptr, ptr + len));
|
|
||||||
}
|
|
||||||
|
|
||||||
function addHeapObject(obj) {
|
|
||||||
if (heap_next === heap.length) heap.push(heap.length + 1);
|
|
||||||
const idx = heap_next;
|
|
||||||
heap_next = heap[idx];
|
|
||||||
|
|
||||||
heap[idx] = obj;
|
|
||||||
return idx;
|
|
||||||
}
|
|
||||||
|
|
||||||
function debugString(val) {
|
|
||||||
// primitive types
|
|
||||||
const type = typeof val;
|
|
||||||
if (type == 'number' || type == 'boolean' || val == null) {
|
|
||||||
return `${val}`;
|
|
||||||
}
|
|
||||||
if (type == 'string') {
|
|
||||||
return `"${val}"`;
|
|
||||||
}
|
|
||||||
if (type == 'symbol') {
|
|
||||||
const description = val.description;
|
|
||||||
if (description == null) {
|
|
||||||
return 'Symbol';
|
|
||||||
} else {
|
|
||||||
return `Symbol(${description})`;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (type == 'function') {
|
|
||||||
const name = val.name;
|
|
||||||
if (typeof name == 'string' && name.length > 0) {
|
|
||||||
return `Function(${name})`;
|
|
||||||
} else {
|
|
||||||
return 'Function';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// objects
|
|
||||||
if (Array.isArray(val)) {
|
|
||||||
const length = val.length;
|
|
||||||
let debug = '[';
|
|
||||||
if (length > 0) {
|
|
||||||
debug += debugString(val[0]);
|
|
||||||
}
|
|
||||||
for(let i = 1; i < length; i++) {
|
|
||||||
debug += ', ' + debugString(val[i]);
|
|
||||||
}
|
|
||||||
debug += ']';
|
|
||||||
return debug;
|
|
||||||
}
|
|
||||||
// Test for built-in
|
|
||||||
const builtInMatches = /\[object ([^\]]+)\]/.exec(toString.call(val));
|
|
||||||
let className;
|
|
||||||
if (builtInMatches.length > 1) {
|
|
||||||
className = builtInMatches[1];
|
|
||||||
} else {
|
|
||||||
// Failed to match the standard '[object ClassName]'
|
|
||||||
return toString.call(val);
|
|
||||||
}
|
|
||||||
if (className == 'Object') {
|
|
||||||
// we're a user defined class or Object
|
|
||||||
// JSON.stringify avoids problems with cycles, and is generally much
|
|
||||||
// easier than looping through ownProperties of `val`.
|
|
||||||
try {
|
|
||||||
return 'Object(' + JSON.stringify(val) + ')';
|
|
||||||
} catch (_) {
|
|
||||||
return 'Object';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// errors
|
|
||||||
if (val instanceof Error) {
|
|
||||||
return `${val.name}: ${val.message}\n${val.stack}`;
|
|
||||||
}
|
|
||||||
// TODO we could test for more things here, like `Set`s and `Map`s.
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
|
|
||||||
function makeMutClosure(arg0, arg1, dtor, f) {
|
|
||||||
const state = { a: arg0, b: arg1, cnt: 1, dtor };
|
|
||||||
const real = (...args) => {
|
|
||||||
// First up with a closure we increment the internal reference
|
|
||||||
// count. This ensures that the Rust closure environment won't
|
|
||||||
// be deallocated while we're invoking it.
|
|
||||||
state.cnt++;
|
|
||||||
const a = state.a;
|
|
||||||
state.a = 0;
|
|
||||||
try {
|
|
||||||
return f(a, state.b, ...args);
|
|
||||||
} finally {
|
|
||||||
if (--state.cnt === 0) {
|
|
||||||
wasm.__wbindgen_export_2.get(state.dtor)(a, state.b);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
state.a = a;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
real.original = state;
|
|
||||||
|
|
||||||
return real;
|
|
||||||
}
|
|
||||||
function __wbg_adapter_24(arg0, arg1, arg2) {
|
|
||||||
wasm._dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__heb2f4d39a212d7d1(arg0, arg1, addHeapObject(arg2));
|
|
||||||
}
|
|
||||||
|
|
||||||
function _assertClass(instance, klass) {
|
|
||||||
if (!(instance instanceof klass)) {
|
|
||||||
throw new Error(`expected instance of ${klass.name}`);
|
|
||||||
}
|
|
||||||
return instance.ptr;
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {Gps} gps
|
|
||||||
* @returns {string}
|
|
||||||
*/
|
|
||||||
export function get_gps_map_svg(gps) {
|
|
||||||
try {
|
|
||||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
||||||
_assertClass(gps, Gps);
|
|
||||||
wasm.get_gps_map_svg(retptr, gps.ptr);
|
|
||||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
|
||||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
|
||||||
return getStringFromWasm0(r0, r1);
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
||||||
wasm.__wbindgen_free(r0, r1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let cachedFloat64Memory0 = new Float64Array();
|
|
||||||
|
|
||||||
function getFloat64Memory0() {
|
|
||||||
if (cachedFloat64Memory0.byteLength === 0) {
|
|
||||||
cachedFloat64Memory0 = new Float64Array(wasm.memory.buffer);
|
|
||||||
}
|
|
||||||
return cachedFloat64Memory0;
|
|
||||||
}
|
|
||||||
|
|
||||||
function getArrayF64FromWasm0(ptr, len) {
|
|
||||||
return getFloat64Memory0().subarray(ptr / 8, ptr / 8 + len);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {Gps} gps
|
|
||||||
* @returns {Float64Array}
|
|
||||||
*/
|
|
||||||
export function get_polygon(gps) {
|
|
||||||
try {
|
|
||||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
||||||
_assertClass(gps, Gps);
|
|
||||||
wasm.get_polygon(retptr, gps.ptr);
|
|
||||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
|
||||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
|
||||||
var v0 = getArrayF64FromWasm0(r0, r1).slice();
|
|
||||||
wasm.__wbindgen_free(r0, r1 * 8);
|
|
||||||
return v0;
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Gps} gps
|
|
||||||
* @returns {Float64Array}
|
|
||||||
*/
|
|
||||||
export function get_polyline(gps) {
|
|
||||||
try {
|
|
||||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
||||||
_assertClass(gps, Gps);
|
|
||||||
wasm.get_polyline(retptr, gps.ptr);
|
|
||||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
|
||||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
|
||||||
var v0 = getArrayF64FromWasm0(r0, r1).slice();
|
|
||||||
wasm.__wbindgen_free(r0, r1 * 8);
|
|
||||||
return v0;
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getArrayU8FromWasm0(ptr, len) {
|
|
||||||
return getUint8Memory0().subarray(ptr / 1, ptr / 1 + len);
|
|
||||||
}
|
|
||||||
/**
|
|
||||||
* @param {Gps} gps
|
|
||||||
* @returns {Uint8Array}
|
|
||||||
*/
|
|
||||||
export function get_gps_content(gps) {
|
|
||||||
try {
|
|
||||||
const retptr = wasm.__wbindgen_add_to_stack_pointer(-16);
|
|
||||||
_assertClass(gps, Gps);
|
|
||||||
wasm.get_gps_content(retptr, gps.ptr);
|
|
||||||
var r0 = getInt32Memory0()[retptr / 4 + 0];
|
|
||||||
var r1 = getInt32Memory0()[retptr / 4 + 1];
|
|
||||||
var v0 = getArrayU8FromWasm0(r0, r1).slice();
|
|
||||||
wasm.__wbindgen_free(r0, r1 * 1);
|
|
||||||
return v0;
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_add_to_stack_pointer(16);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {Gps} gps
|
|
||||||
* @param {string} key1
|
|
||||||
* @param {string} value1
|
|
||||||
* @param {string} key2
|
|
||||||
* @param {string} value2
|
|
||||||
* @param {string} key3
|
|
||||||
* @param {string} value3
|
|
||||||
* @param {string} key4
|
|
||||||
* @param {string} value4
|
|
||||||
* @returns {Promise<void>}
|
|
||||||
*/
|
|
||||||
export function request_map(gps, key1, value1, key2, value2, key3, value3, key4, value4) {
|
|
||||||
_assertClass(gps, Gps);
|
|
||||||
const ptr0 = passStringToWasm0(key1, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
const ptr1 = passStringToWasm0(value1, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len1 = WASM_VECTOR_LEN;
|
|
||||||
const ptr2 = passStringToWasm0(key2, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len2 = WASM_VECTOR_LEN;
|
|
||||||
const ptr3 = passStringToWasm0(value2, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len3 = WASM_VECTOR_LEN;
|
|
||||||
const ptr4 = passStringToWasm0(key3, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len4 = WASM_VECTOR_LEN;
|
|
||||||
const ptr5 = passStringToWasm0(value3, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len5 = WASM_VECTOR_LEN;
|
|
||||||
const ptr6 = passStringToWasm0(key4, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len6 = WASM_VECTOR_LEN;
|
|
||||||
const ptr7 = passStringToWasm0(value4, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len7 = WASM_VECTOR_LEN;
|
|
||||||
const ret = wasm.request_map(gps.ptr, ptr0, len0, ptr1, len1, ptr2, len2, ptr3, len3, ptr4, len4, ptr5, len5, ptr6, len6, ptr7, len7);
|
|
||||||
return takeObject(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {string} input
|
|
||||||
* @returns {Gps}
|
|
||||||
*/
|
|
||||||
export function load_gps_from_string(input) {
|
|
||||||
const ptr0 = passStringToWasm0(input, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
const ret = wasm.load_gps_from_string(ptr0, len0);
|
|
||||||
return Gps.__wrap(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param {number} xmin
|
|
||||||
* @param {number} ymin
|
|
||||||
* @param {number} xmax
|
|
||||||
* @param {number} ymax
|
|
||||||
* @returns {Gps}
|
|
||||||
*/
|
|
||||||
export function gps_from_area(xmin, ymin, xmax, ymax) {
|
|
||||||
const ret = wasm.gps_from_area(xmin, ymin, xmax, ymax);
|
|
||||||
return Gps.__wrap(ret);
|
|
||||||
}
|
|
||||||
|
|
||||||
function handleError(f, args) {
|
|
||||||
try {
|
|
||||||
return f.apply(this, args);
|
|
||||||
} catch (e) {
|
|
||||||
wasm.__wbindgen_exn_store(addHeapObject(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
function __wbg_adapter_84(arg0, arg1, arg2, arg3) {
|
|
||||||
wasm.wasm_bindgen__convert__closures__invoke2_mut__h362f82c7669db137(arg0, arg1, addHeapObject(arg2), addHeapObject(arg3));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*/
|
|
||||||
export class Gps {
|
|
||||||
|
|
||||||
static __wrap(ptr) {
|
|
||||||
const obj = Object.create(Gps.prototype);
|
|
||||||
obj.ptr = ptr;
|
|
||||||
|
|
||||||
return obj;
|
|
||||||
}
|
|
||||||
|
|
||||||
__destroy_into_raw() {
|
|
||||||
const ptr = this.ptr;
|
|
||||||
this.ptr = 0;
|
|
||||||
|
|
||||||
return ptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
free() {
|
|
||||||
const ptr = this.__destroy_into_raw();
|
|
||||||
wasm.__wbg_gps_free(ptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function load(module, imports) {
|
|
||||||
if (typeof Response === 'function' && module instanceof Response) {
|
|
||||||
if (typeof WebAssembly.instantiateStreaming === 'function') {
|
|
||||||
try {
|
|
||||||
return await WebAssembly.instantiateStreaming(module, imports);
|
|
||||||
|
|
||||||
} catch (e) {
|
|
||||||
if (module.headers.get('Content-Type') != 'application/wasm') {
|
|
||||||
console.warn("`WebAssembly.instantiateStreaming` failed because your server does not serve wasm with `application/wasm` MIME type. Falling back to `WebAssembly.instantiate` which is slower. Original error:\n", e);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const bytes = await module.arrayBuffer();
|
|
||||||
return await WebAssembly.instantiate(bytes, imports);
|
|
||||||
|
|
||||||
} else {
|
|
||||||
const instance = await WebAssembly.instantiate(module, imports);
|
|
||||||
|
|
||||||
if (instance instanceof WebAssembly.Instance) {
|
|
||||||
return { instance, module };
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function getImports() {
|
|
||||||
const imports = {};
|
|
||||||
imports.wbg = {};
|
|
||||||
imports.wbg.__wbg_log_d04343b58be82b0f = function(arg0, arg1) {
|
|
||||||
console.log(getStringFromWasm0(arg0, arg1));
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_string_get = function(arg0, arg1) {
|
|
||||||
const obj = getObject(arg1);
|
|
||||||
const ret = typeof(obj) === 'string' ? obj : undefined;
|
|
||||||
var ptr0 = isLikeNone(ret) ? 0 : passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
var len0 = WASM_VECTOR_LEN;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_object_drop_ref = function(arg0) {
|
|
||||||
takeObject(arg0);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_string_new = function(arg0, arg1) {
|
|
||||||
const ret = getStringFromWasm0(arg0, arg1);
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_fetch_57429b87be3dcc33 = function(arg0) {
|
|
||||||
const ret = fetch(getObject(arg0));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_object_clone_ref = function(arg0) {
|
|
||||||
const ret = getObject(arg0);
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_fetch_749a56934f95c96c = function(arg0, arg1) {
|
|
||||||
const ret = getObject(arg0).fetch(getObject(arg1));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_signal_31753ac644b25fbb = function(arg0) {
|
|
||||||
const ret = getObject(arg0).signal;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_new_6396e586b56e1dff = function() { return handleError(function () {
|
|
||||||
const ret = new AbortController();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_abort_064ae59cda5cd244 = function(arg0) {
|
|
||||||
getObject(arg0).abort();
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_newwithstrandinit_05d7180788420c40 = function() { return handleError(function (arg0, arg1, arg2) {
|
|
||||||
const ret = new Request(getStringFromWasm0(arg0, arg1), getObject(arg2));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_new_2d0053ee81e4dd2a = function() { return handleError(function () {
|
|
||||||
const ret = new Headers();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_append_de37df908812970d = function() { return handleError(function (arg0, arg1, arg2, arg3, arg4) {
|
|
||||||
getObject(arg0).append(getStringFromWasm0(arg1, arg2), getStringFromWasm0(arg3, arg4));
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_instanceof_Response_eaa426220848a39e = function(arg0) {
|
|
||||||
let result;
|
|
||||||
try {
|
|
||||||
result = getObject(arg0) instanceof Response;
|
|
||||||
} catch {
|
|
||||||
result = false;
|
|
||||||
}
|
|
||||||
const ret = result;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_url_74285ddf2747cb3d = function(arg0, arg1) {
|
|
||||||
const ret = getObject(arg1).url;
|
|
||||||
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_status_c4ef3dd591e63435 = function(arg0) {
|
|
||||||
const ret = getObject(arg0).status;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_headers_fd64ad685cf22e5d = function(arg0) {
|
|
||||||
const ret = getObject(arg0).headers;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_text_1169d752cc697903 = function() { return handleError(function (arg0) {
|
|
||||||
const ret = getObject(arg0).text();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_new_abda76e883ba8a5f = function() {
|
|
||||||
const ret = new Error();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_stack_658279fe44541cf6 = function(arg0, arg1) {
|
|
||||||
const ret = getObject(arg1).stack;
|
|
||||||
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_error_f851667af71bcfc6 = function(arg0, arg1) {
|
|
||||||
try {
|
|
||||||
console.error(getStringFromWasm0(arg0, arg1));
|
|
||||||
} finally {
|
|
||||||
wasm.__wbindgen_free(arg0, arg1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_cb_drop = function(arg0) {
|
|
||||||
const obj = takeObject(arg0).original;
|
|
||||||
if (obj.cnt-- == 1) {
|
|
||||||
obj.a = 0;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
const ret = false;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_is_object = function(arg0) {
|
|
||||||
const val = getObject(arg0);
|
|
||||||
const ret = typeof(val) === 'object' && val !== null;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_newnoargs_b5b063fc6c2f0376 = function(arg0, arg1) {
|
|
||||||
const ret = new Function(getStringFromWasm0(arg0, arg1));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_next_579e583d33566a86 = function(arg0) {
|
|
||||||
const ret = getObject(arg0).next;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_is_function = function(arg0) {
|
|
||||||
const ret = typeof(getObject(arg0)) === 'function';
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_value_1ccc36bc03462d71 = function(arg0) {
|
|
||||||
const ret = getObject(arg0).value;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_iterator_6f9d4f28845f426c = function() {
|
|
||||||
const ret = Symbol.iterator;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_new_0b9bfdd97583284e = function() {
|
|
||||||
const ret = new Object();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_self_6d479506f72c6a71 = function() { return handleError(function () {
|
|
||||||
const ret = self.self;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_window_f2557cc78490aceb = function() { return handleError(function () {
|
|
||||||
const ret = window.window;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_globalThis_7f206bda628d5286 = function() { return handleError(function () {
|
|
||||||
const ret = globalThis.globalThis;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_global_ba75c50d1cf384f4 = function() { return handleError(function () {
|
|
||||||
const ret = global.global;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbindgen_is_undefined = function(arg0) {
|
|
||||||
const ret = getObject(arg0) === undefined;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_call_97ae9d8645dc388b = function() { return handleError(function (arg0, arg1) {
|
|
||||||
const ret = getObject(arg0).call(getObject(arg1));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_call_168da88779e35f61 = function() { return handleError(function (arg0, arg1, arg2) {
|
|
||||||
const ret = getObject(arg0).call(getObject(arg1), getObject(arg2));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_next_aaef7c8aa5e212ac = function() { return handleError(function (arg0) {
|
|
||||||
const ret = getObject(arg0).next();
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_done_1b73b0672e15f234 = function(arg0) {
|
|
||||||
const ret = getObject(arg0).done;
|
|
||||||
return ret;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_new_9962f939219f1820 = function(arg0, arg1) {
|
|
||||||
try {
|
|
||||||
var state0 = {a: arg0, b: arg1};
|
|
||||||
var cb0 = (arg0, arg1) => {
|
|
||||||
const a = state0.a;
|
|
||||||
state0.a = 0;
|
|
||||||
try {
|
|
||||||
return __wbg_adapter_84(a, state0.b, arg0, arg1);
|
|
||||||
} finally {
|
|
||||||
state0.a = a;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
const ret = new Promise(cb0);
|
|
||||||
return addHeapObject(ret);
|
|
||||||
} finally {
|
|
||||||
state0.a = state0.b = 0;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_resolve_99fe17964f31ffc0 = function(arg0) {
|
|
||||||
const ret = Promise.resolve(getObject(arg0));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_then_11f7a54d67b4bfad = function(arg0, arg1) {
|
|
||||||
const ret = getObject(arg0).then(getObject(arg1));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_then_cedad20fbbd9418a = function(arg0, arg1, arg2) {
|
|
||||||
const ret = getObject(arg0).then(getObject(arg1), getObject(arg2));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_buffer_3f3d764d4747d564 = function(arg0) {
|
|
||||||
const ret = getObject(arg0).buffer;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_newwithbyteoffsetandlength_d9aa266703cb98be = function(arg0, arg1, arg2) {
|
|
||||||
const ret = new Uint8Array(getObject(arg0), arg1 >>> 0, arg2 >>> 0);
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_new_8c3f0052272a457a = function(arg0) {
|
|
||||||
const ret = new Uint8Array(getObject(arg0));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbg_get_765201544a2b6869 = function() { return handleError(function (arg0, arg1) {
|
|
||||||
const ret = Reflect.get(getObject(arg0), getObject(arg1));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_has_8359f114ce042f5a = function() { return handleError(function (arg0, arg1) {
|
|
||||||
const ret = Reflect.has(getObject(arg0), getObject(arg1));
|
|
||||||
return ret;
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_set_bf3f89b92d5a34bf = function() { return handleError(function (arg0, arg1, arg2) {
|
|
||||||
const ret = Reflect.set(getObject(arg0), getObject(arg1), getObject(arg2));
|
|
||||||
return ret;
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbg_stringify_d6471d300ded9b68 = function() { return handleError(function (arg0) {
|
|
||||||
const ret = JSON.stringify(getObject(arg0));
|
|
||||||
return addHeapObject(ret);
|
|
||||||
}, arguments) };
|
|
||||||
imports.wbg.__wbindgen_debug_string = function(arg0, arg1) {
|
|
||||||
const ret = debugString(getObject(arg1));
|
|
||||||
const ptr0 = passStringToWasm0(ret, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
||||||
const len0 = WASM_VECTOR_LEN;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 1] = len0;
|
|
||||||
getInt32Memory0()[arg0 / 4 + 0] = ptr0;
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_throw = function(arg0, arg1) {
|
|
||||||
throw new Error(getStringFromWasm0(arg0, arg1));
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_memory = function() {
|
|
||||||
const ret = wasm.memory;
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
imports.wbg.__wbindgen_closure_wrapper2245 = function(arg0, arg1, arg2) {
|
|
||||||
const ret = makeMutClosure(arg0, arg1, 267, __wbg_adapter_24);
|
|
||||||
return addHeapObject(ret);
|
|
||||||
};
|
|
||||||
|
|
||||||
return imports;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initMemory(imports, maybe_memory) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
function finalizeInit(instance, module) {
|
|
||||||
wasm = instance.exports;
|
|
||||||
init.__wbindgen_wasm_module = module;
|
|
||||||
cachedFloat64Memory0 = new Float64Array();
|
|
||||||
cachedInt32Memory0 = new Int32Array();
|
|
||||||
cachedUint8Memory0 = new Uint8Array();
|
|
||||||
|
|
||||||
|
|
||||||
return wasm;
|
|
||||||
}
|
|
||||||
|
|
||||||
function initSync(module) {
|
|
||||||
const imports = getImports();
|
|
||||||
|
|
||||||
initMemory(imports);
|
|
||||||
|
|
||||||
if (!(module instanceof WebAssembly.Module)) {
|
|
||||||
module = new WebAssembly.Module(module);
|
|
||||||
}
|
|
||||||
|
|
||||||
const instance = new WebAssembly.Instance(module, imports);
|
|
||||||
|
|
||||||
return finalizeInit(instance, module);
|
|
||||||
}
|
|
||||||
|
|
||||||
async function init(input) {
|
|
||||||
if (typeof input === 'undefined') {
|
|
||||||
input = new URL('gps_bg.wasm', import.meta.url);
|
|
||||||
}
|
|
||||||
const imports = getImports();
|
|
||||||
|
|
||||||
if (typeof input === 'string' || (typeof Request === 'function' && input instanceof Request) || (typeof URL === 'function' && input instanceof URL)) {
|
|
||||||
input = fetch(input);
|
|
||||||
}
|
|
||||||
|
|
||||||
initMemory(imports);
|
|
||||||
|
|
||||||
const { instance, module } = await load(await input, imports);
|
|
||||||
|
|
||||||
return finalizeInit(instance, module);
|
|
||||||
}
|
|
||||||
|
|
||||||
export { initSync }
|
|
||||||
export default init;
|
|
Binary file not shown.
|
@ -4,6 +4,7 @@ export const memory: WebAssembly.Memory;
|
||||||
export function __wbg_gps_free(a: number): void;
|
export function __wbg_gps_free(a: number): void;
|
||||||
export function get_gps_map_svg(a: number, b: number): void;
|
export function get_gps_map_svg(a: number, b: number): void;
|
||||||
export function get_polygon(a: number, b: number): void;
|
export function get_polygon(a: number, b: number): void;
|
||||||
|
export function has_heights(a: number): number;
|
||||||
export function get_polyline(a: number, b: number): void;
|
export function get_polyline(a: number, b: number): void;
|
||||||
export function get_gps_content(a: number, b: number): void;
|
export function get_gps_content(a: number, b: number): void;
|
||||||
export function request_map(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number): number;
|
export function request_map(a: number, b: number, c: number, d: number, e: number, f: number, g: number, h: number, i: number, j: number, k: number, l: number, m: number, n: number, o: number, p: number, q: number): number;
|
||||||
|
@ -12,8 +13,8 @@ export function gps_from_area(a: number, b: number, c: number, d: number): numbe
|
||||||
export function __wbindgen_malloc(a: number): number;
|
export function __wbindgen_malloc(a: number): number;
|
||||||
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
export function __wbindgen_realloc(a: number, b: number, c: number): number;
|
||||||
export const __wbindgen_export_2: WebAssembly.Table;
|
export const __wbindgen_export_2: WebAssembly.Table;
|
||||||
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__heb2f4d39a212d7d1(a: number, b: number, c: number): void;
|
export function _dyn_core__ops__function__FnMut__A____Output___R_as_wasm_bindgen__closure__WasmClosure___describe__invoke__hb15c13006e54cdd7(a: number, b: number, c: number): void;
|
||||||
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
export function __wbindgen_add_to_stack_pointer(a: number): number;
|
||||||
export function __wbindgen_free(a: number, b: number): void;
|
export function __wbindgen_free(a: number, b: number): void;
|
||||||
export function __wbindgen_exn_store(a: number): void;
|
export function __wbindgen_exn_store(a: number): void;
|
||||||
export function wasm_bindgen__convert__closures__invoke2_mut__h362f82c7669db137(a: number, b: number, c: number, d: number): void;
|
export function wasm_bindgen__convert__closures__invoke2_mut__h4d77bafb1e69a027(a: number, b: number, c: number, d: number): void;
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
"files": [
|
"files": [
|
||||||
"gps_bg.wasm",
|
"gps_bg.wasm",
|
||||||
"gps.js",
|
"gps.js",
|
||||||
|
"gps_bg.js",
|
||||||
"gps.d.ts"
|
"gps.d.ts"
|
||||||
],
|
],
|
||||||
"module": "gps.js",
|
"module": "gps.js",
|
||||||
|
|
Loading…
Reference in New Issue