mirror of
https://github.com/iNavFlight/inav-configurator.git
synced 2025-07-26 09:45:23 +03:00
Add sanity cheks
This commit is contained in:
parent
abc3fa5606
commit
8a16ee2894
5 changed files with 139 additions and 6 deletions
|
@ -1,5 +1,7 @@
|
|||
'use strict'
|
||||
|
||||
const { Shape } = require("three");
|
||||
|
||||
const GeozoneType = Object.freeze({
|
||||
EXCULSIVE: 0,
|
||||
INCLUSIVE: 1,
|
||||
|
@ -176,6 +178,71 @@ let Geozone = function (type, shape, minAltitude, maxAltitude, sealevelRef, radi
|
|||
vertices = [];
|
||||
}
|
||||
|
||||
self.isCounterClockwise = () => {
|
||||
|
||||
if (shape == GeozoneShapes.CIRCULAR) {
|
||||
return true;
|
||||
}
|
||||
|
||||
let area = 0;
|
||||
for (let i = 0; i < vertices.length; i++) {
|
||||
const x1 = vertices[i].getLat();
|
||||
const y1 = vertices[i].getLon();
|
||||
const next = vertices[(i + 1) % vertices.length];
|
||||
const x2 = next.getLat();
|
||||
const y2 = next.getLon();
|
||||
area += x1 * y2 - y1 * x2;
|
||||
}
|
||||
return area < 0;
|
||||
}
|
||||
|
||||
self.isComplex = () => {
|
||||
if (shape == GeozoneShapes.CIRCULAR) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Intersection of two lines https://en.wikipedia.org/wiki/Line-line_intersection
|
||||
function doLinesIntersect(line1Start, line1End, line2Start, line2End)
|
||||
{
|
||||
const s1 = line1End.x - line1Start.x;
|
||||
const t1 = -(line2End.x - line2Start.x);
|
||||
const r1 = line2Start.x - line1Start.x;
|
||||
|
||||
const s2 = line1End.y - line1Start.y;
|
||||
const t2 = -(line2End.y - line2Start.y);
|
||||
const r2 = line2Start.y - line1Start.y;
|
||||
|
||||
// Use Cramer's rule for the solution of the system of linear equations
|
||||
const determ = s1 * t2 - t1 * s2;
|
||||
if (determ == 0) { // No solution
|
||||
return false;
|
||||
}
|
||||
|
||||
const s0 = (r1 * t2 - t1 * r2) / determ;
|
||||
const t0 = (s1 * r2 - r1 * s2) / determ;
|
||||
|
||||
if (s0 == 0 && t0 == 0) {
|
||||
return false;
|
||||
}
|
||||
return !(s0 <= 0 || s0 >= 1 || t0 <= 0 || t0 >= 1)
|
||||
}
|
||||
|
||||
for (var i = 0; i < vertices.length; i++) {
|
||||
const a = {x: vertices[i].getLat(), y: vertices[i].getLon()};
|
||||
const next = vertices[(i + 1) % vertices.length];
|
||||
const b = {x: next.getLat(), y: next.getLon()};
|
||||
for (var j = i + 2; j < vertices.length; j++) {
|
||||
const c = {x: vertices[j].getLat(), y: vertices[j].getLon()};;
|
||||
const next2 = vertices[(j + 1) % vertices.length];
|
||||
const d = {x: next2.getLat(), y: next2.getLon()};
|
||||
if (doLinesIntersect(a, b, c, d)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
self.getElevationFromServer = async function (lon, lat, globalSettings) {
|
||||
let elevation = "N/A";
|
||||
if (globalSettings.mapProviderType == 'bing') {
|
||||
|
|
|
@ -140,7 +140,7 @@ let GeozoneCollection = function() {
|
|||
buffer.push(zone.getVerticesCount());
|
||||
}
|
||||
} else {
|
||||
buffer = [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 ];
|
||||
buffer = [id, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
||||
}
|
||||
|
||||
return buffer;
|
||||
|
|
|
@ -4772,6 +4772,9 @@
|
|||
"featureGEOZONE": {
|
||||
"message": "Geozone"
|
||||
},
|
||||
"geozone": {
|
||||
"message": "Geozone"
|
||||
},
|
||||
"featureGEOZONETip": {
|
||||
"message": "Virtual perimeters for geographical areas (also called geofence) with automatically triggered actions when the perimeters are violated."
|
||||
},
|
||||
|
@ -4829,6 +4832,21 @@
|
|||
"missionGeozoneAvailableVertices": {
|
||||
"message": "Available Vertices:"
|
||||
},
|
||||
"geozoneInvalidzone": {
|
||||
"message": "Invalid Geozone(s) detected:"
|
||||
},
|
||||
"gezoneInvalidReasonNotCC": {
|
||||
"message": "Not counter clockwise"
|
||||
},
|
||||
"gezoneInvalidReasonComplex": {
|
||||
"message": "Complex"
|
||||
},
|
||||
"gezoneInvalidReasonMinMaxAlt": {
|
||||
"message": "Max. Alt <= Min. Alt"
|
||||
},
|
||||
"geozoneUnableToSave": {
|
||||
"message": "Unable to save geozones: Invalid zones"
|
||||
},
|
||||
"missionMultiMissionHead": {
|
||||
"message": "Multi Missions"
|
||||
},
|
||||
|
|
|
@ -66,6 +66,11 @@
|
|||
<span style="color: red" i18n-replaced data-i18n="warning"></span>
|
||||
<div id="geozoneMissionWarning" style="display: inline-block" data-i18n="missionGeozoneWarning"></div>
|
||||
</div>
|
||||
<div id="infoGeozoneInvalid" style="padding-bottom: 2px;">
|
||||
<span style="color: red" i18n-replaced data-i18n="warning"></span>
|
||||
<div style="display: inline-block" data-i18n="geozoneInvalidzone"></div>
|
||||
<span id="geozoneInvalidContent"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
|
|
@ -76,6 +76,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
let $waypointOptionsTableBody;
|
||||
let selectedGeozone;
|
||||
let $geozoneContent;
|
||||
let invalidGeoZones = false;
|
||||
let isGeozoneEnabeld = false;
|
||||
let settings = {speed: 0, alt: 5000, safeRadiusSH: 50, fwApproachAlt: 60, fwLandAlt: 5, maxDistSH: 0, fwApproachLength: 0, fwLoiterRadius: 0, bingDemModel: false};
|
||||
|
||||
|
@ -152,6 +153,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
}
|
||||
|
||||
$('#infoGeozoneMissionWarning').hide();
|
||||
$('#infoGeozoneInvalid').hide();
|
||||
$safehomeContentBox = $('#SafehomeContentBox');
|
||||
$waypointOptionsTableBody = $('#waypointOptionsTableBody');
|
||||
$geozoneContent = $('#geozoneContent');
|
||||
|
@ -919,7 +921,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
cleanGeozoneLayers();
|
||||
if (!selectedGeozone) {
|
||||
cleanGeozoneLines();
|
||||
geozoneMissionWarning();
|
||||
geozoneWarning();
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -931,7 +933,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
});
|
||||
}
|
||||
});
|
||||
geozoneMissionWarning();
|
||||
geozoneWarning();
|
||||
}
|
||||
|
||||
function cleanGeozoneLines() {
|
||||
|
@ -949,13 +951,45 @@ TABS.mission_control.initialize = function (callback) {
|
|||
geozoneMarkers = [];
|
||||
}
|
||||
|
||||
function geozoneMissionWarning() {
|
||||
function geozoneWarning() {
|
||||
|
||||
if (markers.length >= 1 && geozoneMarkers.length >= 1) {
|
||||
$('#infoGeozoneMissionWarning').show();
|
||||
} else {
|
||||
$('#infoGeozoneMissionWarning').hide();
|
||||
}
|
||||
|
||||
$('#geozoneInvalidContent').empty();
|
||||
invalidGeoZones = false;
|
||||
for (var i = 0; i < FC.GEOZONES.geozoneCount(); i++) {
|
||||
const zone = FC.GEOZONES.at(i);
|
||||
|
||||
var reasons = []
|
||||
if (!zone.isCounterClockwise()) {
|
||||
reasons.push(i18n.getMessage("gezoneInvalidReasonNotCC"));
|
||||
}
|
||||
|
||||
if (zone.isComplex()) {
|
||||
reasons.push(i18n.getMessage("gezoneInvalidReasonComplex"));
|
||||
}
|
||||
|
||||
if (zone.getMaxAltitude() <= zone.getMinAltitude()) {
|
||||
reasons.push(i18n.getMessage("gezoneInvalidReasonMinMaxAlt"));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (reasons.length > 0) {
|
||||
$('#geozoneInvalidContent').append(`<div style="display: inline-block">${i18n.getMessage("geozone")} ${zone.getNumber() + 1}: ${reasons.join(", ")}</div><br/>`);
|
||||
invalidGeoZones = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (invalidGeoZones) {
|
||||
$('#infoGeozoneInvalid').show();
|
||||
} else {
|
||||
$('#infoGeozoneInvalid').hide();
|
||||
}
|
||||
}
|
||||
|
||||
function updateGeozoneInfo() {
|
||||
|
@ -1621,7 +1655,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
});
|
||||
|
||||
}
|
||||
geozoneMissionWarning();
|
||||
geozoneWarning();
|
||||
}
|
||||
|
||||
function redrawLayer() {
|
||||
|
@ -1734,7 +1768,7 @@ TABS.mission_control.initialize = function (callback) {
|
|||
}
|
||||
});
|
||||
});
|
||||
|
||||
geozoneWarning();
|
||||
} else {
|
||||
$('#geozoneContentBox').hide();
|
||||
}
|
||||
|
@ -1992,6 +2026,9 @@ TABS.mission_control.initialize = function (callback) {
|
|||
|
||||
var handleShowGeozoneSettings = function () {
|
||||
$('#missionPlannerGeozones').fadeIn(300);
|
||||
if (!selectedGeozone) {
|
||||
selectedGeozone = FC.GEOZONES.first();
|
||||
}
|
||||
renderGeozoneOptions();
|
||||
renderGeozonesOnMap();
|
||||
};
|
||||
|
@ -3363,6 +3400,12 @@ TABS.mission_control.initialize = function (callback) {
|
|||
});
|
||||
|
||||
$('#saveEepromGeozoneButton').on('click', event => {
|
||||
|
||||
if (invalidGeoZones) {
|
||||
GUI.alert(i18n.getMessage("geozoneUnableToSave"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (confirm(i18n.getMessage("missionGeozoneReboot"))) {
|
||||
$(event.currentTarget).addClass('disabled');
|
||||
GUI.log('Start of sending Geozones');
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue