164 lines
4.4 KiB
JavaScript
164 lines
4.4 KiB
JavaScript
"use strict";
|
|
|
|
import {EventModel} from "./EventModel.ecma.js";
|
|
|
|
/**
|
|
* @typedef {import("./RouteModel.ecma.js").RouteModel} RouteModel
|
|
*/
|
|
|
|
/**
|
|
* @class
|
|
* @constructor
|
|
* @param {!RouteModel} route
|
|
* @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 {!RouteModel} route
|
|
* @param {!number} x
|
|
* @param {!number} y
|
|
* @param {!number} i
|
|
* @param {!Array.<DotModel>} dots
|
|
* @returns {void}
|
|
* @access private
|
|
* @statix
|
|
*/
|
|
const DotModel = function(route, longitude, latitude, i){
|
|
|
|
/** @type {DotModel} */
|
|
const self = this;
|
|
|
|
/** @type {RouteModel} */
|
|
this.route = route;
|
|
/** @type {number} */
|
|
this.i = i;
|
|
/** @type {number} */
|
|
this.longitude = longitude;
|
|
/** @type {number} */
|
|
this.latitude = latitude;
|
|
/** @type {any|null} */
|
|
this.marker = null;
|
|
/** @type {any|null} */
|
|
this.line = null;
|
|
/** @type {number} */
|
|
this.distance = 0;
|
|
|
|
/** @type {object.<string, any|null>} */
|
|
this.attributes = {
|
|
/** @type {boolean} */
|
|
visible : true,
|
|
/** @type {boolean} */
|
|
selected : true
|
|
};
|
|
|
|
/** @type {EventModel} */
|
|
this.on_change = new EventModel();
|
|
/** @type {EventModel} */
|
|
this.on_click = new EventModel();
|
|
/** @type {EventModel} */
|
|
this.on_drop = new EventModel();
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
route.routes_maker.map.driver.add_dot(self);
|
|
self.on_click.add(() => {
|
|
self.remove();
|
|
});
|
|
self.on_drop.add((_, longitude, latitude) => {
|
|
self.longitude = longitude;
|
|
self.latitude = latitude;
|
|
self.route.routes_maker.map.driver.redraw_dot_lines(self);
|
|
self.recalculate_distance();
|
|
});
|
|
self.recalculate_distance();
|
|
};
|
|
|
|
/**
|
|
* @returns {[number, number]}
|
|
* @access public
|
|
*/
|
|
this.get_point = () => [self.latitude, self.longitude];
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.remove = () => {
|
|
|
|
const not_unique = self.i && self.i + 1 < route.dots.length;
|
|
|
|
route.routes_maker.map.driver.remove_dot(self);
|
|
route.dots.splice(self.i, 1);
|
|
route.dots.slice(self.i).forEach(dot => {
|
|
dot.i --;
|
|
});
|
|
not_unique && route.routes_maker.map.driver.redraw_dot_lines(route.dots[self.i]);
|
|
not_unique && route.dots[self.i].recalculate_distance();
|
|
|
|
};
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.recalculate_distance = () => {
|
|
|
|
/** @type {number} */
|
|
const origin = self.distance || 0;
|
|
|
|
if(self.i){
|
|
|
|
/** @type {DotModel} */
|
|
const previous = route.dots[self.i - 1],
|
|
/** @type {number} */
|
|
pi_radians = Math.PI / 180,
|
|
/** @type {number} */
|
|
angle = (
|
|
Math.sin((self.latitude - previous.latitude) * pi_radians / 2) ** 2 +
|
|
Math.cos(self.latitude * pi_radians) * Math.cos(previous.latitude * pi_radians) *
|
|
Math.sin((self.longitude - previous.longitude) * 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);
|
|
|
|
};
|
|
|
|
const update_attributes = () => {
|
|
route.routes_maker.map.driver.update_attributes(self)
|
|
};
|
|
|
|
this.selected = ok => {
|
|
self.attributes.selected = ok;
|
|
update_attributes();
|
|
};
|
|
|
|
this.visible = ok => {
|
|
self.attributes.visible = ok;
|
|
update_attributes();
|
|
};
|
|
|
|
constructor();
|
|
|
|
};
|
|
|
|
/** @type {number} */
|
|
DotModel.EARTH_RADIUS = 6371000;
|
|
|
|
return DotModel;
|
|
})(); |