Skip to content

Commit

Permalink
Merge pull request #18 from matafokka/development
Browse files Browse the repository at this point in the history
First beta!
  • Loading branch information
matafokka authored Feb 15, 2022
2 parents def7cc0 + 1cd58fc commit e109b4c
Show file tree
Hide file tree
Showing 27 changed files with 290 additions and 225 deletions.
13 changes: 8 additions & 5 deletions DrawGeodesic.js
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,11 @@ function _createGeodesic (coords, opts = {}) {
return geodesic;
}

function _polyRedraw(poly) {
/**
* Redraws Leaflet layer or geodesic line
* @param poly {L.Layer | L.Geodesic} Layer to redraw
*/
L.redrawLayer = function (poly) {
if (poly.updateGeometry)
poly.updateGeometry();
else
Expand Down Expand Up @@ -321,7 +325,6 @@ L.Draw.Polyline = L.Draw.Feature.extend({

_shouldAbortMouseEvent: function (e) {
let {lat, lng} = e.latlng;
console.log(e, !this.options.shapeOptions.naturalDrawing && (lat > 85 || lat < -85 || lng < -180 || lng > 180))
return !this.options.shapeOptions.naturalDrawing && (lat > 85 || lat < -85 || lng < -180 || lng > 180);
},

Expand Down Expand Up @@ -864,7 +867,7 @@ L.Edit.PolyVerticesEdit = L.Handler.extend({
var latlngs = this._defaultShape();
var removed = [].splice.apply(latlngs, arguments);
this._poly._convertLatLngs(latlngs, true);
_polyRedraw(this._poly);
L.redrawLayer(this._poly);
return removed;
},

Expand Down Expand Up @@ -939,7 +942,7 @@ L.Edit.PolyVerticesEdit = L.Handler.extend({
this._poly._bounds._northEast = L.latLng(-Infinity, -Infinity);
var latlngs = this._poly.getLatLngs();
this._poly._convertLatLngs(latlngs, true);
_polyRedraw(this._poly);
L.redrawLayer(this._poly);
this._poly.fire('editdrag');
},

Expand Down Expand Up @@ -1001,7 +1004,7 @@ L.Edit.PolyVerticesEdit = L.Handler.extend({
marker._middleRight.setLatLng(this._getMiddleLatLng(marker, marker._next));
}

_polyRedraw(this._poly);
L.redrawLayer(this._poly);
this.updateMarkers();
},

Expand Down
24 changes: 18 additions & 6 deletions ESRIGridParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -226,13 +226,10 @@ class ESRIGridParser {
continue;

if (!this.polygonsStats[name])
this.polygonsStats[name] = {min: Infinity, max: -Infinity}
this.polygonsStats[name] = ESRIGridParser.createStatsObject();

let stats = this.polygonsStats[name];
if (pixelValue < stats.min)
stats.min = pixelValue;
if (pixelValue > stats.max)
stats.max = pixelValue;
ESRIGridParser.addToStats(pixelValue, stats);
}
} else if (!isSpace && !isLineBreak)
this.value += symbol;
Expand Down Expand Up @@ -268,7 +265,7 @@ class ESRIGridParser {
copyStats(layer = undefined) {
let l = this.layer || layer;
if (!l)
throw new Error("Error, can't copy statistics? If you're using ESRIGridParser in a WebWorker, call this method outside of WebWorker!");
throw new Error("Can't copy statistics. If you're using ESRIGridParser in a WebWorker, call this method outside of WebWorker!");
ESRIGridParser.copyStats(l, this.polygonsStats);
this.clearState();
}
Expand Down Expand Up @@ -340,12 +337,27 @@ class ESRIGridParser {
for (let name in stats) {
let widgetable = layer.polygonsWidgets[name];
let s = stats[name];
s.mean = s.sum / s.count;
widgetable.getWidgetById("minHeight").setValue(s.min);
widgetable.getWidgetById("maxHeight").setValue(s.max);
widgetable.getWidgetById("meanHeight").setValue(s.mean);
}
layer.updateAll();
}

static createStatsObject() {
return {min: Infinity, max: -Infinity, mean: 0, sum: 0, count: 0}
}

static addToStats(value, stats) {
if (value < stats.min)
stats.min = value;
if (value > stats.max)
stats.max = value;
stats.sum += value;
stats.count++;
}

}

module.exports = ESRIGridParser;
9 changes: 3 additions & 6 deletions GeoTIFFParser.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const intersect = require("@turf/intersect").default;
const toProj4 = require("geotiff-geokeys-to-proj4");
const proj4 = require("proj4");
const MathTools = require("./MathTools.js");
const ESRIGridParser = require("./ESRIGridParser.js");

/**
* Parses GeoTIFF files
Expand Down Expand Up @@ -79,7 +80,7 @@ module.exports = async function (file, projectionString, initialData) {
// geotiff.js will mash all pixels into one array.
// To easily keep track of coordinates and reduce memory consumption, we need to read image row by row.
let [minX, currentY, maxX, maxY] = imageWindow,
stats = {min: Infinity, max: -Infinity} // Stats for current polygon
stats = ESRIGridParser.createStatsObject(); // Stats for current polygon

for (currentY; currentY <= maxY; currentY++) {
let currentX = minX;
Expand Down Expand Up @@ -107,11 +108,7 @@ module.exports = async function (file, projectionString, initialData) {
let multipliedValue = value * zScale;
if (value === nodata || multipliedValue === nodata)
continue;

if (multipliedValue < stats.min)
stats.min = multipliedValue;
if (multipliedValue > stats.max)
stats.max = multipliedValue;
ESRIGridParser.addToStats(multipliedValue, stats);
}
}
polygonStats[name] = stats;
Expand Down
10 changes: 10 additions & 0 deletions MathTools.js
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,16 @@ class MathTools {
return {x: "lng", y: "lat"}
}

/**
* Wraps lng2 to lng1
* @param lng1 {number} Anchor lng
* @param lng2 {number} Lng to wrap
* @return {number} Wrapped lng2
*/
static wrapLng(lng1, lng2) {
return lng2 - Math.round((lng2 - lng1) / 360);
}

}

module.exports = MathTools;
14 changes: 6 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# SynthFlight Alpha
# SynthFlight Beta

SynthFlight is a fully client-side software for planning aerial photography. Run it either on the desktop or in a [browser online](https://matafokka.github.io/SynthFlight/).

This is an alpha version, so expect bugs, crashes, errors, missing functions, API changes, etc.
This is a beta version, so bugs, huge API changes and lack of backwards compatibility are to be expected.

For now, it only can plan photography by a graticule or grid. However, planning by custom polygons or flight paths is on its way.
Most of the planned functionality is here, however, a number of small changes will be introduced.

SynthFlight also features an advanced extendable layer system for Leaflet that will be released as a separate package when it'll be ready.

You can use layers to try and compare different parameters to choose which ones suites you best.
A stable version will be released in May or June 2022.

# Setup

Expand Down Expand Up @@ -100,5 +98,5 @@ Yes.

There will be no compatibility between SynthFlight versions until first stable release.

## Will this project will ever be finished?
Yes, because it's my master's degree.
## When a stable release will be available?
May or June 2022
24 changes: 5 additions & 19 deletions SynthBase/Hull.js
Original file line number Diff line number Diff line change
Expand Up @@ -169,9 +169,9 @@ L.ALS.SynthBaseLayer.prototype.buildHull = function (path, color) {
* @return {{upper: L.LatLng[], lower: L.LatLng[]}} Convex hull of given points
*/
L.ALS.SynthBaseLayer.prototype.getConvexHull = function (points) {
// Find convex hull of the points using monotone chain.
// Find convex hull of the points using monotone chain
points.sort((a, b) => {
return a.lng === b.lng ? a.lat - b.lat : a.lng - b.lng;
return MathTools.isEqual(a.lng, b.lng) ? a.lat - b.lat : a.lng - MathTools.wrapLng(a.lng, b.lng);
});

let lower = [];
Expand Down Expand Up @@ -392,22 +392,8 @@ L.ALS.SynthBaseLayer.prototype.getOrderedPathFromHull = function (prevPoint, con
return copyTo[copyTo.length - 1]; // Return the last added point which will become a previous point for the next iteration
}

/**
* Calculates length of a polyline
* @param line {L.Polyline | L.LatLng[] | number[][]} Line to calculate length of
* @return {number} Line length
*/
L.ALS.SynthBaseLayer.prototype.getLineLength = function (line) {
let latLngs = line instanceof Array ? line : line.getLatLngs(), length = 0,
{x, y} = MathTools.getXYPropertiesForPoint(latLngs[0]);

for (let i = 0; i < latLngs.length - 1; i++) {
const p1 = latLngs[i], p2 = latLngs[i + 1];
length += Math.sqrt((p1[x] - p2[x]) ** 2 + (p1[y] - p2[y]) ** 2);
}
return length;
}

L.ALS.SynthBaseLayer.prototype.cross = function (a, b, o) {
return (a.lng - o.lng) * (b.lat - o.lat) - (a.lat - o.lat) * (b.lng - o.lng);
// It calculates only direction, so it should be good enough. Also, we wrap lngs to get correct direction on
// lng differences > 90 and near map's edges
return (MathTools.wrapLng(o.lng, a.lng) - o.lng) * (b.lat - o.lat) - (a.lat - o.lat) * (MathTools.wrapLng(o.lng, b.lng) - o.lng);
}
57 changes: 54 additions & 3 deletions SynthBase/SynthBaseLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,14 @@ require("./SynthBaseSettings.js");
const turfHelpers = require("@turf/helpers");
const MathTools = require("../MathTools.js");

/**
* @typedef {Object} PathData
* @property {L.FeatureGroup} pathGroup Group with the path
* @property {L.FeatureGroup} connectionsGroup Group with the connections
* @property {string} colorLabel Label for the color input
* @property {L.Layer[]} toUpdateColors Layers to update colors of
*/

/**
* Base layer. Provides airport markers, basic calculations and menu entries for them.
*
Expand Down Expand Up @@ -30,6 +38,11 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot

init: function (settings, pathGroup1, connectionsGroup1, colorLabel1, path1AdditionalLayers = [], pathGroup2 = undefined, connectionsGroup2 = undefined, colorLabel2 = undefined, path2AdditionalLayers = []) {

/**
* Settings passed from ALS
* @type {Object}
* @private
*/
this._settings = settings;

/**
Expand All @@ -39,23 +52,40 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
*/
this._pathsWidgetsNumber = 1;

/**
* Data related to the first path
* @type PathData
*/
this.path1 = {
pathGroup: pathGroup1,
connectionsGroup: connectionsGroup1,
colorLabel: colorLabel1,
toUpdateColors: [pathGroup1, connectionsGroup1, ...path1AdditionalLayers]
}

/**
* Data related to the second path
* @type PathData
*/
this.path2 = pathGroup2 ? {
pathGroup: pathGroup2,
connectionsGroup: connectionsGroup2,
colorLabel: colorLabel2,
toUpdateColors: [pathGroup2, connectionsGroup2, ...path2AdditionalLayers]
} : undefined;

/**
* Indicates whether this layer has Y overlay, i.e. if it has parallel paths
* @type {boolean}
*/
this.hasYOverlay = !!this.path2;

/**
* Array of paths to work with
* @type {PathData[]}
*/
this.paths = [this.path1];

if (this.hasYOverlay)
this.paths.push(this.path2);

Expand Down Expand Up @@ -83,13 +113,23 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot

this.serializationIgnoreList.push("_airportMarker", "toUpdateThickness");

/**
* Properties to copy to GeoJSON when exporting
* @type {string[]}
*/
this.propertiesToExport = ["cameraWidth", "cameraHeight", "pixelWidth", "focalLength", "flightHeight", "overlayBetweenPaths", "overlayBetweenImages", "imageScale", "ly", "Ly", "By", "lx", "Lx", "Bx", "GSI", "IFOV", "GIFOV", "FOV", "GFOV", "selectedArea", "timeBetweenCaptures"];

// Add airport
let icon = L.divIcon({
iconSize: null,
className: "",
html: "<div class='grd-lyr-airport-icon ri ri-flight-takeoff-line'></div>"
})

/**
* Airport marker
* @protected
*/
this._airportMarker = L.marker(this.map.getCenter(), {
icon: icon,
draggable: true
Expand All @@ -100,6 +140,9 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
this.addLayers(this._airportMarker);
},

/**
* Adds basic parameters' widgets to the menu. Should be called at the constructor!
*/
addBaseParametersInputSection: function () {
this.addWidget(
new L.ALS.Widgets.Number("lineThickness", "lineThickness", this, "setLineThickness").setMin(1).setMax(20).setValue(this._settings.lineThicknessValue),
Expand Down Expand Up @@ -138,6 +181,9 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
this._airportMarker.fire("drag"); // Just to set values
},

/**
* Adds basic parameters' widgets to the menu. Should be called at the constructor!
*/
addBaseParametersOutputSection: function () {
let yWidgets = [];
if (this.hasYOverlay)
Expand Down Expand Up @@ -186,6 +232,10 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
this.updateDrawThickness();
},

/**
* Sets paths' colors, i.e. colors of layers in {@link PathData.toUpdateColors}
* @private
*/
_setPathsColor: function () {
for (let i = 0; i < this.paths.length; i++) {
let style = {color: this.getWidgetById(`color${i}`).getValue()},
Expand All @@ -195,6 +245,7 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
}
},


setAirportLatLng: function () {
this._airportMarker.setLatLng([
this.getWidgetById("airportLat").getValue(),
Expand Down Expand Up @@ -355,7 +406,7 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
let layers = path.connectionsGroup.getLayers();
for (let layer of layers) {
layer.getLatLngs()[1] = airportPos;
layer.redraw();
L.redrawLayer(layer);
layer.updateWidgets(layer.pathLength + this.getLineLengthMeters(layer));
}
}
Expand Down Expand Up @@ -424,14 +475,14 @@ L.ALS.SynthBaseLayer = L.ALS.Layer.extend(/** @lends L.ALS.SynthBaseLayer.protot
color,
dashArray: this.dashedLine,
weight: this.lineThicknessValue,
segmentsNumber: 500,
segmentsNumber: L.GEODESIC_SEGMENTS,
}
},

flashPath: function (widget) {
// Close menu on mobile
if (L.ALS.Helpers.isMobile)
L.ALS.Helpers.dispatchEvent(this._layerSystem._menuCloseButton, "click");
this.layerSystem.clickOnMenu();

for (let group of widget.toFlash) {
let layers = group instanceof L.FeatureGroup ? group.getLayers() : [group];
Expand Down
1 change: 0 additions & 1 deletion SynthBase/calculateParameters.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,6 @@ L.ALS.SynthBaseLayer.prototype.calculateParameters = function () {

let names = ["flightHeight", "lx", "Lx", "Bx", "ly", "Ly", "GSI", "IFOV", "GIFOV", "FOV", "GFOV", "timeBetweenCaptures"];


if (this.hasYOverlay) {
this.By = this.Ly * (100 - this["overlayBetweenPaths"]) / 100; // Distance between paths
names.push("By");
Expand Down
2 changes: 1 addition & 1 deletion SynthGeometryLayer/SynthGeometryLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ require("./SynthGeometrySettings.js");
const shp = require("shpjs");

/**
* Shapefile layer
* Layer with geometry from shapefile or GeoJSON
* @class
* @extends L.ALS.Layer
*/
Expand Down
2 changes: 1 addition & 1 deletion SynthGridLayer/SynthGridLayer.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ require("./SynthGridWizard.js");
* @class
* @extends L.ALS.Layer
*/
L.ALS.SynthGridLayer = L.ALS.SynthPolygonLayer.extend({
L.ALS.SynthGridLayer = L.ALS.SynthPolygonLayer.extend(/** @lends L.ALS.SynthGridLayer.prototype */{

defaultName: "Grid Layer",
useZoneNumbers: true,
Expand Down
Loading

0 comments on commit e109b4c

Please sign in to comment.