|
|
|
'use strict';
|
|
|
|
|
|
|
|
|
|
|
|
let WaypointCollection = function () {
|
|
|
|
|
|
|
|
let self = {},
|
|
|
|
data = [],
|
|
|
|
maxWaypoints = 60,
|
|
|
|
isValidMission = 0,
|
|
|
|
countBusyPoints = 0,
|
|
|
|
version = 0,
|
|
|
|
center = {}
|
|
|
|
|
|
|
|
self.getMaxWaypoints = function () {
|
|
|
|
return maxWaypoints;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setMaxWaypoints = function (data) {
|
|
|
|
maxWaypoints = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getValidMission = function () {
|
|
|
|
return isValidMission;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setValidMission = function (data) {
|
|
|
|
isValidMission = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getCountBusyPoints = function () {
|
|
|
|
return countBusyPoints;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setCountBusyPoints = function (data) {
|
|
|
|
countBusyPoints = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getVersion = function () {
|
|
|
|
return version;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setVersion = function (data) {
|
|
|
|
version = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getCenter = function () {
|
|
|
|
return center;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setCenter = function (data) {
|
|
|
|
center = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setCenterZoom = function (data) {
|
|
|
|
center.zoom = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setCenterLon = function (data) {
|
|
|
|
center.lon = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.setCenterLat = function (data) {
|
|
|
|
center.lat = data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.put = function (element) {
|
|
|
|
data.push(element);
|
|
|
|
};
|
|
|
|
|
|
|
|
self.get = function () {
|
|
|
|
return data;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.isEmpty = function () {
|
|
|
|
return data == [];
|
|
|
|
};
|
|
|
|
|
|
|
|
self.flush = function () {
|
|
|
|
data = [];
|
|
|
|
};
|
|
|
|
|
|
|
|
self.reinit = function () {
|
|
|
|
data = [];
|
|
|
|
maxWaypoints = 60;
|
|
|
|
isValidMission = 0;
|
|
|
|
countBusyPoints = 0;
|
|
|
|
version = 0;
|
|
|
|
center = {};
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getWaypoint = function(waypointId) {
|
|
|
|
for (let waypointIndex in data) {
|
|
|
|
if (data.hasOwnProperty(waypointIndex)) {
|
|
|
|
let waypoint = data[waypointIndex];
|
|
|
|
|
|
|
|
if (waypoint.getNumber() == waypointId ) {
|
|
|
|
return waypoint;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.updateWaypoint = function(newWaypoint) {
|
|
|
|
if (newWaypoint.isUsed()) {
|
|
|
|
data[newWaypoint.getNumber()] = newWaypoint;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
self.dropWaypoint = function(newWaypoint) {
|
|
|
|
self.getWaypoint(newWaypoint.getNumber()).setUsed(false);
|
|
|
|
let indexId = newWaypoint.getNumber()
|
|
|
|
data.forEach(function (wp) {
|
|
|
|
if (wp.getNumber() >= indexId) {
|
|
|
|
wp.setNumber(wp.getNumber()-1);
|
|
|
|
}
|
|
|
|
if (wp.getAction() == MWNP.WPTYPE.JUMP && wp.getP1()>=indexId) {
|
|
|
|
wp.setP1(wp.getP1()-1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
data.splice(indexId, 1);
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
self.insertWaypoint = function (newWaypoint, indexId) {
|
|
|
|
data.forEach(function (wp) {
|
|
|
|
if (wp.getNumber() >= indexId) {
|
|
|
|
wp.setNumber(wp.getNumber()+1);
|
|
|
|
}
|
|
|
|
if (wp.getAction() == MWNP.WPTYPE.JUMP && wp.getP1()>=indexId) {
|
|
|
|
wp.setP1(wp.getP1()+1);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
data.splice(indexId, 0, newWaypoint);
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
self.drop = function (waypointId) {
|
|
|
|
self.getWaypoint(waypointId).setUsed(false);
|
|
|
|
var tmpData = [];
|
|
|
|
let idx = 0;
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.isUsed()) {
|
|
|
|
element.setNumber(idx)
|
|
|
|
tmpData.push(element);
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
data = tmpData;
|
|
|
|
};
|
|
|
|
|
|
|
|
self.update = function (bMWPfile=false, bReverse=false) {
|
|
|
|
let oldWPNumber = 0;
|
|
|
|
let optionIdx = 0;
|
|
|
|
let idx = 0;
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.isUsed()) {
|
|
|
|
if (bMWPfile && !bReverse) {
|
|
|
|
element.setNumber(element.getNumber()-1);
|
|
|
|
if (element.getAction() == MWNP.WPTYPE.JUMP) {
|
|
|
|
element.setP1(element.getP1()-1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bMWPfile && bReverse) {
|
|
|
|
element.setNumber(element.getNumber()+1);
|
|
|
|
if (element.getAction() == MWNP.WPTYPE.JUMP) {
|
|
|
|
element.setP1(element.getP1()+1);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([MWNP.WPTYPE.JUMP,MWNP.WPTYPE.SET_HEAD,MWNP.WPTYPE.RTH].includes(element.getAction())) {
|
|
|
|
element.setAttachedId(oldWPNumber);
|
|
|
|
element.setAttachedNumber(optionIdx);
|
|
|
|
element.setAttached(true);
|
|
|
|
optionIdx++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
oldWPNumber = element.getNumber();
|
|
|
|
element.setLayerNumber(idx);
|
|
|
|
optionIdx = 0;
|
|
|
|
idx++;
|
|
|
|
}
|
|
|
|
if (element.getNumber() == ((bMWPfile && bReverse) ? self.get().length : self.get().length-1)) {
|
|
|
|
element.setEndMission(0xA5);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
element.setEndMission(0);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
};
|
|
|
|
|
|
|
|
self.getNonAttachedList = function () {
|
|
|
|
let tmpData = [];
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (!element.isAttached()) {
|
|
|
|
tmpData.push(element);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return tmpData;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getAttachedList = function () {
|
|
|
|
let tmpData = [];
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.isAttached()) {
|
|
|
|
tmpData.push(element);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return tmpData;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getAttachedFromWaypoint = function (waypoint) {
|
|
|
|
let tmpData = [];
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.isAttached() && element.getAttachedId() == waypoint.getNumber()) {
|
|
|
|
tmpData.push(element);
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
return tmpData;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.addAttachedFromWaypoint = function (waypoint) {
|
|
|
|
let tmpNumber = 0;
|
|
|
|
let tmpData = self.getAttachedFromWaypoint(waypoint);
|
|
|
|
if (tmpData != 'undefined' && tmpData.length !=0) {
|
|
|
|
tmpNumber = tmpData.length;
|
|
|
|
}
|
|
|
|
let tempWp = new Waypoint(waypoint.getNumber()+tmpNumber+1, MWNP.WPTYPE.JUMP, 0, 0);
|
|
|
|
tempWp.setAttached(true);
|
|
|
|
tempWp.setAttachedId(waypoint.getNumber());
|
|
|
|
self.insertWaypoint(tempWp, waypoint.getNumber()+tmpNumber+1);
|
|
|
|
self.update();
|
|
|
|
}
|
|
|
|
|
|
|
|
self.dropAttachedFromWaypoint = function (waypoint, waypointAttachedNumber) {
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.isAttached() && element.getAttachedId() == waypoint.getNumber() && element.getAttachedNumber() == waypointAttachedNumber) {
|
|
|
|
self.dropWaypoint(element);
|
|
|
|
self.update();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
self.extractBuffer = function(waypointId) {
|
|
|
|
let buffer = [];
|
|
|
|
let waypoint = self.getWaypoint(waypointId);
|
|
|
|
buffer.push(waypoint.getNumber()); // sbufReadU8(src); // number
|
|
|
|
buffer.push(waypoint.getAction()); // sbufReadU8(src); // action
|
|
|
|
buffer.push(specificByte(waypoint.getLat(), 0)); // sbufReadU32(src); // lat
|
|
|
|
buffer.push(specificByte(waypoint.getLat(), 1));
|
|
|
|
buffer.push(specificByte(waypoint.getLat(), 2));
|
|
|
|
buffer.push(specificByte(waypoint.getLat(), 3));
|
|
|
|
buffer.push(specificByte(waypoint.getLon(), 0)); // sbufReadU32(src); // lon
|
|
|
|
buffer.push(specificByte(waypoint.getLon(), 1));
|
|
|
|
buffer.push(specificByte(waypoint.getLon(), 2));
|
|
|
|
buffer.push(specificByte(waypoint.getLon(), 3));
|
|
|
|
buffer.push(specificByte(waypoint.getAlt(), 0)); // sbufReadU32(src); // to set altitude (cm)
|
|
|
|
buffer.push(specificByte(waypoint.getAlt(), 1));
|
|
|
|
buffer.push(specificByte(waypoint.getAlt(), 2));
|
|
|
|
buffer.push(specificByte(waypoint.getAlt(), 3));
|
|
|
|
buffer.push(lowByte(waypoint.getP1())); //sbufReadU16(src); // P1 speed or landing
|
|
|
|
buffer.push(highByte(waypoint.getP1()));
|
|
|
|
buffer.push(lowByte(waypoint.getP2())); //sbufReadU16(src); // P2
|
|
|
|
buffer.push(highByte(waypoint.getP2()));
|
|
|
|
buffer.push(lowByte(waypoint.getP3())); //sbufReadU16(src); // P3
|
|
|
|
buffer.push(highByte(waypoint.getP3()));
|
|
|
|
buffer.push(waypoint.getEndMission()); //sbufReadU8(src); // future: to set nav flag
|
|
|
|
|
|
|
|
return buffer;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.missionDisplayDebug = function() {
|
|
|
|
if (data && data.length != 0) {
|
|
|
|
data.forEach(function (element) {
|
|
|
|
console.log("N° : ", element.getNumber(),
|
|
|
|
"Action : ", element.getAction(),
|
|
|
|
"Lon : ", element.getLon(),
|
|
|
|
"Lat : ", element.getLat(),
|
|
|
|
"Alt : ", element.getAlt(),
|
|
|
|
"P1 : ", element.getP1(),
|
|
|
|
"P2 : ", element.getP2(),
|
|
|
|
"P3 : ", element.getP3(),
|
|
|
|
"EndMission : ", element.getEndMission());
|
|
|
|
});
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.copy = function(mission){
|
|
|
|
mission.get().forEach(function (element) {
|
|
|
|
self.put(element);
|
|
|
|
});
|
|
|
|
self.setMaxWaypoints(mission.getMaxWaypoints());
|
|
|
|
self.setValidMission(mission.getValidMission());
|
|
|
|
self.setCountBusyPoints(mission.getCountBusyPoints());
|
|
|
|
self.setVersion(mission.getVersion());
|
|
|
|
self.setCenter(mission.getCenter());
|
|
|
|
}
|
|
|
|
|
|
|
|
self.convertJumpNumberToWaypoint = function(jumpId) {
|
|
|
|
let outputNumber = 0;
|
|
|
|
self.getNonAttachedList().forEach(function (element) {
|
|
|
|
if (element.getLayerNumber() == jumpId) {
|
|
|
|
outputNumber = element.getNumber();
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return outputNumber;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.isJumpTargetAttached = function(waypoint) {
|
|
|
|
let lJumptTargetAttached = [];
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.getAction() == MWNP.WPTYPE.JUMP && element.getP1() == waypoint.getNumber()) {
|
|
|
|
lJumptTargetAttached.push(element.getNumber());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return (lJumptTargetAttached.length != 0 && lJumptTargetAttached != 'undefined')
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getPoiList = function() {
|
|
|
|
let poiList = [];
|
|
|
|
data.forEach(function (element) {
|
|
|
|
if (element.getAction() == MWNP.WPTYPE.SET_POI) {
|
|
|
|
poiList.push(element.getNumber());
|
|
|
|
}
|
|
|
|
});
|
|
|
|
return poiList;
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getPoint2Measure = function(reverse=false) {
|
|
|
|
let point2measure = [];
|
|
|
|
let altPoint2measure = [];
|
|
|
|
let namePoint2measure = [];
|
|
|
|
let refPoint2measure = [];
|
|
|
|
let jumpDict = {};
|
|
|
|
let nStart = 0;
|
|
|
|
let nLoop = 0;
|
|
|
|
let n = 0 ;
|
|
|
|
let startCount = true;
|
|
|
|
while (startCount) {
|
|
|
|
if (nStart > data[data.length -1].getNumber() ) {
|
|
|
|
startCount = false;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ([MWNP.WPTYPE.WAYPOINT,MWNP.WPTYPE.POSHOLD_TIME,MWNP.WPTYPE.LAND].includes(self.getWaypoint(nStart).getAction())) {
|
|
|
|
if (reverse) {
|
|
|
|
point2measure.push([self.getWaypoint(nStart).getLatMap(), self.getWaypoint(nStart).getLonMap()]);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
point2measure.push(ol.proj.fromLonLat([self.getWaypoint(nStart).getLonMap(), self.getWaypoint(nStart).getLatMap()]));
|
|
|
|
}
|
|
|
|
altPoint2measure.push(self.getWaypoint(nStart).getAlt());
|
|
|
|
namePoint2measure.push(self.getWaypoint(nStart).getLayerNumber()+1);
|
|
|
|
refPoint2measure.push(self.getWaypoint(nStart).getP3());
|
|
|
|
nStart++;
|
|
|
|
}
|
|
|
|
else if (self.getWaypoint(nStart).getAction() == MWNP.WPTYPE.JUMP) {
|
|
|
|
if (!Object.keys(jumpDict).includes(String(self.getWaypoint(nStart).getNumber())) ) {
|
|
|
|
jumpDict[self.getWaypoint(nStart).getNumber()] = {nStart: self.getWaypoint(nStart).getP1(), nLoop : self.getWaypoint(nStart).getP2(), n : 0};
|
|
|
|
}
|
|
|
|
if (Object.keys(jumpDict).includes(String(self.getWaypoint(nStart).getNumber())) ) {
|
|
|
|
if (jumpDict[self.getWaypoint(nStart).getNumber()]["nLoop"] == -1) {
|
|
|
|
jumpDict[self.getWaypoint(nStart).getNumber()]["nLoop"] = 1;
|
|
|
|
nLoop = -1;
|
|
|
|
}
|
|
|
|
if ( (jumpDict[self.getWaypoint(nStart).getNumber()]["n"]>=jumpDict[self.getWaypoint(nStart).getNumber()]["nLoop"] || jumpDict[self.getWaypoint(nStart).getNumber()]["nLoop"] ==0) ) {
|
|
|
|
jumpDict[self.getWaypoint(nStart).getNumber()]["n"] = 0;
|
|
|
|
nStart++;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
jumpDict[self.getWaypoint(nStart).getNumber()]["n"] = jumpDict[self.getWaypoint(nStart).getNumber()]["n"]+1;
|
|
|
|
let nStartTemp = jumpDict[self.getWaypoint(nStart).getNumber()]["nStart"];
|
|
|
|
nStart = nStartTemp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
nStart++;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return [nLoop, point2measure, altPoint2measure, namePoint2measure, refPoint2measure];
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getDistance = function(display) {
|
|
|
|
let lengthLine = [];
|
|
|
|
const [nLoop, point2measure, altPoint2measure, namePoint2measure, refPoint2measure] = self.getPoint2Measure();
|
|
|
|
if (nLoop == -1 && display) {
|
|
|
|
return [-1];
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
|
|
|
|
const cumulativeSum = (sum => value => sum += value)(0);
|
|
|
|
|
|
|
|
let oldCoord = [];
|
|
|
|
point2measure.forEach(function (coord) {
|
|
|
|
if (oldCoord != 'undefined' && oldCoord != []) {
|
|
|
|
lengthLine.push(ol.Sphere.getLength(new ol.geom.LineString([oldCoord, coord])));
|
|
|
|
}
|
|
|
|
oldCoord = coord;
|
|
|
|
});
|
|
|
|
//console.log("lengthLine ", lengthLine);
|
|
|
|
return lengthLine.map(cumulativeSum);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
self.getElevation = async function(globalSettings) {
|
|
|
|
const [nLoop, point2measure, altPoint2measure, namePoint2measure, refPoint2measure] = self.getPoint2Measure(true);
|
|
|
|
let lengthMission = self.getDistance(true);
|
|
|
|
let totalMissionDistance = lengthMission[lengthMission.length -1].toFixed(1);
|
|
|
|
let samples;
|
|
|
|
let sampleMaxNum;
|
|
|
|
let sampleDistance;
|
|
|
|
|
|
|
|
if (globalSettings.mapProviderType == 'bing') {
|
|
|
|
sampleMaxNum = 1024;
|
|
|
|
sampleDistance = 30;
|
|
|
|
} else { // use opentopodata.org instead
|
|
|
|
sampleMaxNum = 99;
|
|
|
|
sampleDistance = 60;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (point2measure.length <= 2){
|
|
|
|
samples = 1;
|
|
|
|
}
|
|
|
|
else if (Math.trunc(totalMissionDistance / sampleDistance) <= sampleMaxNum && point2measure.length > 2){
|
|
|
|
samples = Math.trunc(totalMissionDistance / sampleDistance);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
samples = sampleMaxNum;
|
|
|
|
}
|
|
|
|
|
|
|
|
let elevation = "N/A";
|
|
|
|
if (globalSettings.mapProviderType == 'bing') {
|
|
|
|
let elevationEarthModel = $('#elevationEarthModel').prop("checked") ? "sealevel" : "ellipsoid";
|
|
|
|
|
|
|
|
if (point2measure.length >1) {
|
|
|
|
const response = await fetch('http://dev.virtualearth.net/REST/v1/Elevation/Polyline?points='+point2measure+'&heights='+elevationEarthModel+'&samples='+String(samples+1)+'&key='+globalSettings.mapApiKey);
|
|
|
|
const myJson = await response.json();
|
|
|
|
elevation = myJson.resourceSets[0].resources[0].elevations;
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
const response = await fetch('http://dev.virtualearth.net/REST/v1/Elevation/List?points='+point2measure+'&heights='+elevationEarthModel+'&key='+globalSettings.mapApiKey);
|
|
|
|
const myJson = await response.json();
|
|
|
|
elevation = myJson.resourceSets[0].resources[0].elevations;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
let coordList = "";
|
|
|
|
point2measure.forEach(function (item) {
|
|
|
|
coordList += item + '|';
|
|
|
|
});
|
|
|
|
const response = await fetch('https://api.opentopodata.org/v1/aster30m?locations='+coordList+'&samples='+String(samples+1));
|
|
|
|
const myJson = await response.json();
|
|
|
|
|
|
|
|
if (myJson.status == "OK") {
|
|
|
|
elevation = [];
|
|
|
|
for (var i = 0; i < myJson.results.length; i++){
|
|
|
|
if (myJson.results[i].elevation == null) {
|
|
|
|
elevation[i] = 0;
|
|
|
|
} else {
|
|
|
|
elevation[i] = myJson.results[i].elevation;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//console.log("elevation ", elevation);
|
|
|
|
return [lengthMission, totalMissionDistance, samples, elevation, altPoint2measure, namePoint2measure, refPoint2measure];
|
|
|
|
}
|
|
|
|
|
|
|
|
return self;
|
|
|
|
};
|