RoutesMaker/Public/ecma/Models/DotModel.ecma.js

199 lines
5.3 KiB
JavaScript

"use strict";
import {EventModel} from "./EventModel.ecma.js";
/**
* @class
* @constructor
* @param {!L.Map} map
* @param {!number} x
* @param {!number} y
* @param {!number} i
* @param {!Array.<DotModel>} dots
* @returns {void}
* @access public
* @statix
*/
export const DotModel = (function(){
/**
* @constructs DotModel
* @param {!L.Map} map
* @param {!number} x
* @param {!number} y
* @param {!number} i
* @param {!Array.<DotModel>} dots
* @returns {void}
* @access private
* @statix
*/
const DotModel = function(map, x, y, i, dots){
/** @type {DotModel} */
const self = this;
/** @type {Array.<L.Map>} */
this.map = map;
/** @type {number} */
this.i = i;
/** @type {number} */
this.x = x;
/** @type {number} */
this.y = y;
/** @type {L.Marker} */
this.marker = L.marker([y, x], {draggable : true});
/** @type {L.Pulyline|null} */
this.line = null;
/** @type {Array.<DotModel>} */
this.dots = dots;
/** @type {number} */
this.distance = 0;
/** @type {EventModel} */
this.on_change = new EventModel();
/**
* @returns {void}
* @access private
*/
const constructor = () => {
self.marker.addTo(map);
dots.length && (self.line = L.polyline([dots[dots.length - 1].get_dot(), self.get_dot()]).addTo(self.map));
self.marker.on("click", event => {
self.remove();
});
self.marker.on("dragend", event => {
/** @type {L.LatLng} */
const coordenates = event.target.getLatLng();
self.x = coordenates.lng;
self.y = coordenates.lat;
self.remove_lines_linked();
self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
self.dots[self.i + 1].get_dot(),
self.get_dot()
])).addTo(self.map);
self.i && (self.dots[self.i].line = L.polyline([
self.get_dot(),
self.dots[self.i - 1].get_dot()
])).addTo(self.map);
self.recalculate_distance();
});
self.recalculate_distance();
};
/**
* @returns {Object.<string, number>}
* @access public
*/
this.get_leaflet_coordenates = () => ({
lat : self.y,
lng : self.x
});
/**
* @returns {Object.<string, number>}
* @access public
*/
this.get_coordenates = () => ({
latitude : self.y,
longitude : self.x
});
/**
* @returns {[string, number]}
* @access public
*/
this.get_dot = () => [self.y, self.x];
/**
* @returns {void}
* @access public
*/
this.remove_line = () => {
if(self.line){
self.map.removeLayer(self.line);
self.line = null;
};
};
/**
* @returns {void}
* @access public
*/
self.remove_lines_linked = () => {
/** @type {number} */
const l = self.dots.length;
[self.i, self.i + 1].forEach(i => {
i && i < l && self.dots[i].remove_line();
});
};
/**
* @returns {void}
* @access public
*/
this.remove = () => {
self.remove_lines_linked();
self.i && self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
self.dots[self.i + 1].get_dot(),
self.dots[self.i - 1].get_dot()
])).addTo(self.map);
self.dots.splice(self.i, 1);
console.log(["A", self.distance]);
self.dots[self.i + 1].recalculate_distance();
console.log(["B", self.distance]);
self.map.removeLayer(self.marker);
self.dots.slice(self.i).forEach(dot => {
dot.i --;
});
};
/**
* @returns {void}
* @access public
*/
this.recalculate_distance = () => {
/** @type {number} */
const origin = self.distance || 0;
if(self.i){
/** @type {DotModel} */
const previous = self.dots[self.i - 1],
/** @type {number} */
pi_radians = Math.PI / 180,
/** @type {number} */
angle = (
Math.sin((self.y - previous.y) * pi_radians / 2) ** 2 +
Math.cos(self.y * pi_radians) * Math.cos(previous.y * pi_radians) *
Math.sin((self.x - previous.x) * pi_radians / 2) ** 2
);
self.distance = DotModel.EARTH_RADIUS * 2 * Math.atan2(angle ** .5, (1 - angle) ** .5);
}else
self.distance = 0;
origin != self.distance && self.on_change.execute(self);
};
constructor();
};
/** @type {number} */
DotModel.EARTH_RADIUS = 6371000;
return DotModel;
})();