"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.} 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.} dots * @returns {void} * @access private * @statix */ const DotModel = function(map, x, y, i, dots){ /** @type {DotModel} */ const self = this; /** @type {Array.} */ 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.} */ 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.} * @access public */ this.get_leaflet_coordenates = () => ({ lat : self.y, lng : self.x }); /** * @returns {Object.} * @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; })();