parent
304269b996
commit
826781647e
@ -0,0 +1,3 @@
|
|||||||
|
{
|
||||||
|
"C_Cpp.default.configurationProvider": "go2sh.cmake-integration"
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,37 @@
|
|||||||
|
<template>
|
||||||
|
|
||||||
|
<section class="ai-layer">
|
||||||
|
<h1>ai-layer Component</h1>
|
||||||
|
</section>
|
||||||
|
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script lang="js">
|
||||||
|
import {aiLayer} from '../phi/AILayer'
|
||||||
|
|
||||||
|
export default {
|
||||||
|
/* eslint-disable */
|
||||||
|
name: 'ai-layer',
|
||||||
|
props: [],
|
||||||
|
mounted () {
|
||||||
|
this.aiLayer = aiLayer({url: this.$store.state.Settings.settings.phi_url})
|
||||||
|
this.aiLayer.addTo(this.$parent.mapObject)
|
||||||
|
},
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
methods: {
|
||||||
|
|
||||||
|
},
|
||||||
|
computed: {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style scoped lang="scss">
|
||||||
|
.ai-layer {
|
||||||
|
|
||||||
|
}
|
||||||
|
</style>
|
@ -0,0 +1,268 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
const $ = require('jquery');
|
||||||
|
|
||||||
|
const aiAircraftMarker = require('./AircraftMarker').default;
|
||||||
|
|
||||||
|
var aiLayerLookup = {};
|
||||||
|
|
||||||
|
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||||
|
|
||||||
|
var metersPerPixel = function (latitude, zoomLevel) {
|
||||||
|
var earthCircumference = 40075017;
|
||||||
|
var latitudeRadians = latitude * (Math.PI / 180);
|
||||||
|
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
var pixelValue = function (latitude, meters, zoomLevel) {
|
||||||
|
return meters / metersPerPixel(latitude, zoomLevel);
|
||||||
|
};
|
||||||
|
|
||||||
|
function mapSGPropertyNode(node) {
|
||||||
|
var o = {};
|
||||||
|
node.children.forEach(child => {
|
||||||
|
if (child.nChildren > 0) {
|
||||||
|
o[child['name']] = mapSGPropertyNode(child);
|
||||||
|
} else {
|
||||||
|
switch (child.type) {
|
||||||
|
case "string":
|
||||||
|
o[child['name']] = child.value;
|
||||||
|
break;
|
||||||
|
case "bool":
|
||||||
|
o[child['name']] = Boolean(child.value);
|
||||||
|
break;
|
||||||
|
case "double":
|
||||||
|
case "int":
|
||||||
|
o[child['name']] = child.value;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
o.name = node.name;
|
||||||
|
o.index = node.index;
|
||||||
|
o.path = node.path;
|
||||||
|
return o;
|
||||||
|
}
|
||||||
|
|
||||||
|
(function (factory) {
|
||||||
|
if (typeof define === "function" && define.amd) {
|
||||||
|
// AMD. Register as an anonymous module.
|
||||||
|
define([
|
||||||
|
'knockout', 'leaflet', 'props'
|
||||||
|
], factory);
|
||||||
|
} else {
|
||||||
|
// Browser globals
|
||||||
|
factory();
|
||||||
|
}
|
||||||
|
}(function (ko, leaflet, SGPropertyNode) {
|
||||||
|
|
||||||
|
var AITypeToCssClassMap = {
|
||||||
|
aircraft: "ai-aircraft-marker-icon",
|
||||||
|
multiplayer: "mp-aircraft-marker-icon"
|
||||||
|
}
|
||||||
|
|
||||||
|
function formatFL(num) {
|
||||||
|
return "F" + ("000" + (num / 100).toFixed(0)).substr(-3, 3);
|
||||||
|
}
|
||||||
|
|
||||||
|
function ViewModel(h, l) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
self.heading = h;
|
||||||
|
self.labelLines = l;
|
||||||
|
}
|
||||||
|
|
||||||
|
L.AILayer = L.GeoJSON.extend({
|
||||||
|
options: {
|
||||||
|
pointToLayer: function (feature, latlng) {
|
||||||
|
var options = {
|
||||||
|
title: feature.properties.callsign,
|
||||||
|
alt: feature.properties.callsign,
|
||||||
|
riseOnHover: true,
|
||||||
|
draggable: true,
|
||||||
|
};
|
||||||
|
|
||||||
|
var aiMarker = null;
|
||||||
|
|
||||||
|
if (feature.properties.type == "aircraft") {
|
||||||
|
if (aiLayerLookup[feature.id] === undefined) {
|
||||||
|
aiMarker = aiAircraftMarker(latlng, feature.properties);
|
||||||
|
aiMarker.on('add', function (e) {
|
||||||
|
});
|
||||||
|
aiMarker.options.draggable = true;
|
||||||
|
//We can't drag multiplayer
|
||||||
|
if (feature.properties.type == "aircraft") {
|
||||||
|
aiMarker.on('dragstart', function (evt) {
|
||||||
|
evt.target.isDragging = true;
|
||||||
|
});
|
||||||
|
|
||||||
|
aiMarker.on('dragend', function (evt) {
|
||||||
|
if (evt.target !== this)
|
||||||
|
return;
|
||||||
|
var pos = evt.target.getLatLng();
|
||||||
|
|
||||||
|
var props = {
|
||||||
|
name: "position",
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
name: "latitude-deg",
|
||||||
|
value: pos.lat,
|
||||||
|
}, {
|
||||||
|
name: "longitude-deg",
|
||||||
|
value: pos.lng,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
|
$.post("json" + feature.properties.path, JSON.stringify(props));
|
||||||
|
evt.target.isDragging = false;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
aiLayerLookup[feature.id] = aiMarker;
|
||||||
|
return aiMarker;
|
||||||
|
} else {
|
||||||
|
var aiMarker = aiLayerLookup[feature.id];
|
||||||
|
aiMarker.setLatLng({lat: feature.geometry.coordinates[1],
|
||||||
|
lng: feature.geometry.coordinates[0]});
|
||||||
|
aiMarker.updateProperties(feature.properties);
|
||||||
|
return aiMarker;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// onEachFeature : function(feature, layer) {
|
||||||
|
// },
|
||||||
|
},
|
||||||
|
|
||||||
|
onAdd: function (map) {
|
||||||
|
L.GeoJSON.prototype.onAdd.call(this, map);
|
||||||
|
this.update(++this.updateId);
|
||||||
|
},
|
||||||
|
|
||||||
|
onRemove: function (map) {
|
||||||
|
this.updateId++;
|
||||||
|
L.GeoJSON.prototype.onRemove.call(this, map);
|
||||||
|
},
|
||||||
|
|
||||||
|
stop: function () {
|
||||||
|
this.updateId++;
|
||||||
|
},
|
||||||
|
|
||||||
|
// Refresh method called every 10s to reload other aircraft
|
||||||
|
updateId: 0,
|
||||||
|
update: function (id) {
|
||||||
|
var self = this;
|
||||||
|
|
||||||
|
if (self.updateId != id)
|
||||||
|
return;
|
||||||
|
|
||||||
|
var url = this.options.url + "/json/ai/models?d=99";
|
||||||
|
var jqxhr = $.get(url).done(function (data) {
|
||||||
|
try {
|
||||||
|
self.clearLayers();
|
||||||
|
self.addData(self.aiPropsToGeoJson(data, [
|
||||||
|
"aircraft", "multiplayer", "carrier"
|
||||||
|
], self._map.getBounds()));
|
||||||
|
} catch (error) {
|
||||||
|
console.error(error);
|
||||||
|
|
||||||
|
}
|
||||||
|
}).fail(function (a, b) {
|
||||||
|
self.updateId++;
|
||||||
|
// alert('failed to load AI data');
|
||||||
|
}).always(function () {
|
||||||
|
});
|
||||||
|
|
||||||
|
if (self.updateId == id) {
|
||||||
|
setTimeout(function () {
|
||||||
|
self.update(id)
|
||||||
|
}, 10000);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
// Builds the GeoJSON representation of AI, Multiplayer and Carriers
|
||||||
|
aiPropsToGeoJson: function (props, types, bounds) {
|
||||||
|
var geoJSON = {
|
||||||
|
type: "FeatureCollection",
|
||||||
|
features: [],
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
types.forEach(function (type) {
|
||||||
|
props.children.filter(childObject => childObject.path.includes(type))
|
||||||
|
.map(mapSGPropertyNode)
|
||||||
|
.forEach(function (child) {
|
||||||
|
|
||||||
|
if (!child["valid"])
|
||||||
|
return;
|
||||||
|
|
||||||
|
var path = child.path;
|
||||||
|
var position = child.position;
|
||||||
|
var orientation = child.orientation;
|
||||||
|
var velocities = child.velocities;
|
||||||
|
var lon = position["longitude-deg"];
|
||||||
|
var lat = position["latitude-deg"];
|
||||||
|
if (false == bounds.contains(L.latLng(lat, lon))) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var alt = position["altitude-ft"];
|
||||||
|
var heading = orientation["true-heading-deg"];
|
||||||
|
var id = child.id;
|
||||||
|
var callsign = "";
|
||||||
|
var name = "";
|
||||||
|
var speed = 0;
|
||||||
|
var departureAirportId = "";
|
||||||
|
var arrivalAirportId = "";
|
||||||
|
if (type == "multiplayer") {
|
||||||
|
name = child["sim"]["model"]["path"];
|
||||||
|
}
|
||||||
|
if (type == "carrier") {
|
||||||
|
callsign = child["sign"];
|
||||||
|
name = child["name"];
|
||||||
|
speed = velocities["speed-kts"];
|
||||||
|
} else {
|
||||||
|
callsign = child["callsign"];
|
||||||
|
speed = velocities["true-airspeed-kt"];
|
||||||
|
departureAirportId = child["departure-airport-id"];
|
||||||
|
arrivalAirportId = child["arrival-airport-id"];
|
||||||
|
}
|
||||||
|
|
||||||
|
geoJSON.features.push({
|
||||||
|
"type": "Feature",
|
||||||
|
"geometry": {
|
||||||
|
"type": "Point",
|
||||||
|
"coordinates": [
|
||||||
|
lon, lat, alt.toFixed(0)
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"id": id,
|
||||||
|
"properties": {
|
||||||
|
"path": path,
|
||||||
|
"type": type,
|
||||||
|
"heading": heading.toFixed(0),
|
||||||
|
"speed": speed.toFixed(0),
|
||||||
|
"callsign": callsign,
|
||||||
|
"name": name,
|
||||||
|
"departureAirportId": departureAirportId,
|
||||||
|
"arrivalAirportId": arrivalAirportId,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
return geoJSON;
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
L.aiLayer = function (options) {
|
||||||
|
return new L.AILayer(null, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
}));
|
||||||
|
|
||||||
|
export function aiLayer(options) {
|
||||||
|
return new L.AILayer(null, options);
|
||||||
|
}
|
@ -0,0 +1,87 @@
|
|||||||
|
/* eslint-disable */
|
||||||
|
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
|
||||||
|
/**http://wiki.openstreetmap.org/wiki/Zoom_levels*/
|
||||||
|
|
||||||
|
var metersPerPixel = function (latitude, zoomLevel) {
|
||||||
|
var earthCircumference = 40075017;
|
||||||
|
var latitudeRadians = latitude * (Math.PI / 180);
|
||||||
|
return earthCircumference * Math.cos(latitudeRadians) / Math.pow(2, zoomLevel + 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
var pixelValue = function (latitude, meters, zoomLevel) {
|
||||||
|
return meters / metersPerPixel(latitude, zoomLevel);
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
function stripSVG(fName) {
|
||||||
|
var rx = /<\s*svg[^>]*>([\s\S]*)<\s*\/svg[^>]*>/gm;
|
||||||
|
var svg = fs.readFileSync(path.join(__static, '/', fName), 'utf8');
|
||||||
|
var svg2 = rx.exec(svg);
|
||||||
|
return svg2[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
const airLinerSVG = stripSVG('Airplane_silhouette.svg');
|
||||||
|
const gaSVG = stripSVG('Black_aircraft_icon.svg');
|
||||||
|
|
||||||
|
L.AircraftMarker = L.Marker.extend({
|
||||||
|
options: {
|
||||||
|
zIndexOffset: 10000,
|
||||||
|
},
|
||||||
|
|
||||||
|
initialize: function (latlng, options) {
|
||||||
|
L.Marker.prototype.initialize(latlng, options);
|
||||||
|
L.Util.setOptions(this, options);
|
||||||
|
this.heading = options.heading;
|
||||||
|
this.updateIcon();
|
||||||
|
|
||||||
|
this.isDragging = false;
|
||||||
|
|
||||||
|
},
|
||||||
|
updateProperties: function(properties) {
|
||||||
|
this.heading = properties.heading;
|
||||||
|
this.updateIcon();
|
||||||
|
},
|
||||||
|
updateIcon : function() {
|
||||||
|
if(this._map !== undefined && this._map !== null) {
|
||||||
|
var metersPP = metersPerPixel(this._map.getCenter().lat, this._map.getZoom());
|
||||||
|
console.log(metersPP);
|
||||||
|
var scale = 0.07 / metersPP;
|
||||||
|
this.setIcon(L.divIcon({
|
||||||
|
iconSize: null,
|
||||||
|
className: 'aircraft-marker-icon',
|
||||||
|
html: `<div style=\'transform: translateX(-10px) translateY(-10px); height: 20px; width: 20px; border: 1px red\'>${airLinerSVG}</div>`,
|
||||||
|
}));
|
||||||
|
this.getElement().children.item(0).children.item(0).style = `transform: translateX(-200px) translateY(-200px) scale(${scale},${scale}) rotate(${(this.heading)-45}deg)`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
this.setIcon(L.divIcon({
|
||||||
|
iconSize: null,
|
||||||
|
className: 'aircraft-marker-icon',
|
||||||
|
html: `<div style=\'transform: rotate(${this.heading}deg) scale(0.001,0.001) \'>${airLinerSVG}</div>`,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onAdd : function(map) {
|
||||||
|
var metersPP = metersPerPixel(map.getCenter().lat, map.getZoom());
|
||||||
|
console.log(metersPP);
|
||||||
|
console.log(this);
|
||||||
|
this.updateIcon();
|
||||||
|
},
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
//Builds a marker for a ai or multiplayer aircraft
|
||||||
|
module.exports.default = function (latlng, options) {
|
||||||
|
return new L.AircraftMarker(latlng, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
var l1 = feature.properties.callsign,
|
||||||
|
l2 = feature.properties.heading + 'T ' + feature.properties.speed + 'KTAS ' +
|
||||||
|
formatFL(feature.geometry.coordinates[2]),
|
||||||
|
l3 = feature.properties.departureAirportId + ' -> ' + feature.properties.arrivalAirportId;
|
||||||
|
|
||||||
|
*/
|
After Width: | Height: | Size: 2.1 KiB |
After Width: | Height: | Size: 3.9 KiB |
Loading…
Reference in new issue