();
+
+ // Get most visit points
+ data.forEach(beat => {
+ // Only if accuracy is low enough
+ if (beat.accuracy < 35) {
+ data.forEach(beat2 => {
+ const isNearPoint = isPointInRadius(
+ { lat: beat2.coordinate[0], lng: beat2.coordinate[1] },
+ { lat: beat.coordinate[0], lng: beat.coordinate[1] },
+ 0.025
+ );
+
+ if (isNearPoint) {
+ if (mostVisit.has(beat2._id)) {
+ mostVisit.set(beat2._id, mostVisit.get(beat2._id) + 1);
+ } else {
+ mostVisit.set(beat2._id, 1);
+ }
+ }
+ });
+ }
+ });
+
+ console.log(`worker response to`, mostVisit);
+ postMessage(mostVisit);
+});
diff --git a/frontend/src/app/map/map.component.html b/frontend/src/app/map/map.component.html
index 83ca540..e4138a6 100644
--- a/frontend/src/app/map/map.component.html
+++ b/frontend/src/app/map/map.component.html
@@ -23,4 +23,17 @@
source="lastLoc"
[paint]="lastLocationPaint"
>
+
+
+ Compute heat map, please wait ...
+
+
+
+
\ No newline at end of file
diff --git a/frontend/src/app/map/map.component.ts b/frontend/src/app/map/map.component.ts
index a496f2b..6029673 100644
--- a/frontend/src/app/map/map.component.ts
+++ b/frontend/src/app/map/map.component.ts
@@ -10,6 +10,7 @@ export class MapComponent {
lastLocation: number[] = [0, 0];
showMap = false;
+ heatmapPending = false;
data: GeoJSON.FeatureCollection = {
type: 'FeatureCollection', features: [
@@ -126,15 +127,16 @@ export class MapComponent {
if (beats.length === 0) { return; }
this.update();
+ this.buildMap(beats.length === 1);
this.lastLocationPaint['circle-radius'].stops[1][1] = this.metersToPixelsAtMaxZoom(
beats[beats.length - 1].accuracy, this.lastLocation[0]
);
this.lastLocationPaint = { ...this.lastLocationPaint };
+ });
- this.api.maxAccuracy.subscribe(val => {
- this.buildMap(val);
- });
+ this.api.maxAccuracy.subscribe(val => {
+ this.buildMap(false, val);
});
}
@@ -145,22 +147,7 @@ export class MapComponent {
return meters / 0.075 / Math.cos(latitude * Math.PI / 180);
}
- /* Function to find out if a provided point is in the area from
- https://stackoverflow.com/questions/24680247/check-if-a-latitude-and-longitude-is-within-a-circle-google-maps
- */
- private isPointInRadius(checkPoint: { lat: number, lng: number }, centerPoint: { lat: number, lng: number }, km: number): boolean {
- const ky = 40000 / 360;
- const kx = Math.cos(Math.PI * centerPoint.lat / 180.0) * ky;
- const dx = Math.abs(centerPoint.lng - checkPoint.lng) * kx;
- const dy = Math.abs(centerPoint.lat - checkPoint.lat) * ky;
- return Math.sqrt(dx * dx + dy * dy) <= km;
- }
-
async update(): Promise {
- this.data.features[0].geometry.coordinates = [];
-
- this.buildMap();
-
this.lastLocation = [this.api.beats[this.api.beats.length - 1].coordinate[1],
this.api.beats[this.api.beats.length - 1].coordinate[0]];
@@ -170,46 +157,56 @@ export class MapComponent {
this.showMap = true;
}
- buildMap(maxAccuracy: number = 30): void {
- const mostVisit = new Map();
- this.data.features[0].geometry.coordinates = [];
- this.mostVisitData.features[0].geometry.coordinates = [];
+ buildMap(isUpdate: boolean, maxAccuracy: number = 30): void {
+ console.log(isUpdate);
- for (let i = 0; i < this.api.beats.length; i++) {
- const beat = this.api.beats[i];
- if (beat.accuracy > maxAccuracy) { continue; }
- this.data.features[0].geometry.coordinates.push([beat.coordinate[1], beat.coordinate[0]]);
+ // If this is an update don't rebuild entire map.
+ if (!isUpdate) {
+ console.log('Clear');
- // Get most visit points
- for (let b = 0; b < this.api.beats.length; b++) {
- const beat2 = this.api.beats[b];
- const isNearPoint = this.isPointInRadius(
- { lat: beat2.coordinate[0], lng: beat2.coordinate[1] },
- { lat: beat.coordinate[0], lng: beat.coordinate[1] },
- 0.02
- );
+ this.data.features[0].geometry.coordinates = [];
+ this.mostVisitData.features[0].geometry.coordinates = [];
- if (isNearPoint) {
- if (mostVisit.has(beat2._id)) {
- mostVisit.set(beat2._id, mostVisit.get(beat2._id) + 1);
- } else {
- mostVisit.set(beat2._id, 1);
- }
+ this.api.beats.forEach(beat => {
+ if (beat.accuracy < maxAccuracy) {
+ this.data.features[0].geometry.coordinates.push([beat.coordinate[1], beat.coordinate[0]]);
}
+ });
+ } else {
+ console.log('Just push');
+
+ if (this.api.getLastBeat().accuracy < maxAccuracy) {
+ this.data.features[0].geometry.coordinates.push([this.api.getLastBeat().coordinate[1], this.api.getLastBeat().coordinate[0]]);
}
}
- for (const [key, value] of mostVisit) {
- if (value < 2) { continue; }
- this.api.beats.forEach(beat => {
- if (beat._id === key) {
- this.mostVisitData.features[0].geometry.coordinates.push([beat.coordinate[1], beat.coordinate[0]]);
- }
- });
- }
-
this.data = { ... this.data };
- this.mostVisitData = { ... this.mostVisitData };
+ console.log('After update / clear:', this.data);
+
+ // Let worker compute heatmap
+ if (typeof Worker !== 'undefined') {
+ const worker = new Worker('../map.worker', { type: 'module' });
+ this.heatmapPending = true;
+ worker.onmessage = ({ data }) => {
+ for (const [key, value] of data) {
+ if (value < 3) { continue; }
+
+ // Find beat with id
+ this.api.beats.forEach(beat => {
+ if (beat._id === key) {
+ this.mostVisitData.features[0].geometry.coordinates.push([beat.coordinate[1], beat.coordinate[0]]);
+ }
+ });
+ }
+ worker.terminate();
+ this.heatmapPending = false;
+ this.mostVisitData = { ... this.mostVisitData };
+ };
+
+ worker.postMessage(isUpdate ? [this.api.getLastBeat()] : this.api.beats);
+ } else {
+ // TODO: Support older browsers
+ }
}
}
diff --git a/frontend/src/assets/icons/icon-128x128.png b/frontend/src/assets/icons/icon-128x128.png
new file mode 100644
index 0000000..9f9241f
Binary files /dev/null and b/frontend/src/assets/icons/icon-128x128.png differ
diff --git a/frontend/src/assets/icons/icon-144x144.png b/frontend/src/assets/icons/icon-144x144.png
new file mode 100644
index 0000000..4a5f8c1
Binary files /dev/null and b/frontend/src/assets/icons/icon-144x144.png differ
diff --git a/frontend/src/assets/icons/icon-152x152.png b/frontend/src/assets/icons/icon-152x152.png
new file mode 100644
index 0000000..34a1a8d
Binary files /dev/null and b/frontend/src/assets/icons/icon-152x152.png differ
diff --git a/frontend/src/assets/icons/icon-192x192.png b/frontend/src/assets/icons/icon-192x192.png
new file mode 100644
index 0000000..9172e5d
Binary files /dev/null and b/frontend/src/assets/icons/icon-192x192.png differ
diff --git a/frontend/src/assets/icons/icon-384x384.png b/frontend/src/assets/icons/icon-384x384.png
new file mode 100644
index 0000000..e54e8d3
Binary files /dev/null and b/frontend/src/assets/icons/icon-384x384.png differ
diff --git a/frontend/src/assets/icons/icon-512x512.png b/frontend/src/assets/icons/icon-512x512.png
new file mode 100644
index 0000000..51ee297
Binary files /dev/null and b/frontend/src/assets/icons/icon-512x512.png differ
diff --git a/frontend/src/assets/icons/icon-72x72.png b/frontend/src/assets/icons/icon-72x72.png
new file mode 100644
index 0000000..2814a3f
Binary files /dev/null and b/frontend/src/assets/icons/icon-72x72.png differ
diff --git a/frontend/src/assets/icons/icon-96x96.png b/frontend/src/assets/icons/icon-96x96.png
new file mode 100644
index 0000000..d271025
Binary files /dev/null and b/frontend/src/assets/icons/icon-96x96.png differ
diff --git a/frontend/src/index.html b/frontend/src/index.html
index b9e2ee2..4a56e41 100644
--- a/frontend/src/index.html
+++ b/frontend/src/index.html
@@ -6,8 +6,11 @@
+
+
+