mirror of
https://gitlab.com/wgp/dougal/software.git
synced 2025-12-06 12:17:08 +00:00
Add vessel position to map.
Updates via websocket using the `realtime` channel notification message.
This commit is contained in:
@@ -9,10 +9,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@deck.gl/aggregation-layers": "^9.1.13",
|
"@deck.gl/aggregation-layers": "^9.1.13",
|
||||||
"@deck.gl/geo-layers": "^9.1.13",
|
"@deck.gl/geo-layers": "^9.1.13",
|
||||||
|
"@deck.gl/mesh-layers": "^9.1.14",
|
||||||
"@dougal/binary": "file:../../../modules/@dougal/binary",
|
"@dougal/binary": "file:../../../modules/@dougal/binary",
|
||||||
"@dougal/concurrency": "file:../../../modules/@dougal/concurrency",
|
"@dougal/concurrency": "file:../../../modules/@dougal/concurrency",
|
||||||
"@dougal/organisations": "file:../../../modules/@dougal/organisations",
|
"@dougal/organisations": "file:../../../modules/@dougal/organisations",
|
||||||
"@dougal/user": "file:../../../modules/@dougal/user",
|
"@dougal/user": "file:../../../modules/@dougal/user",
|
||||||
|
"@loaders.gl/obj": "^4.3.4",
|
||||||
"@mdi/font": "^7.2.96",
|
"@mdi/font": "^7.2.96",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
|
|||||||
406982
lib/www/client/source/public/assets/boat0.obj
Normal file
406982
lib/www/client/source/public/assets/boat0.obj
Normal file
File diff suppressed because it is too large
Load Diff
@@ -660,6 +660,7 @@ export default {
|
|||||||
maxPitch: 89
|
maxPitch: 89
|
||||||
},
|
},
|
||||||
|
|
||||||
|
vesselPosition: null,
|
||||||
vesselTrackConfig: {
|
vesselTrackConfig: {
|
||||||
lastRefresh: 0,
|
lastRefresh: 0,
|
||||||
refreshInterval: 12, // seconds
|
refreshInterval: 12, // seconds
|
||||||
@@ -1580,18 +1581,46 @@ export default {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
|
handleVesselPosition (context, {payload}) {
|
||||||
|
if (payload.new?.geometry?.coordinates) {
|
||||||
|
const now = Date.now();
|
||||||
|
const lastRefresh = this.vesselPosition?._lastRefresh;
|
||||||
|
|
||||||
|
// Limits refreshes to once every five seconds max
|
||||||
|
if (lastRefresh && (now-lastRefresh) < 5000) return;
|
||||||
|
|
||||||
|
this.vesselPosition = {
|
||||||
|
...payload.new.meta,
|
||||||
|
tstamp: payload.new.tstamp,
|
||||||
|
_lastRefresh: now
|
||||||
|
};
|
||||||
|
if (this.vesselPosition.lineStatus == "offline") {
|
||||||
|
this.vesselPosition.x = this.vesselPosition.longitude ?? payload.new.geometry.coordinates[0];
|
||||||
|
this.vesselPosition.y = this.vesselPosition.latitude ?? payload.new.geometry.coordinates[1];
|
||||||
|
} else {
|
||||||
|
this.vesselPosition.x = this.vesselPosition.longitudeMaster
|
||||||
|
?? payload.new.geometry.coordinates[0];
|
||||||
|
this.vesselPosition.y = this.vesselPosition.latitudeMaster
|
||||||
|
?? payload.new.geometry.coordinates[1];
|
||||||
|
}
|
||||||
|
this.render();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
registerNotificationHandlers (action = "registerHandler") {
|
registerNotificationHandlers (action = "registerHandler") {
|
||||||
|
|
||||||
["raw_lines", "raw_shots", "final_lines", "final_shots"].forEach( table => {
|
["raw_lines", "raw_shots", "final_lines", "final_shots"].forEach( table => {
|
||||||
this.$store.dispatch(action, {
|
this.$store.dispatch(action, {
|
||||||
table,
|
table,
|
||||||
|
handler: this.handleSequences
|
||||||
handler: (context, message) => {
|
|
||||||
this.handleSequences(context, message);
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.$store.dispatch(action, {
|
||||||
|
table: 'realtime',
|
||||||
|
handler: this.handleVesselPosition
|
||||||
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
unregisterNotificationHandlers () {
|
unregisterNotificationHandlers () {
|
||||||
|
|||||||
@@ -6,6 +6,8 @@ import { Deck, WebMercatorViewport, FlyToInterpolator, CompositeLayer } from '@d
|
|||||||
import { GeoJsonLayer, LineLayer, PathLayer, BitmapLayer, ScatterplotLayer, ColumnLayer, IconLayer } from '@deck.gl/layers';
|
import { GeoJsonLayer, LineLayer, PathLayer, BitmapLayer, ScatterplotLayer, ColumnLayer, IconLayer } from '@deck.gl/layers';
|
||||||
import {HeatmapLayer} from '@deck.gl/aggregation-layers';
|
import {HeatmapLayer} from '@deck.gl/aggregation-layers';
|
||||||
import { TileLayer, MVTLayer, TripsLayer } from '@deck.gl/geo-layers';
|
import { TileLayer, MVTLayer, TripsLayer } from '@deck.gl/geo-layers';
|
||||||
|
import { SimpleMeshLayer } from '@deck.gl/mesh-layers';
|
||||||
|
import { OBJLoader } from '@loaders.gl/obj';
|
||||||
|
|
||||||
//import { json } from 'd3-fetch';
|
//import { json } from 'd3-fetch';
|
||||||
import * as d3a from 'd3-array';
|
import * as d3a from 'd3-array';
|
||||||
@@ -254,29 +256,22 @@ export default {
|
|||||||
},
|
},
|
||||||
|
|
||||||
vesselTrackPointsLayer (options = {}) {
|
vesselTrackPointsLayer (options = {}) {
|
||||||
return new ScatterplotLayer({
|
|
||||||
|
if (!this.vesselPosition) return;
|
||||||
|
|
||||||
|
return new SimpleMeshLayer({
|
||||||
id: 'navp',
|
id: 'navp',
|
||||||
data: `/api/navdata?limit=100`,
|
data: [ this.vesselPosition ],
|
||||||
...this.loadOptions(),
|
getColor: [ 255, 48, 0 ],
|
||||||
getPosition: (d) => ([d.longitude, d.latitude]),
|
getOrientation: d => [0, (270 - (d.heading ?? d.cmg ?? d.bearing ?? d.lineBearing ?? 0)) % 360 , 0],
|
||||||
getRadius: d => (d.speed),
|
getPosition: d => [ d.x, d.y ],
|
||||||
radiusScale: 1,
|
mesh: `/assets/boat0.obj`,
|
||||||
lineWidthMinPixels: 2,
|
sizeScale: 0.1,
|
||||||
getFillColor: d => d.guns
|
loaders: [OBJLoader],
|
||||||
? d.lineStatus == "online"
|
|
||||||
? [0xaa, 0x00, 0xff] // Online
|
|
||||||
: [0xd5, 0x00, 0xf9] // Soft start or guns otherwise active
|
|
||||||
: [0xea, 0x80, 0xfc], // Offline, guns inactive
|
|
||||||
getLineColor: [127, 65, 90],
|
|
||||||
getColor: [ 255, 0, 0 ],
|
|
||||||
getPointRadius: 12,
|
|
||||||
radiusUnits: "pixels",
|
|
||||||
pointRadiusMinPixels: 4,
|
|
||||||
stroked: false,
|
|
||||||
filled: true,
|
|
||||||
pickable: true,
|
pickable: true,
|
||||||
...options
|
...options
|
||||||
})
|
});
|
||||||
|
|
||||||
},
|
},
|
||||||
|
|
||||||
vesselTrackLinesLayer (options = {}) {
|
vesselTrackLinesLayer (options = {}) {
|
||||||
|
|||||||
29
package-lock.json
generated
29
package-lock.json
generated
@@ -39,10 +39,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@deck.gl/aggregation-layers": "^9.1.13",
|
"@deck.gl/aggregation-layers": "^9.1.13",
|
||||||
"@deck.gl/geo-layers": "^9.1.13",
|
"@deck.gl/geo-layers": "^9.1.13",
|
||||||
|
"@deck.gl/mesh-layers": "^9.1.14",
|
||||||
"@dougal/binary": "file:../../../modules/@dougal/binary",
|
"@dougal/binary": "file:../../../modules/@dougal/binary",
|
||||||
"@dougal/concurrency": "file:../../../modules/@dougal/concurrency",
|
"@dougal/concurrency": "file:../../../modules/@dougal/concurrency",
|
||||||
"@dougal/organisations": "file:../../../modules/@dougal/organisations",
|
"@dougal/organisations": "file:../../../modules/@dougal/organisations",
|
||||||
"@dougal/user": "file:../../../modules/@dougal/user",
|
"@dougal/user": "file:../../../modules/@dougal/user",
|
||||||
|
"@loaders.gl/obj": "^4.3.4",
|
||||||
"@mdi/font": "^7.2.96",
|
"@mdi/font": "^7.2.96",
|
||||||
"buffer": "^6.0.3",
|
"buffer": "^6.0.3",
|
||||||
"core-js": "^3.6.5",
|
"core-js": "^3.6.5",
|
||||||
@@ -13493,19 +13495,18 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@deck.gl/mesh-layers": {
|
"node_modules/@deck.gl/mesh-layers": {
|
||||||
"version": "9.1.13",
|
"version": "9.1.14",
|
||||||
"resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-9.1.13.tgz",
|
"resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-9.1.14.tgz",
|
||||||
"integrity": "sha512-ujhe9FtB4qRRCXH/hY5p+IQ5VO/AC+/dtern6CTzYzjGnUnAvsbIgBZ3jxSlb1B/D3wlVE778W2cmv7MIToJJg==",
|
"integrity": "sha512-NVUw0yG4stJfrklWCGP9j8bNlf9YQc4PccMeNNIHNrU/Je6/Va6dJZg0RGtVkeaTY1Lk3A7wRzq8/M5Urfvuiw==",
|
||||||
"peer": true,
|
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@loaders.gl/gltf": "^4.2.0",
|
"@loaders.gl/gltf": "^4.2.0",
|
||||||
"@luma.gl/gltf": "^9.1.5",
|
"@luma.gl/gltf": "~9.1.9",
|
||||||
"@luma.gl/shadertools": "^9.1.5"
|
"@luma.gl/shadertools": "~9.1.9"
|
||||||
},
|
},
|
||||||
"peerDependencies": {
|
"peerDependencies": {
|
||||||
"@deck.gl/core": "^9.1.0",
|
"@deck.gl/core": "^9.1.0",
|
||||||
"@luma.gl/core": "^9.1.5",
|
"@luma.gl/core": "~9.1.9",
|
||||||
"@luma.gl/engine": "^9.1.5"
|
"@luma.gl/engine": "~9.1.9"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"node_modules/@dougal/binary": {
|
"node_modules/@dougal/binary": {
|
||||||
@@ -13700,6 +13701,18 @@
|
|||||||
"@loaders.gl/core": "^4.3.0"
|
"@loaders.gl/core": "^4.3.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"node_modules/@loaders.gl/obj": {
|
||||||
|
"version": "4.3.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/@loaders.gl/obj/-/obj-4.3.4.tgz",
|
||||||
|
"integrity": "sha512-Rdn+NHjLI0jKYrKNicJuQJohnHh7QAv4szCji8eafYYMrVtSIonNozBXUfe/c4V7HL/FVvvHCkfC66rvLvayaQ==",
|
||||||
|
"dependencies": {
|
||||||
|
"@loaders.gl/loader-utils": "4.3.4",
|
||||||
|
"@loaders.gl/schema": "4.3.4"
|
||||||
|
},
|
||||||
|
"peerDependencies": {
|
||||||
|
"@loaders.gl/core": "^4.3.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"node_modules/@loaders.gl/schema": {
|
"node_modules/@loaders.gl/schema": {
|
||||||
"version": "4.3.4",
|
"version": "4.3.4",
|
||||||
"resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-4.3.4.tgz",
|
"resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-4.3.4.tgz",
|
||||||
|
|||||||
Reference in New Issue
Block a user