remove globus

This commit is contained in:
Zemledelec 2018-03-15 00:36:11 +03:00
parent f2783e2876
commit be25af6bef
211 changed files with 0 additions and 58877 deletions

View File

@ -1,170 +0,0 @@
/**
* @module og/Clock
*/
'use strict';
import { Events } from './Events.js';
import * as jd from './astro/jd.js';
/**
* Class represents application timer that stores custom current julian datetime, and time speed multiplier.
* @class
* @param {Object} [params]: - Clock parameters:
* @param {number} [params.startDate=0.0] - Julian start date.
* @param {number} [params.endDate=0.0] - Julian end date.
* @param {number} [params.currentDate] - Julian current date. Default: current date.
* @param {number} [params.multiplier=1.0] - Time speed multiolier.
*/
class Clock {
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
constructor(params) {
params = params || {};
this._id = Clock._staticCounter++;
/**
* Clock name.
* @public
* @type {string}
*/
this.name = params.name || "";
/**
* Clock events.
* @public
* @type {Events}
*/
this.events = new Events([
"tick",
"end"
]);
/**
* Start julian date clock loop.
* @public
* @type {number}
*/
this.startDate = params.startDate || 0;
/**
* End julian date clock loop.
* @public
* @type {number}
*/
this.endDate = params.endDate || 0;
var currentDate = params.currentDate || jd.DateToUTC(new Date());
if (params.startDate && currentDate < params.startDate) {
currentDate = params.startDate;
}
if (params.endDate && currentDate > params.endDate) {
currentDate = params.endDate;
}
/**
* Current julian datetime.
* @public
* @type {number}
*/
this.currentDate = currentDate;
/**
* Timer speed multiplier.
* @public
* @type {number}
*/
this.multiplier = params.multiplier !== undefined ? params.multiplier : 1.0;
/**
* Animation frame delta time.
* @public
* @readonly
* @type {number}
*/
this.deltaTicks = 0;
/**
* Timer activity.
* @public
* @type {boolean}
*/
this.active = true;
}
/**
* Sets current clock datetime.
* @public
* @param {Object} date - JavaScript Date object.
*/
setDate(date) {
var d = jd.DateToUTC(date);
if (this.startDate && d < this.startDate) {
d = this.startDate;
}
if (this.endDate && d > this.endDate) {
d = this.endDate;
}
this.currentDate = d;
}
/**
* Returns current application date.
* @public
* @returns {Date} - Current date.
*/
getDate() {
return jd.UTCtoDate(this.currentDate);
}
reset() {
if (this.startDate) {
this.currentDate = this.startDate;
}
}
_tick(dt) {
this.deltaTicks = dt * this.multiplier;
if (this.active) {
var cd = jd.addMilliseconds(this.currentDate, this.deltaTicks);
if (this.multiplier > 0) {
if (this.endDate && cd > this.endDate) {
this.currentDate = this.startDate;
this.events.dispatch(this.events.end, this);
} else {
this.currentDate = cd;
}
} else {
if (this.startDate && cd < this.startDate) {
this.currentDate = this.endDate;
this.events.dispatch(this.events.end, this);
} else {
this.currentDate = cd;
}
}
this.events.dispatch(this.events.tick, this);
}
}
/**
* @public
* @param {Clock} clock - Clock instance to compare.
* @returns {boolean} - Returns true if a clock is the same instance.
*/
equal(clock) {
return this._id === clock._id;
}
};
export { Clock };

View File

@ -1,170 +0,0 @@
/**
* @module og/Events
*/
'use strict';
import { stamp } from './utils/shared.js';
/**
* Base events class to handle custom events.
* @class
* @param {Array.<string>} [eventNames] - Event names that could be dispatched.
*/
class Events {
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
constructor(eventNames) {
/**
* Registered event names.
* @protected
* @type {Array.<string>}
*/
this._eventNames = [];
eventNames && this.registerNames(eventNames);
/**
* Event identifier.
* @protected
* @type {number}
*/
this._counter = 0;
/**
* Stop propagation flag
* @protected
* @type {boolean}
*/
this._stopPropagation = false;
this._stampCache = {};
this.__id = Events.__staticCounter++;
}
/**
* Function that creates event object properties that would be dispatched.
* @public
* @param {Array.<string>} eventNames - Specified event names list.
*/
registerNames(eventNames) {
for (var i = 0; i < eventNames.length; i++) {
this[eventNames[i]] = { "active": true, "handlers": [] };
this._eventNames.push(eventNames[i]);
}
}
/**
* Returns true if event callback has stamped.
* @protected
* @param {Object} name - Event identifier.
* @param {Object} obj - Event callback.
* @return {boolean} -
*/
_stamp(name, obj) {
var ogid = stamp(obj);
var st = name + "_" + this.__id + "_" + ogid;
if (!this._stampCache[st]) {
this._stampCache[st] = ogid;
return true;
}
return false;
}
/**
* Attach listener.
* @public
* @param {string} name - Event name to listen.
* @param {eventCallback} callback - Event callback function.
* @param {Object} sender - Event callback function owner.
*/
on(name, callback, sender) {
if (this._stamp(name, callback)) {
this[name] && this[name].handlers.unshift({ "sender": sender || this, "callback": callback });
}
}
/**
* Stop listening event name with specified callback function.
* @public
* @param {string} name - Event name.
* @param {eventCallback} callback - Attached event callback.
*/
off(name, callback) {
var st = name + "_" + this.__id + "_" + callback._openglobus_id;
if (callback._openglobus_id && this._stampCache[st]) {
var h = this[name].handlers;
var i = h.length;
var indexToRemove = -1;
while (i--) {
var hi = h[i];
if (hi.callback._openglobus_id === callback._openglobus_id) {
indexToRemove = i;
break;
}
}
if (indexToRemove !== -1) {
h.splice(indexToRemove, 1);
this._stampCache[st] = undefined;
delete this._stampCache[st];
}
}
}
/**
* Dispatch event.
* @public
* @param {Object} event - Event instance property that created by event name.
* @param {Object} [obj] - Event object.
*/
dispatch(event, obj) {
if (event && event.active) {
var h = event.handlers;
var i = h.length;
while (i-- && !this._stopPropagation) {
var e = h[i];
e.callback.call(e.sender, obj);
}
}
this._stopPropagation = false;
}
/**
* Brakes events propagation.
* @public
*/
stopPropagation() {
this._stopPropagation = true;
}
/**
* Removes all events.
* @public
*/
clear() {
for (var i = 0; i < this._eventNames.length; i++) {
var e = this[this._eventNames[i]];
e.handlers.length = 0;
e.handlers = [];
}
this._eventNames.length = 0;
this._eventNames = [];
}
};
export { Events };

View File

@ -1,316 +0,0 @@
/**
* @module og/Extent
*/
'use strict';
import * as math from './math.js';
import * as mercator from './mercator.js';
import { LonLat } from './LonLat.js';
/**
* Represents geographical coordinates extent.
* @class
* @param {og.LonLat} [sw] - South West extent corner coordiantes.
* @param {og.LonLat} [ne] - North East extent corner coordiantes.
*/
const Extent = function (sw, ne) {
/**
* @public
*/
this.southWest = sw || new LonLat();
/**
* @public
*/
this.northEast = ne || new LonLat();
};
/**
* Whole mercator extent.
* @const
*/
Extent.FULL_MERC = new Extent(LonLat.SW_MERC, LonLat.NE_MERC);
/**
* Degrees extent from north mercator limit to north pole.
* @const
*/
Extent.NORTH_POLE_DEG = new Extent(LonLat.NW_MERC_DEG, new LonLat(180.0, 90.0));
/**
* Degrees extent from south pole to south mercator limit.
* @const
*/
Extent.SOUTH_POLE_DEG = new Extent(new LonLat(-180.0, -90.0), LonLat.SE_MERC_DEG);
/**
* Creates extent instance from values in array.
* @static
* @param {Array.<number,number,number,number>} arr - South west and north east longitude and latidudes packed in array.
* @return {og.Extent} Extent object.
*/
Extent.createFromArray = function (arr) {
return new Extent(new LonLat(arr[0], arr[1]), new LonLat(arr[2], arr[3]));
};
/**
* Creates bound extent instance by coordinate array.
* @static
* @param {Array.<og.LonLat>} arr - Coordinate array.
* @return {og.Extent} Extent object.
*/
Extent.createByCoordinates = function (arr) {
var lonmin = math.MAX, lonmax = math.MIN,
latmin = math.MAX, latmax = math.MIN;
for (var i = 0; i < arr.length; i++) {
var vi = arr[i];
if (vi.lon < lonmin) lonmin = vi.lon;
if (vi.lon > lonmax) lonmax = vi.lon;
if (vi.lat < latmin) latmin = vi.lat;
if (vi.lat > latmax) latmax = vi.lat;
}
return new Extent(new LonLat(lonmin, latmin), new LonLat(lonmax, latmax));
};
/**
* Creates bound extent instance by coordinate array.
* @static
* @param {Array.<Array<number,number>>} arr - Coordinate array.
* @return {og.Extent} Extent object.
*/
Extent.createByCoordinatesArr = function (arr) {
var lonmin = math.MAX, lonmax = math.MIN,
latmin = math.MAX, latmax = math.MIN;
for (var i = 0; i < arr.length; i++) {
var vi = arr[i];
if (vi[0] < lonmin) lonmin = vi[0];
if (vi[0] > lonmax) lonmax = vi[0];
if (vi[1] < latmin) latmin = vi[1];
if (vi[1] > latmax) latmax = vi[1];
}
return new Extent(new LonLat(lonmin, latmin), new LonLat(lonmax, latmax));
};
/**
* Creates extent by meractor grid tile coordinates.
* @static
* @param {number} x
* @param {number} y
* @param {number} z
* @returns {og.Extent}
*/
Extent.fromTile = function (x, y, z, width, height) {
width = width || mercator.POLE_DOUBLE;
height = height || mercator.POLE_DOUBLE;
var H = Math.pow(2, z),
W = Math.pow(2, z),
lnSize = width / W,
ltSize = height / H;
var left = -width * 0.5 + x * lnSize,
top = height * 0.5 - y * ltSize,
bottom = top - ltSize,
right = left + lnSize;
return new Extent(new LonLat(left, bottom), new LonLat(right, top));
};
/**
* Sets current bounding extent object by coordinate array.
* @public
* @param {Array.<og.LonLat>} arr - Coordinate array.
* @return {og.Extent} Current extent.
*/
Extent.prototype.setByCoordinates = function (arr) {
var lonmin = math.MAX, lonmax = math.MIN,
latmin = math.MAX, latmax = math.MIN;
for (var i = 0; i < arr.length; i++) {
var vi = arr[i];
if (vi.lon < lonmin) lonmin = vi.lon;
if (vi.lon > lonmax) lonmax = vi.lon;
if (vi.lat < latmin) latmin = vi.lat;
if (vi.lat > latmax) latmax = vi.lat;
}
this.southWest.lon = lonmin;
this.southWest.lat = latmin;
this.northEast.lon = lonmax;
this.northEast.lat = latmax;
return this;
};
/**
* Determines if point inside extent.
* @public
* @param {LonLat} lonlat - Coordinate point.
* @return {boolean} Returns true if point inside extent.
*/
Extent.prototype.isInside = function (lonlat) {
var sw = this.southWest,
ne = this.northEast;
return lonlat.lon >= sw.lon && lonlat.lon <= ne.lon &&
lonlat.lat >= sw.lat && lonlat.lat <= ne.lat;
};
/**
* Returns true if two extent overlap each other.
* @public
* @param {Extent} e - Another extent.
* @return {boolean}
*/
Extent.prototype.overlaps = function (e) {
var sw = this.southWest,
ne = this.northEast;
return sw.lon <= e.northEast.lon && ne.lon >= e.southWest.lon &&
sw.lat <= e.northEast.lat && ne.lat >= e.southWest.lat;
};
/**
* Gets extent width.
* @public
* @return {number} Extent width.
*/
Extent.prototype.getWidth = function () {
return this.northEast.lon - this.southWest.lon;
};
/**
* Gets extent height.
* @public
* @return {number} Extent height.
*/
Extent.prototype.getHeight = function () {
return this.northEast.lat - this.southWest.lat
};
/**
* Creates clone instance of the current extent.
* @public
* @return {og.Extent} Extent clone.
*/
Extent.prototype.clone = function () {
return new Extent(this.southWest.clone(), this.northEast.clone());
};
/**
* Gets the center coordinate of the extent.
* @public
* @return {number} Center coordinate.
*/
Extent.prototype.getCenter = function () {
var sw = this.southWest, ne = this.northEast;
return new LonLat(sw.lon + (ne.lon - sw.lon) * 0.5, sw.lat + (ne.lat - sw.lat) * 0.5);
};
/**
* @public
*/
Extent.prototype.getNorthWest = function () {
return new LonLat(this.southWest.lon, this.northEast.lat);
};
/**
* @public
*/
Extent.prototype.getNorthEast = function () {
return new LonLat(this.northEast.lon, this.northEast.lat);
};
Extent.prototype.getSouthWest = function () {
return new LonLat(this.southWest.lon, this.southWest.lat);
};
/**
* @public
*/
Extent.prototype.getSouthEast = function () {
return new LonLat(this.northEast.lon, this.southWest.lat);
};
/**
* @public
*/
Extent.prototype.getNorth = function () {
return this.northEast.lat;
};
Extent.prototype.getEast = function () {
return this.northEast.lon;
};
/**
* @public
*/
Extent.prototype.getWest = function () {
return this.southWest.lon;
};
/**
* @public
*/
Extent.prototype.getSouth = function () {
return this.southWest.lat;
};
/**
* Returns extents are equals.
* @param {og.Extent} extent - Extent.
* @returns {boolean}
*/
Extent.prototype.equals = function (extent) {
return this.southWest.lon === extent.southWest.lon && this.southWest.lat === extent.southWest.lat &&
this.northEast.lon === extent.northEast.lon && this.northEast.lat === extent.northEast.lat;
};
/**
* Converts extent coordinates to mercator projection coordinates.
* @public
* @return {og.Extent} New instance of the current extent.
*/
Extent.prototype.forwardMercator = function () {
return new Extent(this.southWest.forwardMercator(), this.northEast.forwardMercator());
};
/**
* Converts extent coordinates from mercator projection to degrees.
* @public
* @return {og.Extent} New instance of the current extent.
*/
Extent.prototype.inverseMercator = function () {
return new Extent(this.southWest.inverseMercator(), this.northEast.inverseMercator());
};
/**
* Gets cartesian bounding bounds of the current ellipsoid.
* @public
* @param {og.Ellipsoid} ellipsoid - Ellipsoid.
* @return {Array.<number,number,number,number,number,number>} Cartesian 3d coordinate array.
*/
Extent.prototype.getCartesianBounds = function (ellipsoid) {
var xmin = math.MAX, xmax = math.MIN, ymin = math.MAX,
ymax = math.MIN, zmin = math.MAX, zmax = math.MIN;
var v = [new LonLat(this.southWest.lon, this.southWest.lat),
new LonLat(this.southWest.lon, this.northEast.lat),
new LonLat(this.northEast.lon, this.northEast.lat),
new LonLat(this.northEast.lon, this.southWest.lat)];
for (var i = 0; i < v.length; i++) {
var coord = ellipsoid.lonLatToCartesian(v[i]);
var x = coord.x, y = coord.y, z = coord.z;
if (x < xmin) xmin = x;
if (x > xmax) xmax = x;
if (y < ymin) ymin = y;
if (y > ymax) ymax = y;
if (z < zmin) zmin = z;
if (z > zmax) zmax = z;
}
return [xmin, xmax, ymin, ymax, zmin, zmax];
};
Extent.prototype.toString = function () {
return "[" + this.southWest.lon + ", " + this.southWest.lat + ", " + this.northEast.lon + ", " + this.northEast.lat + "]";
};
export { Extent };

View File

@ -1,144 +0,0 @@
/**
* @module og/Frustum
*/
'use strict';
/**
* Frustum object, part of the camera object.
* @class
*/
class Frustum {
constructor() {
/**
* Frustum planes.
* @private
* @type {Array.<Array.<number>>}
*/
this._f = new Array(6);
for (var i = 0; i < 6; i++)
this._f[i] = new Array(4);
}
/**
* Normalize frustum plane.
* @static
* @param {Array.<number>} plane - Frustum plane coordinates.
*/
static planeNormalize(plane) {
var t = Math.sqrt(plane[0] * plane[0] + plane[1] * plane[1] + plane[2] * plane[2]);
plane[0] /= t;
plane[1] /= t;
plane[2] /= t;
plane[3] /= t;
}
/**
* Camera's projection matrix values.
* @public
* @param {Array.<number>} clip - Projection matrix parameters.
*/
setFrustum(clip) {
/* Right */
this._f[0][0] = clip[3] - clip[0];
this._f[0][1] = clip[7] - clip[4];
this._f[0][2] = clip[11] - clip[8];
this._f[0][3] = clip[15] - clip[12];
Frustum.planeNormalize(this._f[0]);
/* Left */
this._f[1][0] = clip[3] + clip[0];
this._f[1][1] = clip[7] + clip[4];
this._f[1][2] = clip[11] + clip[8];
this._f[1][3] = clip[15] + clip[12];
Frustum.planeNormalize(this._f[1]);
/* Bottom */
this._f[2][0] = clip[3] + clip[1];
this._f[2][1] = clip[7] + clip[5];
this._f[2][2] = clip[11] + clip[9];
this._f[2][3] = clip[15] + clip[13];
Frustum.planeNormalize(this._f[2]);
/* Top */
this._f[3][0] = clip[3] - clip[1];
this._f[3][1] = clip[7] - clip[5];
this._f[3][2] = clip[11] - clip[9];
this._f[3][3] = clip[15] - clip[13];
Frustum.planeNormalize(this._f[3]);
/* Backward */
this._f[4][0] = clip[3] - clip[2];
this._f[4][1] = clip[7] - clip[6];
this._f[4][2] = clip[11] - clip[10];
this._f[4][3] = clip[15] - clip[14];
Frustum.planeNormalize(this._f[4]);
/* Forward */
this._f[5][0] = clip[3] + clip[2];
this._f[5][1] = clip[7] + clip[6];
this._f[5][2] = clip[11] + clip[10];
this._f[5][3] = clip[15] + clip[14];
Frustum.planeNormalize(this._f[5]);
}
/**
* Returns true if a point in the frustum.
* @public
* @param {og.math.Vec3} point - Cartesian point.
* @returns {boolean}
*/
containsPoint(point) {
var d;
for (var p = 0; p < 6; p++) {
d = point.dotArr(this._f[p]) + this._f[p][3];
if (d <= 0)
return false;
}
return true;
}
/**
* Returns true if the frustum contains a bonding sphere.
* @public
* @param {og.bv.Sphere} sphere - Bounding sphere.
* @returns {boolean}
*/
containsSphere(sphere) {
var r = -sphere.radius;
if (sphere.center.dotArr(this._f[0]) + this._f[0][3] <= r) return false;
if (sphere.center.dotArr(this._f[1]) + this._f[1][3] <= r) return false;
if (sphere.center.dotArr(this._f[2]) + this._f[2][3] <= r) return false;
if (sphere.center.dotArr(this._f[3]) + this._f[3][3] <= r) return false;
if (sphere.center.dotArr(this._f[4]) + this._f[4][3] <= r) return false;
if (sphere.center.dotArr(this._f[5]) + this._f[5][3] <= r) return false;
return true;
}
/**
* Returns true if the frustum contains a bounding box.
* @public
* @param {og.bv.Box} box - Bounding box.
* @returns {boolean}
*/
containsBox(box) {
var result = true, cout, cin;
for (var i = 0; i < 6; i++) {
cout = 0; cin = 0;
for (var k = 0; k < 8 && (cin == 0 || cout == 0); k++) {
var d = box.vertices[k].dotArr(this._f[i]) + this._f[i][3];
if (d < 0)
cout++;
else
cin++;
}
if (cin == 0)
return false;
else if (cout > 0)
result = true;
}
return (result);
}
};
export { Frustum };

View File

@ -1,258 +0,0 @@
/**
* @module og/Globe
*/
'use strict';
import { EmptyTerrain } from './terrain/EmptyTerrain.js';
import { Handler } from './webgl/Handler.js';
import { Planet } from './scene/Planet.js';
import { Renderer } from './renderer/Renderer.js';
import { wgs84 } from './ellipsoid/wgs84.js';
import { EarthCoordinates } from './control/EarthCoordinates.js';
import { MouseNavigation } from './control/MouseNavigation.js';
import { TouchNavigation } from './control/TouchNavigation.js';
import { Sun } from './control/Sun.js';
import { ZoomControl } from './control/ZoomControl.js';
/** @const {string} */
const CANVAS_ID_PREFIX = "globus_viewport_";
/** @const {string} */
const PLANET_NAME_PREFIX = "globus_planet_";
/**
* Creates a WebGL context with globe.
* @class
*
* @example <caption>Basic initialization</caption>
* globus = new og.Globe({
* 'atmosphere': false,
* 'target': 'globus',
* 'name': 'Earth',
* 'controls': [
* new og.control.MouseNavigation({ autoActivate: true }),
* new og.control.KeyboardNavigation({ autoActivate: true }),
* new og.control.EarthCoordinates({ autoActivate: true, center: false }),
* new og.control.LayerSwitcher({ autoActivate: true }),
* new og.control.ZoomControl({ autoActivate: true }),
* new og.control.TouchNavigation({ autoActivate: true }),
* new og.control.Sun({ autoActivate: true })
* ],
* 'skybox': skybox,
* 'terrain': terrain,
* 'layers': [
* new og.layer.XYZ("OpenStreetMap", { isBaseLayer: true, url: "http://b.tile.openstreetmap.org/{z}/{x}/{y}.png", visibility: true, attribution: 'Data @ <a href="http://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="http://www.openstreetmap.org/copyright">ODbL</a>' })
* ],
* 'autoActivated': true
* });
*
* @param {object} options - Options:
* @param {string} options.target - HTML element id where planet canvas have to be created.
* @param {boolean} [options.skybox] - Render skybox. null - default.
* @param {boolean} [options.atmosphere] - Render planet with atmosphere. False - default.
* @param {string} [options.name] - Planet name. Default is unic identifier.
* @param {og.terrain.Terrain} [options.terrain] - Terrain provider. Default no terrain - og.terrain.EmptyTerrain.
* @param {Array.<og.control.BaseControl>} [options.controls] - Renderer controls array.
* @param {Array.<og.layer.Layer>} [options.layers] - Planet layers.
* @param {og.Extent} [options.viewExtent] - Viewable starting extent.
* @param {boolean} [options.autoActivate] - Globe rendering auto activation flag. True is default.
*/
class Globe {
constructor(options) {
//Canvas creation.
var _canvasId = CANVAS_ID_PREFIX + Globe._staticCounter++;
this._canvas = document.createElement("canvas");
this._canvas.id = _canvasId;
this._canvas.style.width = "100%";
this._canvas.style.height = "100%";
this._canvas.style.display = "block";
this._canvas.style.opacity = "1.0";
/**
* Dom element where WebGL canvas creates
* @public
* @type {Element}
*/
this.div = document.getElementById(options.target);
this.div.appendChild(this._canvas);
this.div.classList.add("ogViewport");
function _disableWheel() { return false; }
function _enableWheel() { return true; }
this.div.onmouseenter = function () { document.onmousewheel = _disableWheel; };
this.div.onmouseleave = function () { document.onmousewheel = _enableWheel; };
//WegGL handler creation
var _handler = new Handler(_canvasId, { 'alpha': false, 'antialias': false });
_handler.initialize();
/**
* Interface for the renderer context(events, input states, renderer nodes etc.)
* @public
* @type {og.Renderer}
*/
this.renderer = new Renderer(_handler);
this.renderer.initialize();
this.renderer.div = this.div;
this.renderer.div.attributions = document.createElement("div");
this.renderer.div.attributions.classList.add("ogAttribution");
this.div.appendChild(this.renderer.div.attributions);
//Skybox
if (options.skybox) {
this.renderer.addRenderNode(options.skybox);
}
/**
* Planet node name. Access with this.renderer.<name>
* @private
* @type {String}
*/
this._planetName = options.name ? options.name : PLANET_NAME_PREFIX + Globe._staticCounter;
if (options.atmosphere) {
/**
* Render node renders a planet.
* @public
* @type {og.scene.Planet|og.scene.PlanetAtmosphere}
*/
//TODO:
} else {
this.planet = new Planet(this._planetName, options.ellipsoid ? options.ellipsoid : wgs84);
}
//Attach terrain provider
if (options.terrain) {
this.planet.setTerrain(options.terrain);
} else {
this.planet.setTerrain(new EmptyTerrain());
}
this.renderer.addRenderNode(this.planet);
this.sun;
//Add controls
if (options.controls) {
this.planet.addControls(options.controls);
} else {
this.planet.addControls([
new MouseNavigation(),
new TouchNavigation(),
new ZoomControl(),
new EarthCoordinates()
]);
}
var _controls = this.renderer.controls;
for (var i = 0; i < _controls.length; i++) {
if (_controls[i] instanceof Sun) {
this.sun = _controls[i];
break;
}
}
if (!this.sun) {
this.sun = new Sun();
this.planet.addControl(this.sun);
}
if (options.sun) {
if (options.sun.active !== undefined && !options.sun.active) {
this.sun.deactivate();
}
}
if (options.layers) {
this.planet.addLayers(options.layers);
}
//TODO: view center, altitude, extent
if (options.viewExtent) {
this.planet.viewToExtent(options.viewExtent);
}
this._opacityCounter = 0;
this._fadeHandler = null;
this._stopHandler = null;
//Run!
if (Globe.isUndefined(options.autoActivate) || options.autoActivate) {
this.fadeIn(500);
this.renderer.start();
}
}
/**
* Starts screen brightness fading in effect by the duration time.
* @public
* @param {number} duration - fadein duration time.
*/
fadeIn(duration) {
clearInterval(this._stopHandler);
clearInterval(this._fadeHandler);
this._canvas.style.opacity = 0.0;
this._opacityCounter = 0.0;
var delta = 10.0;
var d = 1.0 / (duration / delta);
this._fadeHandler = setInterval(() => {
this._opacityCounter += d;
if (this._opacityCounter >= 1) {
this._opacityCounter = 1.0;
clearInterval(this._fadeHandler);
}
this._canvas.style.opacity = this._opacityCounter;
}, delta);
}
/**
* Starts screen brightness fading out effect by the duration time.
* @public
* @param {number} duration - Fadeout duration time.
*/
fadeOut(duration) {
clearInterval(this._stopHandler);
clearInterval(this._fadeHandler);
this._canvas.style.opacity = 1.0;
this._opacityCounter = 1.0;
var delta = 10.0;
var d = 1 / (duration / delta);
this._fadeHandler = setInterval(() => {
this._opacityCounter -= d;
if (this._opacityCounter <= 0.0) {
this._opacityCounter = 0.0;
clearInterval(this._fadeHandler);
}
this._canvas.style.opacity = this._opacityCounter;
}, delta);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Returns true if the object pointer is undefined.
* @function
* @param {Object} obj - Object pointer.
* @returns {boolean} Returns true if object is undefined.
*/
static isUndefined(obj) {
return obj === void 0;
}
};
export { Globe };

View File

@ -1,224 +0,0 @@
/**
* @module og/ImageCanvas
*/
'use strict';
/**
* Usefull class for working with JS canvas object.
* @class
* @param {number} [width] - Canvas width. Default 256.
* @param {number} [height] - Canvas height. Default 256.
*/
class ImageCanvas {
constructor(width, height) {
/**
* Canvas object.
* @protected
* @type {Object}
*/
this._canvas = document.createElement("canvas");
this._canvas.width = width || 256;
this._canvas.height = height || 256;
/**
* Canvas context.
* @protected
* @type {Object}
*/
this._context = this._canvas.getContext('2d');
}
/**
* Returns canvas object.
* @public
* @returns {Object}
*/
getCanvas() {
return this._canvas;
}
/**
* Returns canvas context pointer.
* @public
* @returns {Object}
*/
getContext() {
return this._context;
}
/**
* Fills canvas RGBA with zeroes.
* @public
*/
fillEmpty() {
var imgd = this._context.getImageData(0, 0, this._canvas.width, this._canvas.height);
var pixels = imgd.data;
for (var i = 0, n = pixels.length; i < n; i += 4) {
pixels[i] = pixels[i + 1] = pixels[i + 2] = pixels[i + 3] = 0;
}
this._context.putImageData(imgd, 0, 0);
}
/**
* Gets canvas pixels RGBA data.
* @public
* @returns {Array.<number>}
*/
getData() {
var imgd = this._context.getImageData(0, 0, this._canvas.width, this._canvas.height);
return imgd.data;
}
/**
* Fill the canvas by color.
* @public
* @param {string} color - CSS string color.
*/
fillColor(color) {
this._context.fillStyle = color;
this._context.fillRect(0, 0, this._canvas.width, this._canvas.height);
};
/**
* Sets RGBA pixel data.
* @public
* @param {Array.<number>} data - Array RGBA data.
*/
setData(data) {
var imageData = this._context.createImageData(this._canvas.width, this._canvas.height);
imageData.data.set(data);
this._context.putImageData(imageData, 0, 0);
}
/**
* Resize canvas.
* @public
* @param {number} width - Width.
* @param {number} height - Height.
*/
resize(width, height) {
this._canvas.width = width;
this._canvas.height = height;
this._context = this._canvas.getContext('2d');
}
/**
* Draw an image on the canvas.
* @public
* @param {Image} img - Draw image.
* @param {number} [x] - Left top image corner X coordinate on the canvas.
* @param {number} [y] - Left top image corner Y coordinate on the canvas.
* @param {number} [width] - Image width slice. Image width is default.
* @param {number} [height] - Image height slice. Image height is default.
*/
drawImage(img, x, y, width, height) {
this._context = this._canvas.getContext('2d');
this._context.drawImage(img, x || 0, y || 0, width || img.width, height || img.height);
}
/**
* Converts canvas to JS image object.
* @public
* @returns {Image}
*/
getImage() {
var img = new Image();
img.width = this.getWidth();
img.height = this.getHeight();
img.src = this._canvas.toDataURL("image/png");
return img;
}
/**
* Get measured text width.
* @public
* @param {string} text - Measured text.
* @returns {number}
*/
getTextWidth(text) {
var metrics = this._context.measureText(text);
return Math.round(metrics.width);
}
/**
* Draw a text on the canvas.
* @public
* @param {string} text - Text.
* @param {number} [x] - Canvas X - coordinate. 0 - default.
* @param {number} [y] - Canvas Y - coordinate. 0 - default.
* @param {string} [font] - Font style. 'normal 14px Verdana' - is default.
* @param {string} [color] - Css font color.
*/
drawText(text, x, y, font, color) {
this._context.fillStyle = color || 'black';
this._context.font = font || 'normal 14px Verdana';
this._context.fillText(text, x || 0, y || 14);
}
/**
* Gets canvas width.
* @public
* @returns {number}
*/
getWidth() {
return this._canvas.width;
}
/**
* Gets canvas height.
* @public
* @returns {number}
*/
getHeight() {
return this._canvas.height;
}
/**
* Load image to canvas.
* @public
* @param {string} url - Image url.
* @pararm {imageCallback} [callback] - Image onload callback.
*/
loadImage(url, callback) {
var img = new Image();
var that = this;
img.onload = function () {
that.resize(img.width, img.height);
that._context.drawImage(img, 0, 0, img.width, img.height);
callback && callback(img);
}
img.src = url;
}
/**
* Open canvas image in the new window.
* @public
*/
openImage() {
var img = this.getImage();
var dataUrl = img.src;
var windowContent = '<!DOCTYPE html>';
windowContent += '<html>'
windowContent += '<head><title>Print</title></head>';
windowContent += '<body>'
windowContent += '<img src="' + dataUrl + '">';
windowContent += '</body>';
windowContent += '</html>';
var printWin = window.open('', '', 'width=' + img.width + 'px ,height=' + img.height + 'px');
printWin.document.open();
printWin.document.write(windowContent);
printWin.document.close();
printWin.focus();
}
destroy() {
this._canvas.width = 1;
this._canvas.height = 1;
this._canvas = null;
this._context = null;
}
};
export { ImageCanvas };

View File

@ -1,48 +0,0 @@
/**
* @module og/Lock
*/
'use strict';
class Lock {
constructor() {
this._lock = 0;
}
lock(key) {
this._lock |= (1 << key._id);
}
free(key) {
this._lock &= ~(1 << key._id);
}
isFree() {
return this._lock === 0;
}
isLocked() {
return this._lock !== 0;
}
};
class Key {
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
constructor() {
this._id = Key._staticCounter++;
}
};
export { Lock, Key };

View File

@ -1,175 +0,0 @@
/**
* @module og/LonLat
*/
'use strict';
import * as mercator from './mercator.js';
/**
* Represents a geographical point with a certain latitude, longitude and height.
* @class
* @param {number} [lon] - Longitude.
* @param {number} [lat] - Latitude.
* @param {number} [height] - Height over the surface.
*/
const LonLat = function (lon, lat, height) {
/**
* Longitude.
* @public
* @type {number}
*/
this.lon = lon || 0;
/**
* Latitude.
* @public
* @type {number}
*/
this.lat = lat || 0;
/**
* Height.
* @public
* @type {number}
*/
this.height = height || 0;
};
/**
* Creates coordinates array.
* @static
* @param{Array.<Array<number,number,number>>} arr - Coordinates array data.
* @return{Array.<og.LonLat>} the same coordinates array but each element is LonLat instance.
*/
LonLat.join = function (arr) {
var res = [];
for (var i = 0; i < arr.length; i++) {
var ai = arr[i];
res[i] = new LonLat(ai[0], ai[1], ai[2]);
}
return res;
};
/**
* Creates an object by coordinate array.
* @static
* @param {Array.<number,number,number>} arr - Coordiante array, where first is longitude, second is latitude and third is a height.
* @returns {og.LonLat}
*/
LonLat.createFromArray = function (arr) {
return new LonLat(arr[0], arr[1], arr[2]);
};
/**
* Converts degrees to mercator coordinates.
* @static
* @param {number} lon - Degrees longitude.
* @param {number} lat - Degrees latitude.
* @param {number} [height] - Height.
* @returns {og.LonLat}
*/
LonLat.forwardMercator = function (lon, lat, height) {
var x = lon * mercator.POLE / 180;
var y = Math.log(Math.tan((90 + lat) * Math.PI / 360)) / Math.PI * mercator.POLE;
return new LonLat(x, y, height);
};
/**
* Converts mercator to degrees coordinates.
* @static
* @param {number} x - Mercator longitude.
* @param {number} y - Mercator latitude.
* @param {number} [height] - Height.
* @returns {og.LonLat}
*/
LonLat.inverseMercator = function (x, y, height) {
var lon = 180 * x / mercator.POLE;
var lat = 180 / Math.PI * (2 * Math.atan(Math.exp((y / mercator.POLE) * Math.PI)) - Math.PI / 2);
return new LonLat(lon, lat, height);
};
/**
* Sets coordinates.
* @public
* @param {number} [lon] - Longitude.
* @param {number} [lat] - Latitude.
* @param {number} [height] - Height.
* @returns {og.LonLat}
*/
LonLat.prototype.set = function (lon, lat, height) {
this.lon = lon || 0;
this.lat = lat || 0;
this.height = height || 0;
return this;
};
/**
* Copy coordinates.
* @public
* @param {og.LonLat} [lonLat] - Coordinates to copy.
* @returns {og.LonLat}
*/
LonLat.prototype.copy = function (lonLat) {
this.lon = lonLat.lon;
this.lat = lonLat.lat;
this.height = lonLat.height;
return this;
};
/**
* Clone the coordiante.
* @public
* @returns {og.LonLat}
*/
LonLat.prototype.clone = function () {
return new LonLat(this.lon, this.lat, this.height);
};
/**
* Converts to mercator coordinates.
* @public
* @returns {og.LonLat}
*/
LonLat.prototype.forwardMercator = function () {
return LonLat.forwardMercator(this.lon, this.lat, this.height);
};
LonLat.prototype.forwardMercatorEPS01 = function () {
var lat = this.lat;
if (lat > 89.9) {
lat = 89.9;
} else if (lat < -89.9) {
lat = -89.9;
}
return new LonLat(
this.lon * mercator.POLE / 180,
Math.log(Math.tan((90 + lat) * Math.PI / 360)) / Math.PI * mercator.POLE);
};
/**
* Converts from mercator coordinates.
* @public
* @returns {og.LonLat}
*/
LonLat.prototype.inverseMercator = function () {
return LonLat.inverseMercator(this.lon, this.lat, this.height);
};
/**
* Compares coordinates.
* @public
* @param {og.LonLat} b - Coordinate to compare with.
* @returns {boolean}
*/
LonLat.prototype.equal = function (b) {
if (b.height) {
return this.lon == b.lon && this.lat == b.lat && this.height == b.height;
} else {
return this.lon == b.lon && this.lat == b.lat;
}
};
export { LonLat };

View File

@ -1,69 +0,0 @@
/**
* @module og/QueueArray
*/
'use strict';
class QueueArray {
constructor(size) {
this._size = size || 2048;
this._array = new Array(this._size);
this._popIndex = parseInt(this._size * 0.5);
this._shiftIndex = this._popIndex;
this.length = 0;
}
clear() {
this._array.length = 0;
this._array = new Array(this._size);
this._popIndex = parseInt(this._size * 0.5);
this._shiftIndex = this._popIndex;
this.length = 0;
}
push(data) {
this.length++;
this._array[this._popIndex++] = data;
}
pop() {
if (this.length) {
this.length--;
var res = this._array[--this._popIndex]
this._array[this._popIndex] = null;
if (!this._array[this._popIndex - 1]) {
this._popIndex = parseInt(this._size * 0.5);
this._shiftIndex = this._popIndex;
}
return res;
}
return undefined;
}
unshift(data) {
this.length++;
this._array[--this._shiftIndex] = data;
}
shift() {
if (this.length) {
this.length--;
var res = this._array[this._shiftIndex];
this._array[this._shiftIndex++] = null;
if (!this._array[this._shiftIndex]) {
this._popIndex = parseInt(this._size * 0.5);
this._shiftIndex = this._popIndex;
}
return res;
}
return undefined;
}
each(callback) {
for (var i = this._shiftIndex; i < this._popIndex; i++) {
callback(this._array[i]);
}
}
};
export { QueueArray };

View File

@ -1,106 +0,0 @@
/**
* @module og/Rectangle
*/
'use strict';
/**
* 2D Rectangle class.
* @class
* @param {number} [left] - Left coordinate. 0 - default.
* @param {number} [top] - Top coordinate. 0 - default.
* @param {number} [right] - Right coordinate. 0 - default.
* @param {number} [bottom] - Bottom coordinate. 0 - default.
*/
class Rectangle {
constructor(left, top, right, bottom) {
/**
* Left coordinate.
* @public
* @type {number}
*/
this.left = left || 0;
/**
* Right coordinate.
* @public
* @type {number}
*/
this.right = right || 0;
/**
* Top coordinate.
* @public
* @type {number}
*/
this.top = top || 0;
/**
* Top coordinate.
* @public
* @type {number}
*/
this.bottom = bottom || 0;
}
/**
* Clone rectangle object.
* @public
* @returns {og.Rectangle}
*/
clone() {
return new Rectangle(this.left, this.top, this.right, this.bottom);
}
/**
* Returns rectangle width.
* @public
* @type {number}
*/
getWidth() {
return Math.abs(this.right - this.left);
}
/**
* Returns rectangle height.
* @public
* @type {number}
*/
getHeight() {
return Math.abs(this.bottom - this.top);
}
/**
* Returns rectangle area.
* @public
* @type {number}
*/
getSquare() {
return this.getHeight() * this.getWidth();
}
/**
* Returns rectangle diagonal size.
* @public
* @type {number}
*/
getDiagonal() {
var w = this.getWidth(),
h = this.getHeight();
return Math.sqrt(h * h + w * w);
}
/**
* Returns true if rectangle fits their size in width and height.
* @public
* @param {number} width - Width.
* @param {number} height - Height.
* @type {boolean}
*/
fit(width, height) {
return (this.getWidth() == width && this.getHeight() == height);
}
};
export { Rectangle };

View File

@ -1,50 +0,0 @@
/**
* @module og/Stack
*/
'use strict';
class Node {
constructor() {
this.next = null;
this.prev = null;
this.data = null;
}
};
class Stack {
constructor(size = 256) {
this._current = new Node();
this._head = this._current;
for (var i = 0; i < size; i++) {
var n = new Node();
n.prev = this._current;
this._current.next = n;
this._current = n;
}
this._current = this._head;
}
current() {
return this._current;
}
push(data) {
this._current = this._current.next;
this._current.data = data;
};
pop(data) {
this._current = this._current.prev;
return this._current.next.data;
}
popPrev(data) {
this._current = this._current.prev;
return this._current.data;
}
};
export { Stack };

View File

@ -1,214 +0,0 @@
/**
* @module og/ajax
*/
'use strict';
/**
* Ajax parameters.
* @namespace og.ajax
*/
const ajax = {
/**
* Ajax ready state result.
* @enum
*/
ReadyState:
{
Uninitialized: 0,
Loading: 1,
Loaded: 2,
Interactive: 3,
Complete: 4
},
/**
* Ajax status code.
* @enum
*/
Status:
{
OK: 200,
Created: 201,
Accepted: 202,
NoContent: 204,
BadRequest: 400,
Forbidden: 403,
NotFound: 404,
Gone: 410,
ServerError: 500
},
/**
* Ajax query method.
* @enum
*/
Method: {
Get: "GET",
Post: "POST"
},
/**
* Ajax query type is asynchronous.
* @type {boolean}
*/
Asynchronous: true,
/**
* Ajax query type is synchronous.
* @type {boolean}
*/
Synchronous: false
};
/**
* Xhr object that returned by ajax query.
* @class
* @param {Object} xhr - Current ActiveXObject object.
*/
const Xhr = function (xhr) {
/**
* ActiveXObject object.
* @private
* @type {Object}
*/
var _xhr = xhr;
/**
* Aborts current ajax.
* @public
*/
this.abort = function () {
_xhr.aborted = true;
_xhr.abort();
};
};
const defaultParams = {
type: ajax.Method.Get,
async: ajax.Asynchronous,
data: null,
sender: null,
responseType: "text"
};
function createXMLHttp() {
var xhr = null;
if (typeof XMLHttpRequest !== undefined) {
xhr = new XMLHttpRequest;
return xhr;
} else if (window.ActiveXObject) {
var ieXMLHttpVersions = ['MSXML2.XMLHttp.5.0', 'MSXML2.XMLHttp.4.0', 'MSXML2.XMLHttp.3.0', 'MSXML2.XMLHttp', 'Microsoft.XMLHttp'];
for (var i = 0; i < ieXMLHttpVersions.length; i++) {
try {
xhr = new ActiveXObject(ieXMLHttpVersions[i]);
return xhr;
} catch (e) {
console.log('error: og.ajax.createXMLHttp creation filed.');
}
}
}
};
/**
* Send an ajax request.
* @function
* @param {string} url - Url path.
* @param {Object} [params] - Ajax parameters:
* @param {ajax.Method|string} [params.type] - 'POST' or 'GET' ajax method. 'GET' is default.
* @param {boolean} [params.async] - Asynchronous ajax flag. True is default.
* @param {Object} [params.data] - Qery data.
* @param {Object} [params.sender] - Sender object, that success callback binded with. ActiveXObject is default.
* @param {string} [params.responseType] - Responce data type. Culd be 'text', 'json', 'jsonp', 'html'. 'text' is default.
* @param {ajax.Xhr~successCallback} [params.success] - The callback that handles the success response.
* @param {ajax.Xhr~errorCallback} [params.error] - The callback that handles the failed response.
* @param {ajax.Xhr~abortCallback} [params.abort] - The callback that handles aborted requests.
* @returns {ajax.Xhr} - Returns object that could be aborted.
*/
ajax.request = function (url, params) {
params = params || {};
var p = {}, i;
for (i in defaultParams) {
p[i] = defaultParams[i];
}
for (i in params) {
p[i] = params[i];
}
p.data = params.data;
var xhr = createXMLHttp();
var customXhr = new Xhr(xhr);
var body = null, d;
if (p.type === ajax.Method.Post) {
if (p.data) {
body = "";
for (key in p.data) {
d = p.data[key];
body += key + "=" + encodeURIComponent(d instanceof Object ? JSON.stringify(d) : d) + "&";
}
body = body.slice(0, -1);
}
xhr.open(p.type, url, p.async);
xhr.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
} else if (p.data) {
var tail = "?";
for (key in p.data) {
d = p.data[key];
tail += key + "=" + encodeURIComponent(d instanceof Object ? JSON.stringify(d) : d) + "&";
}
tail = tail.slice(0, -1);
xhr.open(p.type, url + tail, p.async);
} else {
xhr.open(p.type, url, p.async);
}
if (p.async)
xhr.responseType = p.responseType;
xhr.overrideMimeType("text/plain");
xhr.onreadystatechange = function () {
if (xhr.readyState === ajax.ReadyState.Complete) {
if (xhr.status === ajax.Status.OK) {
if (params.success)
/**
* Success callback.
* @callback ajax.Xhr~successCallback
* @param {Object} Response data
*/
params.success.call(params.sender || customXhr, xhr.response);
} else if (xhr.aborted) {
/**
* Abort callback.
* @callback ajax.Xhr~abortCallback
* @param {Object} Response data
* @param {Object} Status object
*/
params.abort && params.abort.call(params.sender || customXhr, xhr.response, xhr.status);
} else {
/**
* Error callback.
* @callback ajax.Xhr~errorCallback
* @param {Object} Response data
* @param {Object} Status object
*/
params.error && params.error.call(params.sender || customXhr, xhr.response, xhr.status);
}
delete xhr['onreadystatechange'];
xhr.onreadystatechange = null;
xhr = null;
} else {
//still loading
}
};
xhr.send(body);
return customXhr;
};
export { ajax };

View File

@ -1,56 +0,0 @@
/**
* @module og/astro/astro
*/
'use strict';
import * as jd from './jd.js';
/**
* Angle between J2000 mean equator and the ecliptic plane.
* 23 deg 26' 21".448 (Seidelmann, _Explanatory Supplement to the
* Astronomical Almanac_ (1992), eqn 3.222-1.
* @const
* @type{Number}
*/
export const J2000_OBLIQUITY = 23.4392911;
/**
* IAU 1976 value
* @const
* @type{Number}
*/
export const AU_TO_METERS = 1.49597870e+11;
/**
* Terestrial and atomic time difference.
* @const
* @type{Number}
*/
export const TDT_TAI = 32.184;
/**
* Earth gravitational parameter product of gravitational constant G and the mass M of the Earth.
* @const
* @type{Number}
*/
export const EARTH_GRAVITATIONAL_PARAMETER = 3.98600435e14;
/**
* Sun gravitational parameter product of gravitational constant G and the mass M of the Sun.
* @const
* @type{Number}
*/
export const SUN_GRAVITATIONAL_PARAMETER = 1.32712440018e20;
/**
* Converts atomic time to barycentric dynamical time.
* @param {Number} tai - Atomic time.
* @returns {Number} - returns barycentric dynamical time.
*/
export function TAItoTDB(tai) {
tai += og.astro.TDT_TAI * jd.ONE_BY_SECONDS_PER_DAY;
var g = 6.239996 + 0.0172019696544 * (tai - jd.J2000);
return tai + 0.001658 * Math.sin(g + 1.671e-2 * Math.sin(g)) * jd.ONE_BY_SECONDS_PER_DAY;
};

View File

@ -1,111 +0,0 @@
/**
* @module og/astro/earth
*/
'use strict';
import * as jd from './jd.js';
import * as math from '../math.js';
import * as astro from './astro.js';
import { Quat } from '../math/Quat.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Returns Sun position in the geocentric coordinate system by the time.
* @param {Number} jDate - Julian date time.
* @returns {og.math.Vector3} - Sun geocentric coordinates.
*/
export function getSunPosition(jDate) {
//http://stjarnhimlen.se/comp/tutorial.html
// a Mean distance, or semi-major axis
// e Eccentricity
// T Time at perihelion
// q Perihelion distance = a * (1 - e)
// Q Aphelion distance = a * (1 + e)
// i Inclination, i.e. the "tilt" of the orbit relative to the
// ecliptic. The inclination varies from 0 to 180 degrees. If
// the inclination is larger than 90 degrees, the planet is in
// a retrogade orbit, i.e. it moves "backwards". The most
// well-known celestial body with retrogade motion is Comet Halley.
// N (usually written as "Capital Omega") Longitude of Ascending
// Node. This is the angle, along the ecliptic, from the Vernal
// Point to the Ascending Node, which is the intersection between
// the orbit and the ecliptic, where the planet moves from south
// of to north of the ecliptic, i.e. from negative to positive
// latitudes.
// w (usually written as "small Omega") The angle from the Ascending
// node to the Perihelion, along the orbit.
// P Orbital period = 365.256898326 * a**1.5/sqrt(1+m) days,
// where m = the mass of the planet in solar masses (0 for
// comets and asteroids). sqrt() is the square root function.
// n Daily motion = 360_deg / P degrees/day
// t Some epoch as a day count, e.g. Julian Day Number. The Time
// at Perihelion, T, should then be expressed as the same day count.
// t - T Time since Perihelion, usually in days
// M Mean Anomaly = n * (t - T) = (t - T) * 360_deg / P
// Mean Anomaly is 0 at perihelion and 180 degrees at aphelion
// L Mean Longitude = M + w + N
// E Eccentric anomaly, defined by Kepler's equation: M = E - e * sin(E)
// An auxiliary angle to compute the position in an elliptic orbit
// v True anomaly: the angle from perihelion to the planet, as seen
// from the Sun
// r Heliocentric distance: the planet's distance from the Sun.
// x,y,z Rectangular coordinates. Used e.g. when a heliocentric
// position (seen from the Sun) should be converted to a
// corresponding geocentric position (seen from the Earth).
var d = jDate - jd.J2000;
var w = 282.9404 + 4.70935E-5 * d; //longitude of perihelion
var a = 1.000000; //mean distance, a.u.
var e = 0.016709 - 1.151E-9 * d; //eccentricity
var M = math.rev(356.0470 + 0.9856002585 * d); //mean anomaly
var oblecl = astro.J2000_OBLIQUITY - 3.563E-7 * d; //obliquity of the ecliptic
var L = math.rev(w + M); //Sun's mean longitude
var E = M + math.DEGREES * e * Math.sin(M * math.RADIANS) * (1 + e * Math.cos(M * math.RADIANS)); //eccentric anomaly
//Sun rectangular coordiantes, where the X axis points towards the perihelion
var x = Math.cos(E * math.RADIANS) - e;
var y = Math.sin(E * math.RADIANS) * Math.sqrt(1 - e * e);
var r = Math.sqrt(x * x + y * y); // distance
var v = Math.atan2(y, x) * math.DEGREES; // true anomaly
var lon = math.rev(v + w); //longitude of the Sun
//the Sun's ecliptic rectangular coordinates
x = r * Math.cos(lon * math.RADIANS);
y = r * Math.sin(lon * math.RADIANS);
//We use oblecl, and rotate these coordinates
var xequat = x;
var yequat = y * Math.cos(oblecl * math.RADIANS);
var zequat = y * Math.sin(oblecl * math.RADIANS);
var theta = math.TWO_PI * (d * 24.0 / 23.9344694 - 259.853 / 360.0); // Siderial spin time
return Quat.yRotation(-theta).mulVec3(new Vec3(-yequat * astro.AU_TO_METERS,
zequat * astro.AU_TO_METERS, -xequat * astro.AU_TO_METERS));
//Convert to RA and Decl
//var RA = Math.atan2(yequat, xequat) * math.DEGREES;
//var Decl = Math.atan2(zequat, Math.sqrt(xequat * xequat + yequat * yequat)) * math.DEGREES;
};

View File

@ -1,513 +0,0 @@
/**
* @module og/astro/jd
*/
'use strict';
import { binarySearch } from '../utils/shared.js';
/**
* Seconds in millisecond.
* @const
* @default
*/
export const SECONDS_PER_MILLISECOND = 0.001;
/**
* Milliseconds in second.
* @const
* @default
*/
export const MILLISECONDS_PER_SECOND = 1000.0;
/**
* Seconds in minute.
* @const
* @default
*/
export const SECONDS_PER_MINUTE = 60.0;
/**
* One by seconds in minute.
* @const
* @default
*/
export const ONE_BY_SECONDS_PER_MINUTE = 1.0 / SECONDS_PER_MINUTE;
/**
* Minutes in hour.
* @const
* @default
*/
export const MINUTES_PER_HOUR = 60.0;
/**
* Hours in day.
* @const
* @default
*/
export const HOURS_PER_DAY = 24.0;
/**
* One by hours in day.
* @const
* @default
*/
export const ONE_BY_HOURS_PER_DAY = 1.0 / HOURS_PER_DAY;
/**
* Seconds in hour.
* @const
* @default
*/
export const SECONDS_PER_HOUR = 3600.0;
/**
* One by seconds in hour.
* @const
* @default
*/
export const ONE_BY_SECONDS_PER_HOUR = 1.0 / SECONDS_PER_HOUR;
/**
* Seconds in 12 hours.
* @const
* @default
*/
export const SECONDS_PER_12_HOURS = 12.0 * SECONDS_PER_HOUR;
/**
* Minutes in day.
* @const
* @default
*/
export const MINUTES_PER_DAY = 1440.0;
/**
* One by minutes in day.
* @const
* @default
*/
export const ONE_BY_MINUTES_PER_DAY = 1.0 / MINUTES_PER_DAY;
/**
* Seconds in day.
* @const
* @default
*/
export const SECONDS_PER_DAY = 86400.0;
/**
* Milliseconds in day.
* @const
* @default
*/
export const MILLISECONDS_PER_DAY = 86400000.0;
/**
* One by milliseconds in day.
* @const
* @default
*/
export const ONE_BY_MILLISECONDS_PER_DAY = 1.0 / MILLISECONDS_PER_DAY;
/**
* One by seconds in day.
* @const
* @default
*/
export const ONE_BY_SECONDS_PER_DAY = 1.0 / SECONDS_PER_DAY;
/**
* Days in julian century.
* @const
* @default
*/
export const DAYS_PER_JULIAN_CENTURY = 36525.0;
/**
* Days in julian year.
* @const
* @default
*/
export const DAYS_PER_JULIAN_YEAR = 365.25;
/**
* Seconds in picosecond.
* @const
* @default
*/
export const PICOSECOND = 0.000000001;
/**
* Modified julian date difference.
* @const
* @default
*/
export const MODIFIED_JULIAN_DATE_DIFFERENCE = 2400000.5;
/**
* Julian date of 2000 year. Epoch.
* @const
* @default
*/
export const J2000 = 2451545.0;
/**
* Returns julian days from Epoch.
* @param {number} jd - Julian date.
* @returns {number} Days from epoch
*/
export function T(jd) {
return (jd - J2000) / DAYS_PER_JULIAN_CENTURY;
};
/**
* Gets the date's julian day.
* @param {number} year - Year.
* @param {number} month - Month.
* @param {number} day - Day.
* @returns {Number} Day number
*/
export function getDayNumber(year, month, day) {
var a = ((month - 14) / 12) | 0;
var b = year + 4800 + a;
return (((1461 * b) / 4) | 0) + (((367 * (month - 2 - 12 * a)) / 12) | 0) -
(((3 * (((b + 100) / 100) | 0)) / 4) | 0) + day - 32075;
};
/**
* Converts javascript date to the universal(UTC) julian date.
* @param {Date} date - Date.
* @returns {number} UTC julian date
*/
export function DateToUTC(date) {
var dayNumber = getDayNumber(date.getUTCFullYear(), date.getUTCMonth() + 1, date.getUTCDate());
var hour = date.getUTCHours() - 12;
if (hour < 0) {
hour += 24;
}
var secondsOfDay =
date.getUTCSeconds() + hour * SECONDS_PER_HOUR +
date.getUTCMinutes() * SECONDS_PER_MINUTE +
date.getUTCMilliseconds() * SECONDS_PER_MILLISECOND;
if (secondsOfDay >= SECONDS_PER_12_HOURS) {
dayNumber--;
}
var extraDays = secondsOfDay * ONE_BY_SECONDS_PER_DAY | 0;
dayNumber += extraDays;
secondsOfDay -= SECONDS_PER_DAY * extraDays;
if (secondsOfDay < 0) {
dayNumber--;
secondsOfDay += SECONDS_PER_DAY;
}
return dayNumber + secondsOfDay * ONE_BY_SECONDS_PER_DAY;
};
/**
* Converts javascript date to the atomic(TAI) julian date.
* @param {Date} date - Date.
* @returns {number} TAI julian date
*/
export function DateToTAI(date) {
return UTCtoTAI(DateToUTC(date));
};
/**
* Converts coordinated universal(UTC) julian date to atomic(TAI) julian date.
* @param {number} jd - UTC julian date.
* @returns {number} TAI julian date
*/
export function UTCtoTAI(jd) {
var leapSeconds = leapSecondsTable;
var index = binarySearch(leapSeconds, jd, function (a, b) {
return a - b.jd;
});
if (index < 0) {
index = ~index;
}
if (index >= leapSeconds.length) {
index = leapSeconds.length - 1;
}
var offset = leapSeconds[index].leapSeconds;
if (index !== 0) {
if ((leapSeconds[index].jd - jd) * SECONDS_PER_DAY > offset) {
offset = leapSeconds[index - 1].leapSeconds;
}
}
return jd + offset * ONE_BY_SECONDS_PER_DAY;
};
/**
* Converts atomic julian date(TAI) to the coordinated universal(UTC) julian date.
* @param {number} tai - TAI julian date.
* @returns {number} UTC julian date
*/
export function TAItoUTC(tai) {
var leapSeconds = leapSecondsTable;
var index = binarySearch(leapSeconds, tai, function (a, b) {
return a - b.jd;
});
if (index < 0) {
index = ~index;
}
if (index >= leapSeconds.length) {
return tai - leapSeconds[index - 1].leapSeconds * ONE_BY_SECONDS_PER_DAY;
}
if (index === 0) {
return tai - leapSeconds[0].leapSeconds * ONE_BY_SECONDS_PER_DAY;
}
var diff = (leapSeconds[index].jd - tai) * SECONDS_PER_DAY;
if (diff === 0) {
return tai - leapSeconds[index].leapSeconds * ONE_BY_SECONDS_PER_DAY;
}
if (diff <= 1.0) {
return null;
}
return tai - leapSeconds[index - 1].leapSeconds * ONE_BY_SECONDS_PER_DAY;
};
/**
* Converts UTC julian date to the javascript date object.
* @param {number} utc - UTC julian date.
* @returns {Date} JavaScript Date object
*/
export function UTCtoDate(utc) {
var julianDayNumber = utc | 0;
var secondsOfDay = (utc - julianDayNumber) * SECONDS_PER_DAY;
if (secondsOfDay >= SECONDS_PER_12_HOURS) {
julianDayNumber++;
}
var L = (julianDayNumber + 68569) | 0;
var N = (4 * L / 146097) | 0;
L = (L - (((146097 * N + 3) / 4) | 0)) | 0;
var I = ((4000 * (L + 1)) / 1461001) | 0;
L = (L - (((1461 * I) / 4) | 0) + 31) | 0;
var J = ((80 * L) / 2447) | 0;
var day = (L - (((2447 * J) / 80) | 0)) | 0;
L = (J / 11) | 0;
var month = (J + 2 - 12 * L) | 0;
var year = (100 * (N - 49) + I + L) | 0;
var hour = secondsOfDay * ONE_BY_SECONDS_PER_HOUR | 0;
var remainingSeconds = secondsOfDay - hour * SECONDS_PER_HOUR;
var minute = remainingSeconds * ONE_BY_SECONDS_PER_MINUTE | 0;
remainingSeconds = remainingSeconds - minute * SECONDS_PER_MINUTE;
var second = remainingSeconds | 0;
var millisecond = (remainingSeconds - second) * MILLISECONDS_PER_SECOND | 0;
hour += 12;
if (hour > 23) {
hour -= 24;
}
return new Date(Date.UTC(year, month - 1, day, hour, minute, second, millisecond));
};
/**
* Converts TAI julian date to the javascript date object.
* @param {number} tai - TAI julian date.
* @returns {Date} JavaScript Date object
*/
export function TAItoDate(tai) {
var utc = TAItoUTC(tai);
if (!utc) {
utc = TAItoUTC(addSeconds(tai, -1));
og.console.logWrn("TAItoDate:336 - can't conv utc.");
}
return UTCtoDate(utc);
};
/**
* Adds milliseconds to the julian date.
* @param {number} jd - Julian date.
* @param {number} milliseconds - Milliseconds to add.
* @returns {number} Julian date
*/
export function addMilliseconds(jd, milliseconds) {
return jd + milliseconds * ONE_BY_MILLISECONDS_PER_DAY;
};
/**
* Adds seconds to the julian date.
* @param {number} jd - Julian date.
* @param {number} seconds - Seconds to add.
* @returns {number} Julian date
*/
export function addSeconds(jd, seconds) {
return jd + seconds * ONE_BY_SECONDS_PER_DAY;
};
/**
* Adds hours to the julian date.
* @param {number} jd - Julian date.
* @param {number} hours - Hours to add.
* @returns {number} Julian date
*/
export function addHours(jd, hours) {
return jd + hours * ONE_BY_HOURS_PER_DAY;
};
/**
* Adds minutes to the julian date.
* @param {number} jd - Julian date.
* @param {number} minutes - Minutes to add.
* @returns {number} Julian date
*/
export function addMinutes(jd, minutes) {
return jd + minutes * MINUTES_PER_DAY;
};
/**
* Adds days to the julian date.
* @param {number} jd - Julian date.
* @param {number} days - Days to add.
* @returns {number} Julian date
*/
export function addDays(jd, days) {
return jd + days;
};
/**
* Gets milliseconds of a julian date.
* @param {number} js - julian date.
* @returns {number} Milliseconds
*/
export function getMilliseconds(jd) {
var s = jd - (jd | 0);
s *= SECONDS_PER_DAY;
return (s - (s | 0)) * MILLISECONDS_PER_SECOND | 0;
};
/**
* Gets seconds of a julian date.
* @param {number} js - julian date.
* @returns {number} Seconds
*/
export function getSeconds(jd) {
var s = jd - (jd | 0);
return s * SECONDS_PER_DAY;
};
/**
* Gets hours of a julian date.
* @param {number} js - julian date.
* @returns {number} Hours
*/
export function getHours(jd) {
var julianDayNumber = jd | 0;
var secondsOfDay = (jd - julianDayNumber) * SECONDS_PER_DAY;
var hour = secondsOfDay * ONE_BY_SECONDS_PER_HOUR | 0;
var remainingSeconds = secondsOfDay - hour * SECONDS_PER_HOUR;
var minute = remainingSeconds * ONE_BY_SECONDS_PER_MINUTE | 0;
remainingSeconds = remainingSeconds - minute * SECONDS_PER_MINUTE;
var second = remainingSeconds | 0;
var millisecond = (remainingSeconds - second) * MILLISECONDS_PER_SECOND | 0;
hour += 12 + minute / 60 + second / 3600 + millisecond / 1000;
if (hour > 23) {
hour -= 24;
}
return hour;
};
/**
* Gets minutes of a julian date.
* @param {number} js - julian date.
* @returns {number} Minutes
*/
export function getMinutes(jd) {
var s = jd - (jd | 0);
return s * MINUTES_PER_DAY | 0;
};
/**
* Gets days of a julian date.
* @param {number} js - julian date.
* @returns {number} Days
*/
export function getDays(jd) {
return jd | 0;
};
/**
* Returns days in seconds.
* @param {number} s - Seconds.
* @returns {number} Days
*/
export function secondsToDays(s) {
return s * ONE_BY_SECONDS_PER_DAY;
};
/**
* Returns seconds in days.
* @param {number} d - Days.
* @returns {number} Seconds
*/
export function daysToSeconds(d) {
return d * SECONDS_PER_DAY;
};
function __ls(jd, leapSeconds) {
return {
"jd": jd,
"leapSeconds": leapSeconds
};
};
const leapSecondsTable = [
__ls(2441317.5, 10.0), // 1972-01-01T00:00:00.000Z
__ls(2441499.5, 11.0), // 1972-07-01T00:00:00.000Z
__ls(2441683.5, 12.0), // 1973-01-01T00:00:00.000Z
__ls(2442048.5, 13.0), // 1974-01-01T00:00:00.000Z
__ls(2442413.5, 14.0), // 1975-01-01T00:00:00.000Z
__ls(2442778.5, 15.0), // 1976-01-01T00:00:00.000Z
__ls(2443144.5, 16.0), // 1977-01-01T00:00:00.000Z
__ls(2443509.5, 17.0), // 1978-01-01T00:00:00.000Z
__ls(2443874.5, 18.0), // 1979-01-01T00:00:00.000Z
__ls(2444239.5, 19.0), // 1980-01-01T00:00:00.000Z
__ls(2444786.5, 20.0), // 1981-07-01T00:00:00.000Z
__ls(2445151.5, 21.0), // 1982-07-01T00:00:00.000Z
__ls(2445516.5, 22.0), // 1983-01-01T00:00:00.000Z
__ls(2446247.5, 23.0), // 1985-07-01T00:00:00.000Z
__ls(2447161.5, 24.0), // 1988-01-01T00:00:00.000Z
__ls(2447892.5, 25.0), // 1990-01-01T00:00:00.000Z
__ls(2448257.5, 26.0), // 1991-01-01T00:00:00.000Z
__ls(2448804.5, 27.0), // 1992-07-01T00:00:00.000Z
__ls(2449169.5, 28.0), // 1993-07-01T00:00:00.000Z
__ls(2449534.5, 29.0), // 1994-07-01T00:00:00.000Z
__ls(2450083.5, 30.0), // 1996-01-01T00:00:00.000Z
__ls(2450630.5, 31.0), // 1997-07-01T00:00:00.000Z
__ls(2451179.5, 32.0), // 1999-01-01T00:00:00.000Z
__ls(2453736.5, 33.0), // 2006-01-01T00:00:00.000Z
__ls(2454832.5, 34.0), // 2009-01-01T00:00:00.000Z
__ls(2456109.5, 35.0), // 2012-07-01T00:00:00.000Z
__ls(2457204.5, 36.0) // 2015-07-01T00:00:00.000Z
];
export const J2000TAI = UTCtoTAI(J2000);

View File

@ -1,121 +0,0 @@
/**
* @module og/astro/orbit
*/
'use strict';
import * as math from '../math.js');
import { Mat3 } from '../math/Mat3.js';
export function getEccentricAnomaly(M, ecc) {
if (ecc == 0.0) {
// Circular orbit
return M;
} else if (ecc < 0.2) {
// Low eccentricity, so use the standard iteration technique
return math.solve_iteration_fixed(solveKeplerFunc1(ecc, M), M, 5);
} else if (ecc < 0.9) {
// Higher eccentricity elliptical orbit; use a more complex but
// much faster converging iteration.
return math.solve_iteration_fixed(solveKeplerFunc2(ecc, M), M, 6);
} else if (ecc < 1.0) {
// Extremely stable Laguerre-Conway method for solving Kepler's
// equation. Only use this for high-eccentricity orbits, as it
// requires more calcuation.
var E = M + 0.85 * ecc * sign(sin(M));
return math.solve_iteration_fixed(solveKeplerLaguerreConway(ecc, M), E, 8);
} else if (ecc == 1.0) {
//TODO: Parabolic orbit
return M;
} else {
// Laguerre-Conway method for hyperbolic (ecc > 1) orbits.
var E = log(2 * M / ecc + 1.85);
return math.solve_iteration_fixed(solveKeplerLaguerreConwayHyp(ecc, M), E, 30);
}
};
// Standard iteration for solving Kepler's Equation
function solveKeplerFunc1(ecc, M) {
return function (x) {
return M + ecc * Math.sin(x);
}
};
// Faster converging iteration for Kepler's Equation; more efficient
// than above for orbits with eccentricities greater than 0.3. This
// is from Jean Meeus's _Astronomical Algorithms_ (2nd ed), p. 199
function solveKeplerFunc2(ecc, M) {
return function (x) {
return x + (M + ecc * Math.sin(x) - x) / (1 - ecc * Math.cos(x));
}
};
function solveKeplerLaguerreConway(ecc, M) {
return function (x) {
var s = ecc * Math.sin(x);
var c = ecc * Math.cos(x);
var f = x - s - M;
var f1 = 1 - c;
var f2 = s;
x += -5 * f / (f1 + Math.sign(f1) * Math.sqrt(abs(16 * f1 * f1 - 20 * f * f2)));
return x;
}
};
function solveKeplerLaguerreConwayHyp(ecc, M) {
return function (x) {
var s = ecc * Math.sinh(x);
var c = ecc * Math.cosh(x);
var f = s - x - M;
var f1 = c - 1;
var f2 = s;
x += -5 * f / (f1 + Math.sign(f1) * Math.sqrt(Math.abs(16 * f1 * f1 - 20 * f * f2)));
return x;
}
};
export function getEllipticalEccentricAnomaly(meanAnomaly, eccentricity) {
var tol = 0.00000001745;
var iterations = 20;
var e = meanAnomaly - 2.0 * Math.PI * (meanAnomaly / (2.0 * Math.PI) | 0);
var err = 1;
while (Math.abs(err) > tol && iterations > 0) {
err = e - eccentricity * Math.sin(e) - meanAnomaly;
var delta = err / (1 - eccentricity * Math.cos(e));
e -= delta;
iterations--;
}
return e;
};
export function getTrueAnomaly(eccentricAnomaly, eccentricity) {
var revs = Math.floor(eccentricAnomaly / math.TWO_PI);
eccentricAnomaly -= revs * math.TWO_PI;
var trueAnomaly = Math.atan2(Math.sin(eccentricAnomaly) * Math.sqrt(1 - eccentricity * eccentricity),
Math.cos(eccentricAnomaly) - eccentricity);
trueAnomaly = math.zeroTwoPI(trueAnomaly);
if (eccentricAnomaly < 0) {
trueAnomaly -= math.TWO_PI;
}
return trueAnomaly + revs * math.TWO_PI;
};
export function getPerifocalToCartesianMatrix(argumentOfPeriapsis, inclination, rightAscension) {
var res = new Mat3();
var cosap = Math.cos(argumentOfPeriapsis),
sinap = Math.sin(argumentOfPeriapsis),
cosi = Math.cos(inclination),
sini = Math.sin(inclination),
cosraan = Math.cos(rightAscension),
sinraan = Math.sin(rightAscension);
res._m[0] = cosraan * cosap - sinraan * sinap * cosi;
res._m[1] = sinraan * cosap + cosraan * sinap * cosi;
res._m[2] = sinap * sini;
res._m[3] = -cosraan * sinap - sinraan * cosap * cosi;
res._m[4] = -sinraan * sinap + cosraan * cosap * cosi;
res._m[5] = cosap * sini;
res._m[6] = sinraan * sini;
res._m[7] = -cosraan * sini;
res._m[8] = cosi;
return res;
};

View File

@ -1,31 +0,0 @@
/**
* @module og/astro/rotation
*/
'use strict';
export function getRotationMatrix(rightAscension, declination) {
xAxis.x = Math.cos(rightAscension + og.math.PI_TWO);
xAxis.y = Math.sin(rightAscension + og.math.PI_TWO);
xAxis.z = 0.0;
var cosDec = Math.cos(declination);
zAxis.x = cosDec * Math.cos(rightAscension);
zAxis.y = cosDec * Math.sin(rightAscension);
zAxis.z = Math.sin(declination);
var yAxis = zAxis.cross(xAxis);
res._m[0] = xAxis.x;
res._m[1] = yAxis.x;
res._m[2] = zAxis.x;
res._m[3] = xAxis.y;
res._m[4] = yAxis.y;
res._m[5] = zAxis.y;
res._m[6] = xAxis.z;
res._m[7] = yAxis.z;
res._m[8] = zAxis.z;
return result;
};

View File

@ -1,52 +0,0 @@
/**
* @module og/bv/Box
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
/**
* Bounding box class.
* @class
*/
class Box {
constructor() {
/**
* Vertices array.
* @public
* @type{Array.<og.math.Vector3>}
*/
this.vertices = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
}
/**
* Sets bounding box coordinates by the bounds array.
* @param {Array.<number>} bounds - Bounds is an array where [minX, maxX, minY, maxY, minZ, maxZ]
*/
setFromBounds(bounds) {
var xmin = bounds[0], xmax = bounds[1],
ymin = bounds[2], ymax = bounds[3],
zmin = bounds[4], zmax = bounds[5];
this.vertices[0].set(xmin, ymin, zmin);
this.vertices[1].set(xmax, ymin, zmin);
this.vertices[2].set(xmax, ymin, zmax);
this.vertices[3].set(xmin, ymin, zmax);
this.vertices[4].set(xmin, ymax, zmin);
this.vertices[5].set(xmax, ymax, zmin);
this.vertices[6].set(xmax, ymax, zmax);
this.vertices[7].set(xmin, ymax, zmax);
}
/**
* Sets bounding box coordiantes by ellipsoid geodetic extend.
* @param {og.Ellipsoid} ellipsoid - Ellipsoid.
* @param {og.Extent} extent - Geodetic extent.
*/
setFromExtent(ellipsoid, extent) {
this.setFromBounds(extent.getCartesianBounds(ellipsoid));
}
};
export { Box };

View File

@ -1,52 +0,0 @@
/**
* @module og/bv/Sphere
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
/**
* Bounding sphere class.
* @class
* @param {Number} [radius] - Bounding sphere radius.
* @param {og.math.Vector3} [center] - Bounding sphere coordiantes.
*/
class Sphere {
constructor(radius, center) {
/**
* Sphere radius.
* @public
* @type {Number}
*/
this.radius = radius || 0;
/**
* Sphere coordiantes.
* @public
* @type {og.math.Vector3}
*/
this.center = center ? center.clone() : new Vec3();
}
/**
* Sets bounding sphere coordinates by the bounds array.
* @param {Array.<number>} bounds - Bounds is an array where [minX, maxX, minY, maxY, minZ, maxZ]
*/
setFromBounds(bounds) {
this.center.set(bounds[0] + (bounds[1] - bounds[0]) / 2, bounds[2] + (bounds[3] - bounds[2]) / 2, bounds[4] + (bounds[5] - bounds[4]) / 2);
this.radius = this.center.distance(new Vec3(bounds[0], bounds[2], bounds[4]));
}
/**
* Sets bounding sphere coordiantes by ellipsoid geodetic extend.
* @param {og.Ellipsoid} ellipsoid - Ellipsoid.
* @param {og.Extent} extent - Geodetic extent.
*/
setFromExtent(ellipsoid, extent) {
this.setFromBounds(extent.getCartesianBounds(ellipsoid));
}
};
export { Sphere };

View File

@ -1,52 +0,0 @@
/**
* @module og/bv/Box
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
/**
* Bounding box class.
* @class
*/
class Box {
constructor() {
/**
* Vertices array.
* @public
* @type{Array.<og.math.Vector3>}
*/
this.vertices = [new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3(), new Vec3()];
}
/**
* Sets bounding box coordinates by the bounds array.
* @param {Array.<number>} bounds - Bounds is an array where [minX, maxX, minY, maxY, minZ, maxZ]
*/
setFromBounds(bounds) {
var xmin = bounds[0], xmax = bounds[1],
ymin = bounds[2], ymax = bounds[3],
zmin = bounds[4], zmax = bounds[5];
this.vertices[0].set(xmin, ymin, zmin);
this.vertices[1].set(xmax, ymin, zmin);
this.vertices[2].set(xmax, ymin, zmax);
this.vertices[3].set(xmin, ymin, zmax);
this.vertices[4].set(xmin, ymax, zmin);
this.vertices[5].set(xmax, ymax, zmin);
this.vertices[6].set(xmax, ymax, zmax);
this.vertices[7].set(xmin, ymax, zmax);
}
/**
* Sets bounding box coordiantes by ellipsoid geodetic extend.
* @param {og.Ellipsoid} ellipsoid - Ellipsoid.
* @param {og.Extent} extent - Geodetic extent.
*/
setFromExtent(ellipsoid, extent) {
this.setFromBounds(extent.getCartesianBounds(ellipsoid));
}
};
export { Box };

View File

@ -1,52 +0,0 @@
/**
* @module og/bv/Sphere
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
/**
* Bounding sphere class.
* @class
* @param {Number} [radius] - Bounding sphere radius.
* @param {og.math.Vector3} [center] - Bounding sphere coordiantes.
*/
class Sphere {
constructor(radius, center) {
/**
* Sphere radius.
* @public
* @type {Number}
*/
this.radius = radius || 0;
/**
* Sphere coordiantes.
* @public
* @type {og.math.Vector3}
*/
this.center = center ? center.clone() : new Vec3();
}
/**
* Sets bounding sphere coordinates by the bounds array.
* @param {Array.<number>} bounds - Bounds is an array where [minX, maxX, minY, maxY, minZ, maxZ]
*/
setFromBounds(bounds) {
this.center.set(bounds[0] + (bounds[1] - bounds[0]) / 2, bounds[2] + (bounds[3] - bounds[2]) / 2, bounds[4] + (bounds[5] - bounds[4]) / 2);
this.radius = this.center.distance(new Vec3(bounds[0], bounds[2], bounds[4]));
}
/**
* Sets bounding sphere coordiantes by ellipsoid geodetic extend.
* @param {og.Ellipsoid} ellipsoid - Ellipsoid.
* @param {og.Extent} extent - Geodetic extent.
*/
setFromExtent(ellipsoid, extent) {
this.setFromBounds(extent.getCartesianBounds(ellipsoid));
}
};
export { Sphere };

View File

@ -1,649 +0,0 @@
/**
* @module og/camera/Camera
*/
'use strict';
import * as math from '../math.js';
import { Events } from '../Events.js';
import { Frustum } from '../Frustum.js';
import { Vec2 } from '../math/Vec2.js';
import { Vec3 } from '../math/Vec3.js';
import { Vec4 } from '../math/Vec4.js';
import { Mat3 } from '../math/Mat3.js';
import { Mat4 } from '../math/Mat4.js';
/**
* Camera class.
* @class
* @param {og.Renderer} [renderer] - Renderer uses the camera instance.
* @param {Object} [options] - Camera options:
* @param {Object} [options.name] - Camera name.
* @param {number} [options.viewAngle=30] - Camera angle of view. Default is 30.0
* @param {number} [options.near=1] - Camera near plane distance. Default is 1.0
* @param {number} [options.far=og.math.MAX] - Camera far plane distance. Deafult is og.math.MAX
* @param {og.math.Vector3} [options.eye=[0,0,0]] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look=[0,0,0]] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up=[0,1,0]] - Camera eye position. Default (0,1,0)
*
* @fires og.Camera#viewchange
*/
class Camera {
constructor(renderer, options) {
/**
* Assigned renderer.
* @public
* @type {og.Renderer}
*/
this.renderer = null;
/**
* Camera events handler.
* @public
* @type {og.Events}
*/
this.events = new Events(EVENT_NAMES);
/**
* Camera position.
* @public
* @type {og.math.Vector3}
*/
this.eye = new Vec3();
/**
* Camera frustum.
* @public
* @type {og.Frustum}
*/
this.frustum = new Frustum();
/**
* Aspect ratio.
* @protected
* @type {Number}
*/
this._aspect = options.aspect || 0;
/**
* Camera near distance.
* @protected
* @type {Number}
*/
this._nearDist = 0;
/**
* Camera far distance.
* @protected
* @type {Number}
*/
this._farDist = 0;
/**
* Camera view angle in degrees.
* @protected
* @type {Number}
*/
this._viewAngle = 0;
/**
* Camera normal matrix.
* @protected
* @type {og.math.Matrix3}
*/
this._normalMatrix = new Mat3();
/**
* Camera projection matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionMatrix = new Mat4();
/**
* Camera view matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._viewMatrix = new Mat4();
/**
* Product of projection and view matrices.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionViewMatrix = new Mat4();
/**
* Inverse projectionView Matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._inverseProjectionViewMatrix = new Mat4();
/**
* Camera projection matrix for small near and far distances.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionMatrixPrecise = new Mat4();
/**
* Camera right vector.
* @protected
* @type {og.math.Vector3}
*/
this._u = new Vec3(0, 1, 0); //up x n
/**
* Camera up vector.
* @protected
* @type {og.math.Vector3}
*/
this._v = new Vec3(1, 0, 0); //n x u - UP
this.slope = 0;
/**
* Camera forward vector.
* @protected
* @type {og.math.Vector3}
*/
this._n = new Vec3(0, 0, 1); //eye - look - FORWARD
this._pu = this._u;
this._pv = this._v;
this._pn = this._n;
this._peye = this.eye;
this._moved = false;
this._tanViewAngle_hrad = 0;
this._tanViewAngle_hradOneByHeight = 0;
this.renderer = renderer;
renderer && this._initialize(options);
}
/**
* Updates model view matrix.
* @protected
*/
_setViewMatrix() {
var u = this._u,
v = this._v,
n = this._n,
eye = this.eye;
this._viewMatrix.set([u.x, v.x, n.x, 0,
u.y, v.y, n.y, 0,
u.z, v.z, n.z, 0,
-eye.dot(u), -eye.dot(v), -eye.dot(n), 1.0]);
}
checkMoveEnd() {
var u = this._u,
v = this._v,
n = this._n,
eye = this.eye;
if (this.events.moveend.handlers.length) {
if (this._peye.equal(eye) &&
this._pu.equal(u) &&
this._pv.equal(v) &&
this._pn.equal(n)) {
if (this._moved) {
this.events.dispatch(this.events.moveend, this);
}
this._moved = false;
} else {
this._moved = true;
}
}
this._pu = u;
this._pv = v;
this._pn = n;
this._peye = eye;
}
/**
* Camera initialization.
* @public
* @param {og.Renderer} renderer - OpenGlobus renderer object.
* @param {Object} [options] - Camera options:
* @param {number} [options.viewAngle] - Camera angle of view. Default is 30.0
* @param {number} [options.near] - Camera near plane distance. Default is 1.0
* @param {number} [options.far] - Camera far plane distance. Deafult is og.math.MAX
* @param {og.math.Vector3} [options.eye] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up] - Camera eye position. Default (0,1,0)
*/
_initialize(options) {
this.setProjectionMatrix(
options.viewAngle || defaultOptions.viewAngle,
this._aspect || this.renderer.handler.getClientAspect(),
options.near || defaultOptions.near,
options.far || defaultOptions.far);
this.set(
options.eye || defaultOptions.eye.clone(),
options.look || defaultOptions.look.clone(),
options.up || defaultOptions.up.clone());
}
getUp() {
return this._v;
}
getDown() {
return this._v.negateTo();
}
getRight() {
return this._u;
}
getLeft() {
return this._u.negateTo();
}
getForward() {
return this._n;
}
getBackward() {
return this._n.negateTo();
}
/**
* Clone camera instance to another one.
* @public
* @virtual
* @returns {og.Camera} - Cloned camera instance.
*/
clone() {
var newcam = new Camera();
newcam.eye.copy(cam.eye);
newcam._u.copy(cam._u);
newcam._v.copy(cam._v);
newcam._n.copy(cam._n);
newcam.renderer = cam.renderer;
newcam._projectionMatrix.copy(cam._projectionMatrix);
newcam._viewMatrix.copy(cam._viewMatrix);
newcam._projectionViewMatrix.copy(cam._projectionViewMatrix);
newcam._inverseProjectionViewMatrix.copy(cam._inverseProjectionViewMatrix);
newcam.frustum.setFrustum(newcam._projectionViewMatrix);
return newcam;
}
/**
* Updates camera view space.
* @public
* @virtual
*/
update() {
this._setViewMatrix();
this._projectionViewMatrix = this._projectionMatrix.mul(this._viewMatrix);
this.frustum.setFrustum(this._projectionViewMatrix._m);
this._inverseProjectionViewMatrix = this._projectionViewMatrix.inverseTo();
this._normalMatrix = this._viewMatrix.toMatrix3();//this._viewMatrix.toInverseMatrix3().transposeTo();
this.events.dispatch(this.events.viewchange, this);
}
/**
* Refresh camera matrices.
* @public
*/
refresh() {
this.setProjectionMatrix(this._viewAngle, this._aspect, this._nearDist, this._farDist);
this.update();
}
/**
* Sets aspect ratio.
* @public
* @param {Number} aspect - Camera aspect ratio.
*/
setAspectRatio(aspect) {
this._aspect = aspect;
this.refresh();
}
/**
* Returns aspect ratio.
* @public
* @returns {number} - Aspect ratio.
*/
getAspectRatio() {
return this._aspect;
}
/**
* Sets far camera distance.
* @public
* @param {number} distance - Far distance.
*/
setFar(distance) {
this._farDist = distance;
this.refresh();
}
/**
* Gets far distance.
* @public
* @returns {number} - Far plane distance.
*/
getFar() {
return this._farDist;
}
/**
* Sets camera's near distance.
* @public
* @param {number} distance - Near distance.
*/
setNear(distance) {
this._nearDist = distance;
this.refresh();
}
/**
* Gets near distance.
* @public
* @returns {number} - Near plane distance.
*/
getNear() {
return this._nearDist;
}
/**
* Sets up camera projection matrix.
* @public
* @param {nnumber} angle - Camera's view angle.
* @param {number} aspect - Screen aspect ration.
* @param {number} near - Near camera distance.
* @param {number} far - Far camera distance.
*/
setProjectionMatrix(angle, aspect, near, far) {
this._viewAngle = angle;
this._aspect = aspect;
this._nearDist = near;
this._farDist = far;
this._tanViewAngle_hrad = Math.tan(angle * math.RADIANS_HALF);
this._tanViewAngle_hradOneByHeight = this._tanViewAngle_hrad * this.renderer.handler._oneByHeight;
var c = this.renderer.handler.canvas;
this._projSizeConst = Math.min(c.clientWidth, c.clientHeight) / (this._viewAngle * math.RADIANS);
this._projectionMatrix.setPerspective(angle, aspect, near, far);
this._projectionMatrixPrecise.setPerspective(angle, aspect, 0.1, 10);
}
/**
* Sets camera view angle in degrees.
* @public
* @param {number} angle - View angle.
*/
setViewAngle(angle) {
this._viewAngle = angle;
this.refresh();
}
/**
* Sets camera to eye position.
* @public
* @param {og.math.Vector3} eye - Camera position.
* @param {og.math.Vector3} look - Look point.
* @param {og.math.Vector3} up - Camera up vector.
* @returns {og.Camera} - This camera.
*/
set(eye, look, up) {
this.eye.x = eye.x;
this.eye.y = eye.y;
this.eye.z = eye.z;
look = look || this._n;
up = up || this._v;
this._n.x = eye.x - look.x;
this._n.y = eye.y - look.y;
this._n.z = eye.z - look.z;
this._u.copy(up.cross(this._n));
this._n.normalize();
this._u.normalize();
this._v.copy(this._n.cross(this._u));
return this;
}
/**
* Sets camera look point.
* @public
* @param {og.math.Vector3} look - Look point.
* @param {og.math.Vector3} [up] - Camera up vector otherwise camera current up vector(this._v)
*/
look(look, up) {
this._n.set(this.eye.x - look.x, this.eye.y - look.y, this.eye.z - look.z);
this._u.copy((up || this._v).cross(this._n));
this._n.normalize();
this._u.normalize();
this._v.copy(this._n.cross(this._u));
}
/**
* Slides camera to vector d - (du, dv, dn).
* @public
* @param {number} du - delta X.
* @param {number} dv - delta Y.
* @param {number} dn - delta Z.
*/
slide(du, dv, dn) {
this.eye.x += du * this._u.x + dv * this._v.x + dn * this._n.x;
this.eye.y += du * this._u.y + dv * this._v.y + dn * this._n.y;
this.eye.z += du * this._u.z + dv * this._v.z + dn * this._n.z;
}
/**
* Roll the camera to the angle in degrees.
* @public
* @param {number} angle - Delta roll angle in degrees.
*/
roll(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._u.clone();
this._u.set(cs * t.x - sn * this._v.x, cs * t.y - sn * this._v.y, cs * t.z - sn * this._v.z);
this._v.set(sn * t.x + cs * this._v.x, sn * t.y + cs * this._v.y, sn * t.z + cs * this._v.z);
}
/**
* Pitch the camera to the angle in degrees.
* @public
* @param {number} angle - Delta pitch angle in degrees.
*/
pitch(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._n.clone();
this._n.set(cs * t.x - sn * this._v.x, cs * t.y - sn * this._v.y, cs * t.z - sn * this._v.z);
this._v.set(sn * t.x + cs * this._v.x, sn * t.y + cs * this._v.y, sn * t.z + cs * this._v.z);
}
/**
* Yaw the camera to the angle in degrees.
* @public
* @param {number} angle - Delta yaw angle in degrees.
*/
yaw(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._u.clone();
this._u.set(cs * t.x - sn * this._n.x, cs * t.y - sn * this._n.y, cs * t.z - sn * this._n.z);
this._n.set(sn * t.x + cs * this._n.x, sn * t.y + cs * this._n.y, sn * t.z + cs * this._n.z);
}
/**
* Returns normal vector direction to to the unprojected screen point from camera eye.
* @public
* @param {number} x - Scren X coordinate.
* @param {number} y - Scren Y coordinate.
* @returns {og.math.Vector3} - Direction vector.
*/
unproject(x, y) {
var c = this.renderer.handler.canvas,
w = c.width * 0.5,
h = c.height * 0.5;
var px = (x - w) / w,
py = -(y - h) / h;
var world1 = this._inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, -1, 1)).affinity(),
world2 = this._inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, 0, 1)).affinity();
return world2.subA(world1).toVec3().normalize();
}
/**
* Gets projected 3d point to the 2d screen coordiantes.
* @public
* @param {og.math.Vector3} v - Cartesian 3d coordiantes.
* @returns {og.math.Vector2} - Screen point coordinates.
*/
project(v) {
var r = this._projectionViewMatrix.mulVec4(v.toVector4()),
c = this.renderer.handler.canvas;
return new Vec2((1 + r.x / r.w) * c.width * 0.5, (1 - r.y / r.w) * c.height * 0.5);
}
/**
* Rotates camera around center point.
* @public
* @param {number} angle - Rotation angle in radians.
* @param {boolaen} isArc - If true camera up vector gets from current up vector every frame,
* otherwise up is always input parameter.
* @param {og.math.Vector3} center - Point that the camera rotates around.
* @param {og.math.Vecto3} [up] - Camera up vector.
*/
rotateAround(angle, isArc, center, up) {
center = center || Vec3.ZERO;
up = up || Vec3.UP;
var rot = new Mat4().setRotation(isArc ? this._v : up, angle);
var tr = new Mat4().setIdentity().translate(center);
var ntr = new Mat4().setIdentity().translate(center.negateTo());
var trm = tr.mul(rot).mul(ntr);
this.eye = trm.mulVec3(this.eye);
this._v = rot.mulVec3(this._v).normalize();
this._u = rot.mulVec3(this._u).normalize();
this._n = rot.mulVec3(this._n).normalize();
}
/**
* Rotates camera around center point by horizontal.
* @public
* @param {number} angle - Rotation angle in radians.
* @param {boolaen} isArc - If true camera up vector gets from current up vector every frame,
* otherwise up is always input parameter.
* @param {og.math.Vector3} center - Point that the camera rotates around.
* @param {og.math.Vector3} [up] - Camera up vector.
*/
rotateHorizontal(angle, isArc, center, up) {
this.rotateAround(angle, isArc, center, up);
}
/**
* Rotates camera around center point by vecrtical.
* @param {number} angle - Rotation angle in radians.
* @param {og.math.Vector3} center - Point that the camera rotates around.
*/
rotateVertical(angle, center) {
this.rotateAround(angle, false, center, this._u);
}
/**
* Gets 3d size factor. Uses in LOD distance calculation.
* @public
* @param {og.math.Vector3} p - Far point.
* @param {og.math.Vector3} r - Far point.
* @returns {number} - Size factor.
*/
projectedSize(p, r) {
return Math.atan(r / this.eye.distance(p)) * this._projSizeConst;
}
/**
* Returns normal matrix.
* @public
* @returns {og.math.Matrix3} - Normal matrix.
*/
getNormalMatrix() {
return this._normalMatrix;
}
/**
* Returns projection matrix.
* @public
* @returns {og.math.Matrix4} - Projection matrix.
*/
getProjectionMatrix() {
return this._projectionMatrix;
}
/**
* Returns model matrix.
* @public
* @returns {og.math.Matrix4} - View matrix.
*/
getViewMatrix() {
return this._viewMatrix;
}
/**
* Returns projection and model matrix product.
* @public
* @return {og.math.Matrix4} - Projection-view matrix.
*/
getProjectionViewMatrix() {
return this._projectionViewMatrix;
}
/**
* Returns inverse projection and model matrix product.
* @public
* @returns {og.math.Matrix4} - Inversed projection-view matrix.
*/
getInverseProjecttionViewMatrix() {
return this._inverseProjectionViewMatrix;
}
};
const EVENT_NAMES = [
/**
* When camera has been updated.
* @event og.Camera#viewchange
*/
"viewchange",
/**
* Camera is stopped.
* @event og.Camera#moveend
*/
"moveend"
];
const defaultOptions = {
'viewAngle': 30,
'near': 1,
'far': math.MAX,
'eye': new Vec3(0, 0, 0),
'look': new Vec3(0, 0, 0),
'up': new Vec3(0, 1, 0)
};
export { Camera };

View File

@ -1,529 +0,0 @@
/**
* @module og/camera/PlanetCamera
*/
'use strict';
import * as math from '../math.js';
import * as mercator from '../mercator.js';
import { Camera } from './Camera.js';
import { Vec3 } from '../math/Vec3.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Ray } from '../math/Ray.js';
/**
* Planet camera.
* @class
* @extends {og.Camera}
* @param {og.RenderNode} planet - Planet render node.
* @param {Object} [options] - Planet camera options:
* @param {Object} [options.name] - Camera name.
* @param {number} [options.viewAngle] - Camera angle of view. Default is 35.0
* @param {number} [options.near] - Camera near plane distance. Default is 1.0
* @param {number} [options.far] - Camera far plane distance. Deafult is og.math.MAX
* @param {number} [options.minAltitude] - Minimal altitude for the camera. Deafult is 50
* @param {og.math.Vector3} [options.eye] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up] - Camera eye position. Default (0,1,0)
*/
class PlanetCamera extends Camera {
constructor(planet, options) {
super(planet.renderer, options);
/**
* Assigned camera's planet.
* @public
* @type {og.scene.Planet}
*/
this.planet = planet;
/**
* Minimal alltitude that camera can reach over the terrain.
* @public
* @type {number}
*/
this.minAltitude = options.minAltitude || 50;
/**
* Current geographical degree position.
* @protected
* @type {og.LonLat}
*/
this._lonLat = this.planet.ellipsoid.cartesianToLonLat(this.eye);
/**
* Current geographical mercator position.
* @protected
* @type {og.LonLat}
*/
this._lonLatMerc = this._lonLat.forwardMercator();
/**
* Current altitude.
* @protected
* @type {number}
*/
this._terrainAltitude = this._lonLat.height;
/**
* Cartesian coordinates on the terrain.
* @protected
* @type {og.math.Vector3}
*/
this._terrainPoint = new Vec3();
/**
* Quad node that camera flies over.
* @protected
* @type {og.quadTree.Node}
*/
this._insideSegment = null;
this.slope = 0;
/**
* Coordinates that depends on what segment class we are fling over.
* It can be WGS84 or Mercator coordinates. Gets in og.quadTree.Node
* @protected
* @type {og.LonLat}
*/
this._insideSegmentPosition = null;
this._keyLock = new Key();
//Camera's flying frames
this._framesArr = [];
this._framesCounter = 0;
this._numFrames = 50;
this._completeCallback = null;
this._flying = false;
}
/**
* Clone planet camera instance to another one.
* @public
* @virtual
* @returns {og.PlanetCamera}
*/
clone() {
var newcam = new PlanetCamera();
newcam.eye.copy(cam.eye);
newcam._u.copy(cam._u);
newcam._v.copy(cam._v);
newcam._n.copy(cam._n);
newcam.renderer = cam.renderer;
newcam._projectionMatrix.copy(cam._projectionMatrix);
newcam._viewMatrix.copy(cam._viewMatrix);
newcam._projectionViewMatrix.copy(cam._projectionViewMatrix);
newcam._inverseProjectionViewMatrix.copy(cam._inverseProjectionViewMatrix);
newcam.frustum.setFrustum(newcam._projectionViewMatrix);
newcam.planet = cam.planet;
newcam._lonLat = cam._lonLat.clone();
return newcam;
}
/**
* Updates camera view space.
* @public
* @virtual
*/
update() {
this._setViewMatrix();
this._projectionViewMatrix = this._projectionMatrix.mul(this._viewMatrix);
this.frustum.setFrustum(this._projectionViewMatrix._m);
this._inverseProjectionViewMatrix = this._projectionMatrixPrecise.mul(this._viewMatrix).inverseTo();
//this._normalMatrix = this._viewMatrix.toInverseMatrix3().transposeTo();
this._normalMatrix = this._viewMatrix.toMatrix3();
this.updateGeodeticPosition();
this.slope = this._n.dot(this.eye.normal());
this.events.dispatch(this.events.viewchange, this);
}
updateGeodeticPosition() {
this._lonLat = this.planet.ellipsoid.cartesianToLonLat(this.eye);
if (Math.abs(this._lonLat.lat) <= mercator.MAX_LAT) {
this._lonLatMerc = this._lonLat.forwardMercator();
}
}
/**
* Sets altitude over the terrain.
* @public
* @param {number} alt - Altitude over the terrain.
*/
setAltitude(alt) {
var n = this.eye.normal();
var t = this._terrainPoint;
this.eye.x = n.x * alt + t.x;
this.eye.y = n.y * alt + t.y;
this.eye.z = n.z * alt + t.z;
this._terrainAltitude = alt;
this.update();
}
/**
* Gets altitude over the terrain.
* @public
*/
getAltitude() {
return this._terrainAltitude;
}
/**
* Moves camera to the geographical position.
* @public
* @param {og.LonLat} lonlat - Geographical position.
*/
setLonLat(lonlat, up) {
this._lonLat.set(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
var newEye = this.planet.ellipsoid.lonLatToCartesian(this._lonLat);
var rot = new Mat4().rotateBetweenVectors(newEye.normal(), this.eye.normal());
this.eye = newEye;
this._v = rot.mulVec3(this._v);
this._u = rot.mulVec3(this._u);
this._n = rot.mulVec3(this._n);
}
/**
* Returns camera geographical position.
* @public
* @returns {og.LonLat}
*/
getLonLat() {
return this._lonLat;
}
/**
* Returns camera height.
* @public
* @returns {number}
*/
getHeight() {
return this._lonLat.height;
}
/**
* Places camera to view to the geographical point.
* @public
* @param {og.LonLat} lonlat - New camera and camera view position.
* @param {og.math.Vector3} [up] - Camera UP vector. Default (0,1,0)
*/
viewLonLat(lonlat, up) {
this._lonLat.set(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
var el = this.planet.ellipsoid;
var newEye = el.lonLatToCartesian(this._lonLat);
var newLook = el.lonLatToCartesian(new LonLat(this._lonLat.lon, this._lonLat.lat, 0));
this.set(newEye, newLook, up || Vec3.UP);
}
/**
* Gets position by viewable extent.
* @public
* @param {og.Extent} extent - Viewable extent.
* @returns {og.math.Vector3}
*/
getExtentPosition(extent) {
var north = extent.getNorth();
var south = extent.getSouth();
var east = extent.getEast();
var west = extent.getWest();
if (west > east) {
east += 360;
}
var e = this.planet.ellipsoid;
var cart = new LonLat(east, north);
var northEast = e.lonLatToCartesian(cart);
cart.lat = south;
var southEast = e.lonLatToCartesian(cart);
cart.lon = west;
var southWest = e.lonLatToCartesian(cart);
cart.lat = north;
var northWest = e.lonLatToCartesian(cart);
var center = Vec3.sub(northEast, southWest).scale(0.5).addA(southWest);
var mag = center.length();
if (mag < 0.000001) {
cart.lon = (east + west) * 0.5;
cart.lat = (north + south) * 0.5;
center = e.lonLatToCartesian(cart);
}
northWest.subA(center);
southEast.subA(center);
northEast.subA(center);
southWest.subA(center);
var direction = center.normal();//ellipsoid.getSurfaceNormal(center).negate().normalize();
var right = direction.cross(Vec3.UP).normalize();
var up = right.cross(direction).normalize();
var height = Math.max(
Math.abs(up.dot(northWest)),
Math.abs(up.dot(southEast)),
Math.abs(up.dot(northEast)),
Math.abs(up.dot(southWest))
);
var width = Math.max(
Math.abs(right.dot(northWest)),
Math.abs(right.dot(southEast)),
Math.abs(right.dot(northEast)),
Math.abs(right.dot(southWest))
);
var tanPhi = Math.tan(this._viewAngle * math.RADIANS * 0.5);
var tanTheta = this._aspect * tanPhi;
var d = Math.max(width / tanTheta, height / tanPhi);
center.normalize();
center.scale(mag + d);
return center;
}
/**
* View current extent.
* @public
* @param {og.Extent} extent - Current extent.
*/
viewExtent(extent) {
this.stopFlying();
this.set(this.getExtentPosition(extent), Vec3.ZERO, Vec3.UP);
this.refresh();
}
/**
* Flies to the current extent.
* @public
* @param {og.Extent} extent - Current extent.
* @param {og.math.Vector3} [up] - Camera UP in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyExtent(extent, up, completeCallback, startCallback) {
this.flyCartesian(this.getExtentPosition(extent), Vec3.ZERO,
up, completeCallback, startCallback);
}
/**
* Flies to the cartesian coordinates.
* @public
* @param {og.math.Vector3} cartesian - Finish cartesian coordinates.
* @param {og.math.Vector3} [look] - Camera LOOK in the end of flying. Default - (0,0,0)
* @param {og.math.Vector3} [up] - Camera UP vector in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyCartesian(cartesian, look, up, completeCallback, startCallback) {
//???????
//if (this.eye.distance(cartesian) < 23000) {
// return;
//}
this.stopFlying();
this._completeCallback = completeCallback;
if (startCallback) {
startCallback.call(this);
}
var _look = look || Vec3.ZERO;
if (look instanceof LonLat) {
_look = this.planet.ellipsoid.lonLatToCartesian(look);
}
var ground_a = this.planet.ellipsoid.lonLatToCartesian(new LonLat(this._lonLat.lon, this._lonLat.lat));
var v_a = this._v,
n_a = this._n;
var lonlat_b = this.planet.ellipsoid.cartesianToLonLat(cartesian);
var up_b = up || Vec3.UP;
var ground_b = this.planet.ellipsoid.lonLatToCartesian(new LonLat(lonlat_b.lon, lonlat_b.lat, 0));
var eye_b = cartesian;
var n_b = Vec3.sub(eye_b, _look);
var u_b = up_b.cross(n_b);
n_b.normalize();
u_b.normalize();
var v_b = n_b.cross(u_b);
var an = ground_a.normal();
var bn = ground_b.normal();
var anbn = 1.0 - an.dot(bn);
var hM_a = math.SQRT_HALF * Math.sqrt((anbn) > 0.0 ? anbn : 0.0);
var maxHeight = 6639613;
var currMaxHeight = Math.max(this._lonLat.height, lonlat_b.height);
if (currMaxHeight > maxHeight) {
maxHeight = currMaxHeight;
}
var max_h = currMaxHeight + 2.5 * hM_a * (maxHeight - currMaxHeight);
var zero = Vec3.ZERO;
//camera path and orientations calculation
for (var i = 0; i <= this._numFrames; i++) {
var d = 1 - i / this._numFrames;
d = d * d * (3 - 2 * d);
d *= d;
//Error here
var g_i = ground_a.smerp(ground_b, d).normalize();
var ground_i = this.planet.getRayIntersectionEllipsoid(new Ray(zero, g_i));
var t = 1 - d;
var height_i = this._lonLat.height * d * d * d + max_h * 3 * d * d * t + max_h * 3 * d * t * t + lonlat_b.height * t * t * t;
var eye_i = ground_i.addA(g_i.scale(height_i));
var up_i = v_a.smerp(v_b, d);
var look_i = Vec3.add(eye_i, n_a.smerp(n_b, d).negateTo());
var n = new Vec3(eye_i.x - look_i.x, eye_i.y - look_i.y, eye_i.z - look_i.z);
var u = up_i.cross(n);
n.normalize();
u.normalize();
var v = n.cross(u);
this._framesArr[i] = {
"eye": eye_i,
"n": n,
"u": u,
"v": v
};
}
this._framesCounter = this._numFrames;
this._flying = true;
}
/**
* Flies to the geo coordiantes.
* @public
* @param {og.LonLat} lonlat - Finish coordinates.
* @param {og.math.Vector3} [look] - Camera LOOK in the end of flying. Default - (0,0,0)
* @param {og.math.Vector3} [up] - Camera UP vector in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyLonLat(lonlat, look, up, completeCallback, startCallback) {
var _lonlat = new LonLat(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
this.flyCartesian(this.planet.ellipsoid.lonLatToCartesian(_lonlat), look, up, completeCallback, startCallback);
}
/**
* Breaks the flight.
* @public
*/
stopFlying() {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
this._flying = false;
this._framesArr.length = 0;
this._framesArr = [];
this._framesCounter = -1;
}
/**
* Returns camera is flying.
* @public
* @returns {boolean}
*/
isFlying() {
return this._flying;
}
/**
* Rotates around planet to the left.
* @public
* @param {number} angle - Rotation angle.
* @param {boolean} [spin] - If its true rotates around globe spin.
*/
rotateLeft(angle, spin) {
this.rotateHorizontal(angle * math.RADIANS, spin ^ true, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the right.
* @public
* @param {number} angle - Rotation angle.
* @param {boolean} [spin] - If its true rotates around globe spin.
*/
rotateRight(angle, spin) {
this.rotateHorizontal(-angle * math.RADIANS, spin ^ true, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the north pole.
* @public
* @param {number} angle - Rotation angle.
*/
rotateUp(angle) {
this.rotateVertical(angle * math.RADIANS, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the south pole.
* @public
* @param {number} angle - Rotation angle.
*/
rotateDown(angle) {
this.rotateVertical(-angle * math.RADIANS, Vec3.ZERO);
this.update();
}
/**
* Prepare camera to the frame. Used in render node frame function.
* @public
*/
prepareFrame() {
if (this._flying) {
var c = this._numFrames - this._framesCounter;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.eye = this._framesArr[c].eye;
this._u = this._framesArr[c].u;
this._v = this._framesArr[c].v;
this._n = this._framesArr[c].n;
this.update();
this._framesCounter--;
if (this._framesCounter < 0) {
this.stopFlying();
if (this._completeCallback) {
this._completeCallback();
this._completeCallback = null;
}
}
} else {
this._terrainAltitude = this._lonLat.height;
if (this._lonLat.height < 1000000) {
this._terrainAltitude = this._insideSegment.getTerrainPoint(this._terrainPoint, this.eye, this._insideSegmentPosition);
if (this._terrainAltitude < this.minAltitude) {
this.setAltitude(this.minAltitude);
}
}
}
}
};
export { PlanetCamera };

View File

@ -1,649 +0,0 @@
/**
* @module og/camera/Camera
*/
'use strict';
import * as math from '../math.js';
import { Events } from '../Events.js';
import { Frustum } from '../Frustum.js';
import { Vec2 } from '../math/Vec2.js';
import { Vec3 } from '../math/Vec3.js';
import { Vec4 } from '../math/Vec4.js';
import { Mat3 } from '../math/Mat3.js';
import { Mat4 } from '../math/Mat4.js';
/**
* Camera class.
* @class
* @param {og.Renderer} [renderer] - Renderer uses the camera instance.
* @param {Object} [options] - Camera options:
* @param {Object} [options.name] - Camera name.
* @param {number} [options.viewAngle=30] - Camera angle of view. Default is 30.0
* @param {number} [options.near=1] - Camera near plane distance. Default is 1.0
* @param {number} [options.far=og.math.MAX] - Camera far plane distance. Deafult is og.math.MAX
* @param {og.math.Vector3} [options.eye=[0,0,0]] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look=[0,0,0]] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up=[0,1,0]] - Camera eye position. Default (0,1,0)
*
* @fires og.Camera#viewchange
*/
class Camera {
constructor(renderer, options) {
/**
* Assigned renderer.
* @public
* @type {og.Renderer}
*/
this.renderer = null;
/**
* Camera events handler.
* @public
* @type {og.Events}
*/
this.events = new Events(EVENT_NAMES);
/**
* Camera position.
* @public
* @type {og.math.Vector3}
*/
this.eye = new Vec3();
/**
* Camera frustum.
* @public
* @type {og.Frustum}
*/
this.frustum = new Frustum();
/**
* Aspect ratio.
* @protected
* @type {Number}
*/
this._aspect = options.aspect || 0;
/**
* Camera near distance.
* @protected
* @type {Number}
*/
this._nearDist = 0;
/**
* Camera far distance.
* @protected
* @type {Number}
*/
this._farDist = 0;
/**
* Camera view angle in degrees.
* @protected
* @type {Number}
*/
this._viewAngle = 0;
/**
* Camera normal matrix.
* @protected
* @type {og.math.Matrix3}
*/
this._normalMatrix = new Mat3();
/**
* Camera projection matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionMatrix = new Mat4();
/**
* Camera view matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._viewMatrix = new Mat4();
/**
* Product of projection and view matrices.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionViewMatrix = new Mat4();
/**
* Inverse projectionView Matrix.
* @protected
* @type {og.math.Matrix4}
*/
this._inverseProjectionViewMatrix = new Mat4();
/**
* Camera projection matrix for small near and far distances.
* @protected
* @type {og.math.Matrix4}
*/
this._projectionMatrixPrecise = new Mat4();
/**
* Camera right vector.
* @protected
* @type {og.math.Vector3}
*/
this._u = new Vec3(0, 1, 0); //up x n
/**
* Camera up vector.
* @protected
* @type {og.math.Vector3}
*/
this._v = new Vec3(1, 0, 0); //n x u - UP
this.slope = 0;
/**
* Camera forward vector.
* @protected
* @type {og.math.Vector3}
*/
this._n = new Vec3(0, 0, 1); //eye - look - FORWARD
this._pu = this._u;
this._pv = this._v;
this._pn = this._n;
this._peye = this.eye;
this._moved = false;
this._tanViewAngle_hrad = 0;
this._tanViewAngle_hradOneByHeight = 0;
this.renderer = renderer;
renderer && this._initialize(options);
}
/**
* Updates model view matrix.
* @protected
*/
_setViewMatrix() {
var u = this._u,
v = this._v,
n = this._n,
eye = this.eye;
this._viewMatrix.set([u.x, v.x, n.x, 0,
u.y, v.y, n.y, 0,
u.z, v.z, n.z, 0,
-eye.dot(u), -eye.dot(v), -eye.dot(n), 1.0]);
}
checkMoveEnd() {
var u = this._u,
v = this._v,
n = this._n,
eye = this.eye;
if (this.events.moveend.handlers.length) {
if (this._peye.equal(eye) &&
this._pu.equal(u) &&
this._pv.equal(v) &&
this._pn.equal(n)) {
if (this._moved) {
this.events.dispatch(this.events.moveend, this);
}
this._moved = false;
} else {
this._moved = true;
}
}
this._pu = u;
this._pv = v;
this._pn = n;
this._peye = eye;
}
/**
* Camera initialization.
* @public
* @param {og.Renderer} renderer - OpenGlobus renderer object.
* @param {Object} [options] - Camera options:
* @param {number} [options.viewAngle] - Camera angle of view. Default is 30.0
* @param {number} [options.near] - Camera near plane distance. Default is 1.0
* @param {number} [options.far] - Camera far plane distance. Deafult is og.math.MAX
* @param {og.math.Vector3} [options.eye] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up] - Camera eye position. Default (0,1,0)
*/
_initialize(options) {
this.setProjectionMatrix(
options.viewAngle || defaultOptions.viewAngle,
this._aspect || this.renderer.handler.getClientAspect(),
options.near || defaultOptions.near,
options.far || defaultOptions.far);
this.set(
options.eye || defaultOptions.eye.clone(),
options.look || defaultOptions.look.clone(),
options.up || defaultOptions.up.clone());
}
getUp() {
return this._v;
}
getDown() {
return this._v.negateTo();
}
getRight() {
return this._u;
}
getLeft() {
return this._u.negateTo();
}
getForward() {
return this._n;
}
getBackward() {
return this._n.negateTo();
}
/**
* Clone camera instance to another one.
* @public
* @virtual
* @returns {og.Camera} - Cloned camera instance.
*/
clone() {
var newcam = new Camera();
newcam.eye.copy(cam.eye);
newcam._u.copy(cam._u);
newcam._v.copy(cam._v);
newcam._n.copy(cam._n);
newcam.renderer = cam.renderer;
newcam._projectionMatrix.copy(cam._projectionMatrix);
newcam._viewMatrix.copy(cam._viewMatrix);
newcam._projectionViewMatrix.copy(cam._projectionViewMatrix);
newcam._inverseProjectionViewMatrix.copy(cam._inverseProjectionViewMatrix);
newcam.frustum.setFrustum(newcam._projectionViewMatrix);
return newcam;
}
/**
* Updates camera view space.
* @public
* @virtual
*/
update() {
this._setViewMatrix();
this._projectionViewMatrix = this._projectionMatrix.mul(this._viewMatrix);
this.frustum.setFrustum(this._projectionViewMatrix._m);
this._inverseProjectionViewMatrix = this._projectionViewMatrix.inverseTo();
this._normalMatrix = this._viewMatrix.toMatrix3();//this._viewMatrix.toInverseMatrix3().transposeTo();
this.events.dispatch(this.events.viewchange, this);
}
/**
* Refresh camera matrices.
* @public
*/
refresh() {
this.setProjectionMatrix(this._viewAngle, this._aspect, this._nearDist, this._farDist);
this.update();
}
/**
* Sets aspect ratio.
* @public
* @param {Number} aspect - Camera aspect ratio.
*/
setAspectRatio(aspect) {
this._aspect = aspect;
this.refresh();
}
/**
* Returns aspect ratio.
* @public
* @returns {number} - Aspect ratio.
*/
getAspectRatio() {
return this._aspect;
}
/**
* Sets far camera distance.
* @public
* @param {number} distance - Far distance.
*/
setFar(distance) {
this._farDist = distance;
this.refresh();
}
/**
* Gets far distance.
* @public
* @returns {number} - Far plane distance.
*/
getFar() {
return this._farDist;
}
/**
* Sets camera's near distance.
* @public
* @param {number} distance - Near distance.
*/
setNear(distance) {
this._nearDist = distance;
this.refresh();
}
/**
* Gets near distance.
* @public
* @returns {number} - Near plane distance.
*/
getNear() {
return this._nearDist;
}
/**
* Sets up camera projection matrix.
* @public
* @param {nnumber} angle - Camera's view angle.
* @param {number} aspect - Screen aspect ration.
* @param {number} near - Near camera distance.
* @param {number} far - Far camera distance.
*/
setProjectionMatrix(angle, aspect, near, far) {
this._viewAngle = angle;
this._aspect = aspect;
this._nearDist = near;
this._farDist = far;
this._tanViewAngle_hrad = Math.tan(angle * math.RADIANS_HALF);
this._tanViewAngle_hradOneByHeight = this._tanViewAngle_hrad * this.renderer.handler._oneByHeight;
var c = this.renderer.handler.canvas;
this._projSizeConst = Math.min(c.clientWidth, c.clientHeight) / (this._viewAngle * math.RADIANS);
this._projectionMatrix.setPerspective(angle, aspect, near, far);
this._projectionMatrixPrecise.setPerspective(angle, aspect, 0.1, 10);
}
/**
* Sets camera view angle in degrees.
* @public
* @param {number} angle - View angle.
*/
setViewAngle(angle) {
this._viewAngle = angle;
this.refresh();
}
/**
* Sets camera to eye position.
* @public
* @param {og.math.Vector3} eye - Camera position.
* @param {og.math.Vector3} look - Look point.
* @param {og.math.Vector3} up - Camera up vector.
* @returns {og.Camera} - This camera.
*/
set(eye, look, up) {
this.eye.x = eye.x;
this.eye.y = eye.y;
this.eye.z = eye.z;
look = look || this._n;
up = up || this._v;
this._n.x = eye.x - look.x;
this._n.y = eye.y - look.y;
this._n.z = eye.z - look.z;
this._u.copy(up.cross(this._n));
this._n.normalize();
this._u.normalize();
this._v.copy(this._n.cross(this._u));
return this;
}
/**
* Sets camera look point.
* @public
* @param {og.math.Vector3} look - Look point.
* @param {og.math.Vector3} [up] - Camera up vector otherwise camera current up vector(this._v)
*/
look(look, up) {
this._n.set(this.eye.x - look.x, this.eye.y - look.y, this.eye.z - look.z);
this._u.copy((up || this._v).cross(this._n));
this._n.normalize();
this._u.normalize();
this._v.copy(this._n.cross(this._u));
}
/**
* Slides camera to vector d - (du, dv, dn).
* @public
* @param {number} du - delta X.
* @param {number} dv - delta Y.
* @param {number} dn - delta Z.
*/
slide(du, dv, dn) {
this.eye.x += du * this._u.x + dv * this._v.x + dn * this._n.x;
this.eye.y += du * this._u.y + dv * this._v.y + dn * this._n.y;
this.eye.z += du * this._u.z + dv * this._v.z + dn * this._n.z;
}
/**
* Roll the camera to the angle in degrees.
* @public
* @param {number} angle - Delta roll angle in degrees.
*/
roll(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._u.clone();
this._u.set(cs * t.x - sn * this._v.x, cs * t.y - sn * this._v.y, cs * t.z - sn * this._v.z);
this._v.set(sn * t.x + cs * this._v.x, sn * t.y + cs * this._v.y, sn * t.z + cs * this._v.z);
}
/**
* Pitch the camera to the angle in degrees.
* @public
* @param {number} angle - Delta pitch angle in degrees.
*/
pitch(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._n.clone();
this._n.set(cs * t.x - sn * this._v.x, cs * t.y - sn * this._v.y, cs * t.z - sn * this._v.z);
this._v.set(sn * t.x + cs * this._v.x, sn * t.y + cs * this._v.y, sn * t.z + cs * this._v.z);
}
/**
* Yaw the camera to the angle in degrees.
* @public
* @param {number} angle - Delta yaw angle in degrees.
*/
yaw(angle) {
var cs = Math.cos(math.RADIANS * angle);
var sn = Math.sin(math.RADIANS * angle);
var t = this._u.clone();
this._u.set(cs * t.x - sn * this._n.x, cs * t.y - sn * this._n.y, cs * t.z - sn * this._n.z);
this._n.set(sn * t.x + cs * this._n.x, sn * t.y + cs * this._n.y, sn * t.z + cs * this._n.z);
}
/**
* Returns normal vector direction to to the unprojected screen point from camera eye.
* @public
* @param {number} x - Scren X coordinate.
* @param {number} y - Scren Y coordinate.
* @returns {og.math.Vector3} - Direction vector.
*/
unproject(x, y) {
var c = this.renderer.handler.canvas,
w = c.width * 0.5,
h = c.height * 0.5;
var px = (x - w) / w,
py = -(y - h) / h;
var world1 = this._inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, -1, 1)).affinity(),
world2 = this._inverseProjectionViewMatrix.mulVec4(new Vec4(px, py, 0, 1)).affinity();
return world2.subA(world1).toVec3().normalize();
}
/**
* Gets projected 3d point to the 2d screen coordiantes.
* @public
* @param {og.math.Vector3} v - Cartesian 3d coordiantes.
* @returns {og.math.Vector2} - Screen point coordinates.
*/
project(v) {
var r = this._projectionViewMatrix.mulVec4(v.toVector4()),
c = this.renderer.handler.canvas;
return new Vec2((1 + r.x / r.w) * c.width * 0.5, (1 - r.y / r.w) * c.height * 0.5);
}
/**
* Rotates camera around center point.
* @public
* @param {number} angle - Rotation angle in radians.
* @param {boolaen} isArc - If true camera up vector gets from current up vector every frame,
* otherwise up is always input parameter.
* @param {og.math.Vector3} center - Point that the camera rotates around.
* @param {og.math.Vecto3} [up] - Camera up vector.
*/
rotateAround(angle, isArc, center, up) {
center = center || Vec3.ZERO;
up = up || Vec3.UP;
var rot = new Mat4().setRotation(isArc ? this._v : up, angle);
var tr = new Mat4().setIdentity().translate(center);
var ntr = new Mat4().setIdentity().translate(center.negateTo());
var trm = tr.mul(rot).mul(ntr);
this.eye = trm.mulVec3(this.eye);
this._v = rot.mulVec3(this._v).normalize();
this._u = rot.mulVec3(this._u).normalize();
this._n = rot.mulVec3(this._n).normalize();
}
/**
* Rotates camera around center point by horizontal.
* @public
* @param {number} angle - Rotation angle in radians.
* @param {boolaen} isArc - If true camera up vector gets from current up vector every frame,
* otherwise up is always input parameter.
* @param {og.math.Vector3} center - Point that the camera rotates around.
* @param {og.math.Vector3} [up] - Camera up vector.
*/
rotateHorizontal(angle, isArc, center, up) {
this.rotateAround(angle, isArc, center, up);
}
/**
* Rotates camera around center point by vecrtical.
* @param {number} angle - Rotation angle in radians.
* @param {og.math.Vector3} center - Point that the camera rotates around.
*/
rotateVertical(angle, center) {
this.rotateAround(angle, false, center, this._u);
}
/**
* Gets 3d size factor. Uses in LOD distance calculation.
* @public
* @param {og.math.Vector3} p - Far point.
* @param {og.math.Vector3} r - Far point.
* @returns {number} - Size factor.
*/
projectedSize(p, r) {
return Math.atan(r / this.eye.distance(p)) * this._projSizeConst;
}
/**
* Returns normal matrix.
* @public
* @returns {og.math.Matrix3} - Normal matrix.
*/
getNormalMatrix() {
return this._normalMatrix;
}
/**
* Returns projection matrix.
* @public
* @returns {og.math.Matrix4} - Projection matrix.
*/
getProjectionMatrix() {
return this._projectionMatrix;
}
/**
* Returns model matrix.
* @public
* @returns {og.math.Matrix4} - View matrix.
*/
getViewMatrix() {
return this._viewMatrix;
}
/**
* Returns projection and model matrix product.
* @public
* @return {og.math.Matrix4} - Projection-view matrix.
*/
getProjectionViewMatrix() {
return this._projectionViewMatrix;
}
/**
* Returns inverse projection and model matrix product.
* @public
* @returns {og.math.Matrix4} - Inversed projection-view matrix.
*/
getInverseProjecttionViewMatrix() {
return this._inverseProjectionViewMatrix;
}
};
const EVENT_NAMES = [
/**
* When camera has been updated.
* @event og.Camera#viewchange
*/
"viewchange",
/**
* Camera is stopped.
* @event og.Camera#moveend
*/
"moveend"
];
const defaultOptions = {
'viewAngle': 30,
'near': 1,
'far': math.MAX,
'eye': new Vec3(0, 0, 0),
'look': new Vec3(0, 0, 0),
'up': new Vec3(0, 1, 0)
};
export { Camera };

View File

@ -1,529 +0,0 @@
/**
* @module og/camera/PlanetCamera
*/
'use strict';
import * as math from '../math.js';
import * as mercator from '../mercator.js';
import { Camera } from './Camera.js';
import { Vec3 } from '../math/Vec3.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Ray } from '../math/Ray.js';
/**
* Planet camera.
* @class
* @extends {og.Camera}
* @param {og.RenderNode} planet - Planet render node.
* @param {Object} [options] - Planet camera options:
* @param {Object} [options.name] - Camera name.
* @param {number} [options.viewAngle] - Camera angle of view. Default is 35.0
* @param {number} [options.near] - Camera near plane distance. Default is 1.0
* @param {number} [options.far] - Camera far plane distance. Deafult is og.math.MAX
* @param {number} [options.minAltitude] - Minimal altitude for the camera. Deafult is 50
* @param {og.math.Vector3} [options.eye] - Camera eye position. Default (0,0,0)
* @param {og.math.Vector3} [options.look] - Camera look position. Default (0,0,0)
* @param {og.math.Vector3} [options.up] - Camera eye position. Default (0,1,0)
*/
class PlanetCamera extends Camera {
constructor(planet, options) {
super(planet.renderer, options);
/**
* Assigned camera's planet.
* @public
* @type {og.scene.Planet}
*/
this.planet = planet;
/**
* Minimal alltitude that camera can reach over the terrain.
* @public
* @type {number}
*/
this.minAltitude = options.minAltitude || 50;
/**
* Current geographical degree position.
* @protected
* @type {og.LonLat}
*/
this._lonLat = this.planet.ellipsoid.cartesianToLonLat(this.eye);
/**
* Current geographical mercator position.
* @protected
* @type {og.LonLat}
*/
this._lonLatMerc = this._lonLat.forwardMercator();
/**
* Current altitude.
* @protected
* @type {number}
*/
this._terrainAltitude = this._lonLat.height;
/**
* Cartesian coordinates on the terrain.
* @protected
* @type {og.math.Vector3}
*/
this._terrainPoint = new Vec3();
/**
* Quad node that camera flies over.
* @protected
* @type {og.quadTree.Node}
*/
this._insideSegment = null;
this.slope = 0;
/**
* Coordinates that depends on what segment class we are fling over.
* It can be WGS84 or Mercator coordinates. Gets in og.quadTree.Node
* @protected
* @type {og.LonLat}
*/
this._insideSegmentPosition = null;
this._keyLock = new Key();
//Camera's flying frames
this._framesArr = [];
this._framesCounter = 0;
this._numFrames = 50;
this._completeCallback = null;
this._flying = false;
}
/**
* Clone planet camera instance to another one.
* @public
* @virtual
* @returns {og.PlanetCamera}
*/
clone() {
var newcam = new PlanetCamera();
newcam.eye.copy(cam.eye);
newcam._u.copy(cam._u);
newcam._v.copy(cam._v);
newcam._n.copy(cam._n);
newcam.renderer = cam.renderer;
newcam._projectionMatrix.copy(cam._projectionMatrix);
newcam._viewMatrix.copy(cam._viewMatrix);
newcam._projectionViewMatrix.copy(cam._projectionViewMatrix);
newcam._inverseProjectionViewMatrix.copy(cam._inverseProjectionViewMatrix);
newcam.frustum.setFrustum(newcam._projectionViewMatrix);
newcam.planet = cam.planet;
newcam._lonLat = cam._lonLat.clone();
return newcam;
}
/**
* Updates camera view space.
* @public
* @virtual
*/
update() {
this._setViewMatrix();
this._projectionViewMatrix = this._projectionMatrix.mul(this._viewMatrix);
this.frustum.setFrustum(this._projectionViewMatrix._m);
this._inverseProjectionViewMatrix = this._projectionMatrixPrecise.mul(this._viewMatrix).inverseTo();
//this._normalMatrix = this._viewMatrix.toInverseMatrix3().transposeTo();
this._normalMatrix = this._viewMatrix.toMatrix3();
this.updateGeodeticPosition();
this.slope = this._n.dot(this.eye.normal());
this.events.dispatch(this.events.viewchange, this);
}
updateGeodeticPosition() {
this._lonLat = this.planet.ellipsoid.cartesianToLonLat(this.eye);
if (Math.abs(this._lonLat.lat) <= mercator.MAX_LAT) {
this._lonLatMerc = this._lonLat.forwardMercator();
}
}
/**
* Sets altitude over the terrain.
* @public
* @param {number} alt - Altitude over the terrain.
*/
setAltitude(alt) {
var n = this.eye.normal();
var t = this._terrainPoint;
this.eye.x = n.x * alt + t.x;
this.eye.y = n.y * alt + t.y;
this.eye.z = n.z * alt + t.z;
this._terrainAltitude = alt;
this.update();
}
/**
* Gets altitude over the terrain.
* @public
*/
getAltitude() {
return this._terrainAltitude;
}
/**
* Moves camera to the geographical position.
* @public
* @param {og.LonLat} lonlat - Geographical position.
*/
setLonLat(lonlat, up) {
this._lonLat.set(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
var newEye = this.planet.ellipsoid.lonLatToCartesian(this._lonLat);
var rot = new Mat4().rotateBetweenVectors(newEye.normal(), this.eye.normal());
this.eye = newEye;
this._v = rot.mulVec3(this._v);
this._u = rot.mulVec3(this._u);
this._n = rot.mulVec3(this._n);
}
/**
* Returns camera geographical position.
* @public
* @returns {og.LonLat}
*/
getLonLat() {
return this._lonLat;
}
/**
* Returns camera height.
* @public
* @returns {number}
*/
getHeight() {
return this._lonLat.height;
}
/**
* Places camera to view to the geographical point.
* @public
* @param {og.LonLat} lonlat - New camera and camera view position.
* @param {og.math.Vector3} [up] - Camera UP vector. Default (0,1,0)
*/
viewLonLat(lonlat, up) {
this._lonLat.set(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
var el = this.planet.ellipsoid;
var newEye = el.lonLatToCartesian(this._lonLat);
var newLook = el.lonLatToCartesian(new LonLat(this._lonLat.lon, this._lonLat.lat, 0));
this.set(newEye, newLook, up || Vec3.UP);
}
/**
* Gets position by viewable extent.
* @public
* @param {og.Extent} extent - Viewable extent.
* @returns {og.math.Vector3}
*/
getExtentPosition(extent) {
var north = extent.getNorth();
var south = extent.getSouth();
var east = extent.getEast();
var west = extent.getWest();
if (west > east) {
east += 360;
}
var e = this.planet.ellipsoid;
var cart = new LonLat(east, north);
var northEast = e.lonLatToCartesian(cart);
cart.lat = south;
var southEast = e.lonLatToCartesian(cart);
cart.lon = west;
var southWest = e.lonLatToCartesian(cart);
cart.lat = north;
var northWest = e.lonLatToCartesian(cart);
var center = Vec3.sub(northEast, southWest).scale(0.5).addA(southWest);
var mag = center.length();
if (mag < 0.000001) {
cart.lon = (east + west) * 0.5;
cart.lat = (north + south) * 0.5;
center = e.lonLatToCartesian(cart);
}
northWest.subA(center);
southEast.subA(center);
northEast.subA(center);
southWest.subA(center);
var direction = center.normal();//ellipsoid.getSurfaceNormal(center).negate().normalize();
var right = direction.cross(Vec3.UP).normalize();
var up = right.cross(direction).normalize();
var height = Math.max(
Math.abs(up.dot(northWest)),
Math.abs(up.dot(southEast)),
Math.abs(up.dot(northEast)),
Math.abs(up.dot(southWest))
);
var width = Math.max(
Math.abs(right.dot(northWest)),
Math.abs(right.dot(southEast)),
Math.abs(right.dot(northEast)),
Math.abs(right.dot(southWest))
);
var tanPhi = Math.tan(this._viewAngle * math.RADIANS * 0.5);
var tanTheta = this._aspect * tanPhi;
var d = Math.max(width / tanTheta, height / tanPhi);
center.normalize();
center.scale(mag + d);
return center;
}
/**
* View current extent.
* @public
* @param {og.Extent} extent - Current extent.
*/
viewExtent(extent) {
this.stopFlying();
this.set(this.getExtentPosition(extent), Vec3.ZERO, Vec3.UP);
this.refresh();
}
/**
* Flies to the current extent.
* @public
* @param {og.Extent} extent - Current extent.
* @param {og.math.Vector3} [up] - Camera UP in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyExtent(extent, up, completeCallback, startCallback) {
this.flyCartesian(this.getExtentPosition(extent), Vec3.ZERO,
up, completeCallback, startCallback);
}
/**
* Flies to the cartesian coordinates.
* @public
* @param {og.math.Vector3} cartesian - Finish cartesian coordinates.
* @param {og.math.Vector3} [look] - Camera LOOK in the end of flying. Default - (0,0,0)
* @param {og.math.Vector3} [up] - Camera UP vector in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyCartesian(cartesian, look, up, completeCallback, startCallback) {
//???????
//if (this.eye.distance(cartesian) < 23000) {
// return;
//}
this.stopFlying();
this._completeCallback = completeCallback;
if (startCallback) {
startCallback.call(this);
}
var _look = look || Vec3.ZERO;
if (look instanceof LonLat) {
_look = this.planet.ellipsoid.lonLatToCartesian(look);
}
var ground_a = this.planet.ellipsoid.lonLatToCartesian(new LonLat(this._lonLat.lon, this._lonLat.lat));
var v_a = this._v,
n_a = this._n;
var lonlat_b = this.planet.ellipsoid.cartesianToLonLat(cartesian);
var up_b = up || Vec3.UP;
var ground_b = this.planet.ellipsoid.lonLatToCartesian(new LonLat(lonlat_b.lon, lonlat_b.lat, 0));
var eye_b = cartesian;
var n_b = Vec3.sub(eye_b, _look);
var u_b = up_b.cross(n_b);
n_b.normalize();
u_b.normalize();
var v_b = n_b.cross(u_b);
var an = ground_a.normal();
var bn = ground_b.normal();
var anbn = 1.0 - an.dot(bn);
var hM_a = math.SQRT_HALF * Math.sqrt((anbn) > 0.0 ? anbn : 0.0);
var maxHeight = 6639613;
var currMaxHeight = Math.max(this._lonLat.height, lonlat_b.height);
if (currMaxHeight > maxHeight) {
maxHeight = currMaxHeight;
}
var max_h = currMaxHeight + 2.5 * hM_a * (maxHeight - currMaxHeight);
var zero = Vec3.ZERO;
//camera path and orientations calculation
for (var i = 0; i <= this._numFrames; i++) {
var d = 1 - i / this._numFrames;
d = d * d * (3 - 2 * d);
d *= d;
//Error here
var g_i = ground_a.smerp(ground_b, d).normalize();
var ground_i = this.planet.getRayIntersectionEllipsoid(new Ray(zero, g_i));
var t = 1 - d;
var height_i = this._lonLat.height * d * d * d + max_h * 3 * d * d * t + max_h * 3 * d * t * t + lonlat_b.height * t * t * t;
var eye_i = ground_i.addA(g_i.scale(height_i));
var up_i = v_a.smerp(v_b, d);
var look_i = Vec3.add(eye_i, n_a.smerp(n_b, d).negateTo());
var n = new Vec3(eye_i.x - look_i.x, eye_i.y - look_i.y, eye_i.z - look_i.z);
var u = up_i.cross(n);
n.normalize();
u.normalize();
var v = n.cross(u);
this._framesArr[i] = {
"eye": eye_i,
"n": n,
"u": u,
"v": v
};
}
this._framesCounter = this._numFrames;
this._flying = true;
}
/**
* Flies to the geo coordiantes.
* @public
* @param {og.LonLat} lonlat - Finish coordinates.
* @param {og.math.Vector3} [look] - Camera LOOK in the end of flying. Default - (0,0,0)
* @param {og.math.Vector3} [up] - Camera UP vector in the end of flying. Default - (0,1,0)
* @param {cameraCallback} [completeCallback] - Callback that calls after flying when flying is finished.
* @param {cameraCallback} [startCallback] - Callback that calls befor the flying begins.
*/
flyLonLat(lonlat, look, up, completeCallback, startCallback) {
var _lonlat = new LonLat(lonlat.lon, lonlat.lat, lonlat.height || this._lonLat.height);
this.flyCartesian(this.planet.ellipsoid.lonLatToCartesian(_lonlat), look, up, completeCallback, startCallback);
}
/**
* Breaks the flight.
* @public
*/
stopFlying() {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
this._flying = false;
this._framesArr.length = 0;
this._framesArr = [];
this._framesCounter = -1;
}
/**
* Returns camera is flying.
* @public
* @returns {boolean}
*/
isFlying() {
return this._flying;
}
/**
* Rotates around planet to the left.
* @public
* @param {number} angle - Rotation angle.
* @param {boolean} [spin] - If its true rotates around globe spin.
*/
rotateLeft(angle, spin) {
this.rotateHorizontal(angle * math.RADIANS, spin ^ true, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the right.
* @public
* @param {number} angle - Rotation angle.
* @param {boolean} [spin] - If its true rotates around globe spin.
*/
rotateRight(angle, spin) {
this.rotateHorizontal(-angle * math.RADIANS, spin ^ true, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the north pole.
* @public
* @param {number} angle - Rotation angle.
*/
rotateUp(angle) {
this.rotateVertical(angle * math.RADIANS, Vec3.ZERO);
this.update();
}
/**
* Rotates around planet to the south pole.
* @public
* @param {number} angle - Rotation angle.
*/
rotateDown(angle) {
this.rotateVertical(-angle * math.RADIANS, Vec3.ZERO);
this.update();
}
/**
* Prepare camera to the frame. Used in render node frame function.
* @public
*/
prepareFrame() {
if (this._flying) {
var c = this._numFrames - this._framesCounter;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.eye = this._framesArr[c].eye;
this._u = this._framesArr[c].u;
this._v = this._framesArr[c].v;
this._n = this._framesArr[c].n;
this.update();
this._framesCounter--;
if (this._framesCounter < 0) {
this.stopFlying();
if (this._completeCallback) {
this._completeCallback();
this._completeCallback = null;
}
}
} else {
this._terrainAltitude = this._lonLat.height;
if (this._lonLat.height < 1000000) {
this._terrainAltitude = this._insideSegment.getTerrainPoint(this._terrainPoint, this.eye, this._insideSegmentPosition);
if (this._terrainAltitude < this.minAltitude) {
this.setAltitude(this.minAltitude);
}
}
}
}
};
export { PlanetCamera };

View File

@ -1,170 +0,0 @@
/**
* @module og/Clock
*/
'use strict';
import { Events } from './Events.js';
import * as jd from './astro/jd.js';
/**
* Class represents application timer that stores custom current julian datetime, and time speed multiplier.
* @class
* @param {Object} [params]: - Clock parameters:
* @param {number} [params.startDate=0.0] - Julian start date.
* @param {number} [params.endDate=0.0] - Julian end date.
* @param {number} [params.currentDate] - Julian current date. Default: current date.
* @param {number} [params.multiplier=1.0] - Time speed multiolier.
*/
class Clock {
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
constructor(params) {
params = params || {};
this._id = Clock._staticCounter++;
/**
* Clock name.
* @public
* @type {string}
*/
this.name = params.name || "";
/**
* Clock events.
* @public
* @type {Events}
*/
this.events = new Events([
"tick",
"end"
]);
/**
* Start julian date clock loop.
* @public
* @type {number}
*/
this.startDate = params.startDate || 0;
/**
* End julian date clock loop.
* @public
* @type {number}
*/
this.endDate = params.endDate || 0;
var currentDate = params.currentDate || jd.DateToUTC(new Date());
if (params.startDate && currentDate < params.startDate) {
currentDate = params.startDate;
}
if (params.endDate && currentDate > params.endDate) {
currentDate = params.endDate;
}
/**
* Current julian datetime.
* @public
* @type {number}
*/
this.currentDate = currentDate;
/**
* Timer speed multiplier.
* @public
* @type {number}
*/
this.multiplier = params.multiplier !== undefined ? params.multiplier : 1.0;
/**
* Animation frame delta time.
* @public
* @readonly
* @type {number}
*/
this.deltaTicks = 0;
/**
* Timer activity.
* @public
* @type {boolean}
*/
this.active = true;
}
/**
* Sets current clock datetime.
* @public
* @param {Object} date - JavaScript Date object.
*/
setDate(date) {
var d = jd.DateToUTC(date);
if (this.startDate && d < this.startDate) {
d = this.startDate;
}
if (this.endDate && d > this.endDate) {
d = this.endDate;
}
this.currentDate = d;
}
/**
* Returns current application date.
* @public
* @returns {Date} - Current date.
*/
getDate() {
return jd.UTCtoDate(this.currentDate);
}
reset() {
if (this.startDate) {
this.currentDate = this.startDate;
}
}
_tick(dt) {
this.deltaTicks = dt * this.multiplier;
if (this.active) {
var cd = jd.addMilliseconds(this.currentDate, this.deltaTicks);
if (this.multiplier > 0) {
if (this.endDate && cd > this.endDate) {
this.currentDate = this.startDate;
this.events.dispatch(this.events.end, this);
} else {
this.currentDate = cd;
}
} else {
if (this.startDate && cd < this.startDate) {
this.currentDate = this.endDate;
this.events.dispatch(this.events.end, this);
} else {
this.currentDate = cd;
}
}
this.events.dispatch(this.events.tick, this);
}
}
/**
* @public
* @param {Clock} clock - Clock instance to compare.
* @returns {boolean} - Returns true if a clock is the same instance.
*/
equal(clock) {
return this._id === clock._id;
}
};
export { Clock };

View File

@ -1,109 +0,0 @@
'use strict';
/**
* Console logging singleton object.
* @class
*/
export class Cons {
constructor() {
this._container = document.createElement("div");
this._container.classList.add("ogConsole");
this._container.style.display = "none";
if (document.body) {
document.body.appendChild(this._container);
}
this._visibility = false;
}
getVisibility() {
return this._visibility;
}
setVisibility(visibility) {
if (this._visibility != visibility) {
this._visibility = visibility;
if (this._visibility) {
this.show();
} else {
this.hide();
}
}
}
/**
* Show console panel.
* @public
*/
show() {
if (!this._container.parentNode) {
if (document.body) {
document.body.appendChild(this._container);
}
}
this._container.style.display = "block";
this._visibility = true;
}
/**
* Hide console panel.
* @public
*/
hide() {
this._container.style.display = "none";
this._visibility = false;
}
/**
* Adds error text in the console.
* @public
* @param {string} str - Error text.
*/
logErr(str) {
var d = document.createElement("div");
d.classList.add("ogConsole-text");
d.classList.add("ogConsole-error");
d.innerHTML = "error: " + str;
console.log(d.innerHTML);
this._container.appendChild(d);
this.show();
}
/**
* Adds warning text in the console.
* @public
* @param {string} str - Warning text.
*/
logWrn(str) {
var d = document.createElement("div");
d.classList.add("ogConsole-text");
d.classList.add("ogConsole-warning");
d.innerHTML = "warning: " + str;
console.log(d.innerHTML);
this._container.appendChild(d);
this.show();
}
/**
* Adds log text in the console.
* @public
* @param {string} str - Log text.
* @param {Object} [style] - HTML style.
*/
log(str, style) {
var d = document.createElement("div");
d.classList.add("ogConsole-text");
if (style) {
for (var s in style) {
d.style[s] = style[s];
}
}
d.innerHTML = str;
console.log(str);
this._container.appendChild(d);
this.show();
}
}
export const cons = new Cons();

View File

@ -1,138 +0,0 @@
/**
* @module og/control/BaseControl
*/
'use strict';
/**
* Base control class for implementing renderer controls.
* All other controls extend from this class.
* @class
* @param {Object} [options] - Control activation options:
* @param {Boolean} [options.autoActivated=true] - If true - calls initialize function after the renderer assigning.
*/
class BaseControl {
constructor(options) {
options = options || {};
/**
* Control initialized.
* @protected
* @type {Boolean}
*/
this._initialized = false;
/**
* Assigned renderer.
* @public
* @type {og.Renderer}
*/
this.renderer = null;
/**
* Auto activation flag.
* @public
* @type {Boolean}
*/
this.autoActivate = options.autoActivate != undefined ? options.autoActivate : true;
/**
* Control activity.
* @protected
* @type {Boolean}
*/
this._active = false;
}
/**
* Control initialization function have to be overriden.
* @public
* @virtual
*/
oninit() { }
/**
* Control renderer assigning function have to be overriden.
* @public
* @virtual
*/
onadd() { }
/**
* Control remove function have to be overriden.
* @public
* @virtual
*/
onremove() { }
/**
* Control activation function have to be overriden.
* @public
* @virtual
*/
onactivate() { }
/**
* Control deactivation function have to be overriden.
* @public
* @virtual
*/
ondeactivate() { }
/**
* Assign renderer to the control.
* @public
* @type {og.Renderer}
*/
addTo(renderer) {
if (renderer) {
this.renderer = renderer;
renderer.controls.push(this);
this.onadd && this.onadd();
if (this.autoActivate) {
this.oninit && this.oninit();
this._initialized = true;
this._active = true;
}
}
}
/**
* Assign renderer to the control.
* @public
*/
remove() {
this.onremove && this.onremove();
this.renderer = null;
this._active = false;
this._initialized = false;
}
/**
* Activate control.
* @public
*/
activate() {
this._active = true;
this.onactivate && this.onactivate();
}
/**
* Deactivate control.
* @public
*/
deactivate() {
this._active = false;
this.ondeactivate && this.ondeactivate();
}
/**
* Is control active.
* @public
*/
isActive() {
return this._active;
}
};
export { BaseControl };

View File

@ -1,199 +0,0 @@
/**
* @module og/control/EarthCoordinates
*/
'use strict';
import { BaseControl } from './BaseControl.js';
function dec2deg(base) {
var t, t2;
var degrees = base < 0 ? Math.ceil(base) : Math.floor(base);
var minutes = Math.floor(t = Math.abs((base - degrees)) * 60);
var seconds = Math.floor(t2 = (t - minutes) * 6000);
seconds = seconds / 100.00;
return (numToFixedString(degrees, 3) + "\u00B0" +
numToFixedString(minutes, 2) + "\u0027" +
numToFixedString(seconds.toFixed(2), 2) + "\u0022");
};
function numToFixedString(num, fixed) {
var dl = num.toString().split('.')[0].length;
var white = "&nbsp;";
for (var i = dl; i < fixed; i++) {
white += '&nbsp;&nbsp;';
}
return white + num.toString();
};
function toDecimal(ll) {
return ll.lat.toFixed(5) + ", " + ll.lon.toFixed(5);
};
function toDegrees(ll) {
return dec2deg(ll.lat) + ", " + dec2deg(ll.lon);
};
function toMercator(ll) {
var m = ll.forwardMercator();
return m.lat.toFixed(5) + ", " + m.lon.toFixed(5);
};
const DisplayTypesConverters = [
toDecimal,
toDegrees,
toMercator
];
/**
* Control displays mouse or screen center Earth coordinates.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Options:
* @param {Boolean} [options.center] - Earth coordiantes by screen center otherwise mouse pointer. False is default.
* @param {Boolean} [options.type] - Coordinates shown: 0 - is decimal degrees, 1 - degrees, 2 - mercator geodetic coordinates.
*/
class EarthCoordinates extends BaseControl {
constructor(options) {
super(options);
options = options || {};
/**
* Display type.
* @private
* @type {Boolean}
*/
this._displayType = options.type || 0;
/**
* Current coordinates type converter.
* @private
* @function
*/
this._converter = DisplayTypesConverters[0];
/**
* Display dom element.
* @private
* @type {Object}
*/
this._display = null;
/**
* Screen center or mouse pointer coordinates show flag.
* @private
* @type {Boolean}
*/
var pad = false;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
pad = true;
}
this._center = options.center || pad;
/**
* Current position.
* @public
* @type {og.math.Vector3}
*/
this.position = null;
}
oninit() {
this._display = document.createElement('div');
this._display.className = 'ogEarthCoordinatesControl';
var that = this;
function _refresh(el) {
if (that._displayType >= DisplayTypesConverters.length)
that._displayType = 0;
if (that._displayType == 0) {
el.style.width = "275px";
} else if (that._displayType == 1) {
el.style.width = "355px";
} else if (that._displayType == 2) {
el.style.width = "350px";
}
that._converter = DisplayTypesConverters[that._displayType];
that._showPosition();
};
this._display.onclick = function (e) {
that._displayType += 1;
_refresh(this);
};
this.renderer.div.appendChild(this._display);
_refresh(this._display);
let centerDiv = document.createElement('div');
centerDiv.className = 'ogCenterIcon';
centerDiv.innerHTML = '<svg width="12" height="12"><g><path stroke-width="1" stroke-opacity="1" d="M6 0L6 12M0 6L12 6" stroke="#009DFF"></path></g></svg>';
this.renderer.div.appendChild(centerDiv);
if (this._center) {
this.renderer.activeCamera.events.on("moveend", this._grabCoordinates, this);
centerDiv.style.display = "block";
} else {
this.renderer.events.on("mousemove", this._onMouseMove, this);
centerDiv.style.display = "none";
}
}
/**
* Sets coordinates capturing type.
* @public
* @param {Boolean} center - True - capture screen center, false - mouse pointer.
*/
setCenter(center) {
if (center != this._center) {
this._center = center;
if (center) {
this.renderer.events.off("mousemove", this._onMouseMove);
this.renderer.activeCamera.events.on("moveend", this._grabCoordinates, this);
centerDiv.style.display = "block";
} else {
this.renderer.events.off("draw", this._draw);
this.renderer.events.on("mousemove", this._onMouseMove, this);
centerDiv.style.display = "none";
}
}
}
_showPosition() {
if (this.position) {
this.position.height = ((this.position.height > 10000 || this.position.height < -10000) ? 0 : this.position.height);
this._display.innerHTML = "Lat/Lon: " + this._converter(this.position) + " h(km): " + (this.position.height > 0 ? "~" + (Math.round(this.position.height) / 1000).toFixed(2) : "-");
} else {
this._display.innerHTML = "Lat/Lon: " + "_____________________";
}
}
_grabCoordinates() {
var r = this.renderer;
var ts = r.events.touchState;
this.position = this.planet.getLonLatFromPixelTerrain(r.handler.getCenter());
this._showPosition();
}
_onMouseMove() {
var r = this.renderer;
var ms = r.events.mouseState;
if (!(ms.leftButtonDown || ms.rightButtonDown) &&
r.controlsBag.scaleRot <= 0 &&
!r.activeCamera._flying) {
this.position = this.planet.getLonLatFromPixelTerrain(ms, true);
this._showPosition();
}
}
};
export function earthCoordinates(options) {
return new EarthCoordinates(options);
};
export { EarthCoordinates };

View File

@ -1,62 +0,0 @@
/**
* @module og/control/GeoImageDragControl
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { BaseGeoImage } from '../layer/BaseGeoImage.js';
class GeoImageDragControl extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this._cornerIndex = -1;
this._catchCorner = false;
}
oninit() {
var that = this;
var p = this.planet;
p.events.on('layeradd', function (e) {
if (e instanceof BaseGeoImage) {
e.events.on('mousemove', function (ms) {
if (that._active) {
if (that._catchCorner) {
var corners = e.getCornersLonLat();
corners[that._cornerIndex] = p.getLonLatFromPixelTerrain(ms, true);
e.setCornersLonLat(corners);
} else {
that._cornerIndex = -1;
for (var i = 0; i < e._cornersWgs84.length; i++) {
var ground = p.getLonLatFromPixelTerrain(ms, true)
if (ground && p.ellipsoid.getGreatCircleDistance(e._cornersWgs84[i], ground) / p.getDistanceFromPixel(ms, true) <= 0.05) {
that._cornerIndex = i;
break;
}
}
}
}
});
e.events.on('ldown', function (ms) {
if (that._active && that._cornerIndex != -1) {
that._catchCorner = true;
p.renderer.controls[0]._active = false;
}
});
e.events.on('lup', function (ms) {
if (that._active) {
that._catchCorner = false;
p.renderer.controls[0]._active = true;
}
});
}
});
}
};
export { GeoImageDragControl };

View File

@ -1,117 +0,0 @@
/**
* @module og/control/KeyboardNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Planet camera keyboard navigation. Use W,S,A,D and left shift key for fly around a planet.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class KeyboardNavigation extends BaseControl {
constructor(options) {
options = options || {};
super(options);
}
oninit() {
this.renderer.events.on("keypress", input.KEY_W, this.onCameraMoveForward, this);
this.renderer.events.on("keypress", input.KEY_S, this.onCameraMoveBackward, this);
this.renderer.events.on("keypress", input.KEY_A, this.onCameraStrifeLeft, this);
this.renderer.events.on("keypress", input.KEY_D, this.onCameraStrifeRight, this);
this.renderer.events.on("keypress", input.KEY_UP, this.onCameraLookUp, this);
this.renderer.events.on("keypress", input.KEY_DOWN, this.onCameraLookDown, this);
this.renderer.events.on("keypress", input.KEY_LEFT, this.onCameraTurnLeft, this);
this.renderer.events.on("keypress", input.KEY_RIGHT, this.onCameraTurnRight, this);
this.renderer.events.on("keypress", input.KEY_Q, this.onCameraRollLeft, this);
this.renderer.events.on("keypress", input.KEY_E, this.onCameraRollRight, this);
}
onCameraMoveForward(event) {
var camera = this.renderer.activeCamera;
camera.slide(0, 0, -camera._lonLat.height / 30);
camera.update();
}
onCameraMoveBackward(event) {
var camera = this.renderer.activeCamera;
camera.slide(0, 0, camera._lonLat.height / 30);
camera.update();
}
onCameraStrifeLeft(event) {
var camera = this.renderer.activeCamera;
camera.slide(-camera._lonLat.height / 30, 0, 0);
camera.update();
}
onCameraStrifeRight(event) {
var camera = this.renderer.activeCamera;
camera.slide(camera._lonLat.height / 30, 0, 0);
camera.update();
}
onCameraLookUp(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.pitch(5);
} else {
cam.rotateVertical(cam._lonLat.height / 3000000 * math.RADIANS, Vec3.ZERO);
}
cam.update();
}
onCameraLookDown(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.pitch(-5);
} else {
cam.rotateVertical(-cam._lonLat.height / 3000000 * math.RADIANS, Vec3.ZERO);
}
cam.update();
}
onCameraTurnLeft(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.yaw(5);
} else {
cam.rotateHorizontal(cam._lonLat.height / 3000000 * math.RADIANS, false, Vec3.ZERO);
}
cam.update();
}
onCameraTurnRight(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.yaw(-5);
} else {
cam.rotateHorizontal(-cam._lonLat.height / 3000000 * math.RADIANS, false, Vec3.ZERO);
}
cam.update();
}
onCameraRollLeft(event) {
this.renderer.activeCamera.roll(-5);
this.renderer.activeCamera.update();
}
onCameraRollRight(event) {
this.renderer.activeCamera.roll(5);
this.renderer.activeCamera.update();
}
};
export function keyboardNavigation(options) {
return new KeyboardNavigation(options);
};
export { KeyboardNavigation };

View File

@ -1,159 +0,0 @@
/**
* @module og/control/LayerSwitcher
*/
'use strict';
import { BaseControl } from './BaseControl.js';
/**
* Simple(OpenLayers like)layer switcher, includes base layers, overlays, geo images etc. groups.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class LayerSwitcher extends BaseControl {
constructor(options) {
super(options);
this.dialog = null;
this.baseLayersDiv = null;
this.overlaysDiv = null;
this._id = LayerSwitcher.numSwitches++;
}
static get numSwitches() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set numSwitches(n) {
this._counter = n;
}
oninit() {
this.planet.events.on("layeradd", this.onLayerAdded, this);
this.planet.events.on("layerremove", this.onLayerRemoved, this);
this.createSwitcher();
this.createDialog();
}
onLayerAdded(layer) {
if (layer.displayInLayerSwitcher) {
if (layer.isBaseLayer()) {
this.addSwitcher("radio", layer, this.baseLayersDiv);
} else {
this.addSwitcher("checkbox", layer, this.overlaysDiv, this._id);
}
}
};
onLayerRemoved(layer) {
layer._removeCallback();
layer._removeCallback = null;
}
addSwitcher(type, obj, container, id) {
var lineDiv = document.createElement('div');
var that = this;
var center = document.createElement('div');
center.classList.add('ogViewExtentBtn');
center.onclick = function () {
that.planet.flyExtent(obj.getExtent());
};
var inp = document.createElement('input');
inp.type = type;
inp.name = "ogBaseLayerRadiosId" + (id || "");
inp.checked = obj.getVisibility();
inp.className = "ogLayerSwitcherInput";
inp.onclick = function () {
obj.setVisibility(this.checked);
};
obj.events && obj.events.on("visibilitychange", function (e) {
inp.checked = e.getVisibility();
});
var lbl = document.createElement('label');
lbl.className = "ogLayerSwitcherLabel";
lbl.innerHTML = (obj.name || obj.src || "noname") + "</br>";
obj._removeCallback = function () {
container.removeChild(lineDiv);
}
lineDiv.appendChild(center);
lineDiv.appendChild(inp);
lineDiv.appendChild(lbl);
container.appendChild(lineDiv);
}
createBaseLayersContainer() {
var layersDiv = document.createElement('div');
layersDiv.className = "layersDiv";
this.dialog.appendChild(layersDiv);
var baseLayersLbl = document.createElement('div');
baseLayersLbl.className = "layersDiv";
baseLayersLbl.innerHTML = "Base Layer";
layersDiv.appendChild(baseLayersLbl);
this.baseLayersDiv = document.createElement('div');
layersDiv.appendChild(this.baseLayersDiv);
}
createOverlaysContainer() {
var overlaysDiv = document.createElement('div');
overlaysDiv.className = "layersDiv";
this.dialog.appendChild(overlaysDiv);
var overlaysLbl = document.createElement('div');
overlaysLbl.className = "layersDiv";
overlaysLbl.innerHTML = "Overlays";
overlaysDiv.appendChild(overlaysLbl);
this.overlaysDiv = document.createElement('div');
overlaysDiv.appendChild(this.overlaysDiv);
}
createDialog() {
this.dialog = document.createElement('div');
this.dialog.id = "ogLayerSwitcherDialog";
this.dialog.className = "displayNone";
this.renderer.div.appendChild(this.dialog);
this.createBaseLayersContainer();
this.createOverlaysContainer();
if (this.planet) {
for (var i = 0; i < this.planet.layers.length; i++) {
this.onLayerAdded(this.planet.layers[i]);
}
}
}
createSwitcher() {
var button = document.createElement('div');
button.className = 'ogLayerSwitcherButton';
button.id = "ogLayerSwitcherButtonMaximize";
var that = this;
button.onclick = function (e) {
if (this.id === "ogLayerSwitcherButtonMaximize") {
this.id = "ogLayerSwitcherButtonMinimize";
that.dialog.className = "displayBlock";
} else {
this.id = "ogLayerSwitcherButtonMaximize";
that.dialog.className = "displayNone";
}
};
this.renderer.div.appendChild(button);
}
};
export { LayerSwitcher };

View File

@ -1,327 +0,0 @@
/**
* @module og/control/MouseNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Quat } from '../math/Quat.js';
import { Ray } from '../math/Ray.js';
import { Sphere } from '../bv/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Mouse planet camera dragging control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class MouseNavigation extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this.grabbedPoint = new Vec3();
this._eye0 = new Vec3();
this.pointOnEarth = new Vec3();
this.earthUp = new Vec3();
this.inertia = 0.007;
this.grabbedSpheroid = new Sphere();
this.planet = null;
this.qRot = new Quat();
this.scaleRot = 0;
this.distDiff = 0.33;
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
this._keyLock = new Key();
}
static getMovePointsFromPixelTerrain(cam, planet, stepsCount, delta, point, forward, dir) {
var steps = []
var eye = cam.eye.clone(),
n = cam._n.clone(),
u = cam._u.clone(),
v = cam._v.clone();
var a = planet.getCartesianFromPixelTerrain(point, true);
if (!dir) {
dir = Vec3.sub(a, cam.eye).normalize();
}
var d = a ? delta * cam.eye.distance(a) / stepsCount : 1000;
if (forward) {
d = -d;
} else {
d *= 2;
}
var scaled_n = n.scaleTo(d);
if (a && cam._lonLat.height > 9000 && cam.slope > 0.6) {
var grabbedSpheroid = new Sphere();
grabbedSpheroid.radius = a.length();
var rotArr = [],
eyeArr = []
var breaked = false;
for (var i = 0; i < stepsCount; i++) {
eye.addA(scaled_n);
var b = new Ray(eye, dir).hitSphere(grabbedSpheroid);
eyeArr[i] = eye.clone();
if (b) {
rotArr[i] = new Mat4().rotateBetweenVectors(a.normal(), b.normal());
} else {
breaked = true;
break;
}
}
if (!breaked) {
for (var i = 0; i < stepsCount; i++) {
var rot = rotArr[i];
steps[i] = {};
steps[i].eye = rot.mulVec3(eyeArr[i]);
steps[i].v = rot.mulVec3(v);
steps[i].u = rot.mulVec3(u);
steps[i].n = rot.mulVec3(n);
}
} else {
eye = cam.eye.clone();
for (var i = 0; i < stepsCount; i++) {
steps[i] = {};
steps[i].eye = eye.addA(scaled_n).clone();
steps[i].v = v;
steps[i].u = u;
steps[i].n = n;
}
}
} else {
for (var i = 0; i < stepsCount; i++) {
steps[i] = {};
steps[i].eye = eye.addA(dir.scaleTo(-d)).clone();
steps[i].v = v;
steps[i].u = u;
steps[i].n = n;
}
}
return steps;
}
onactivate() {
this.renderer.events.on("mousewheel", this.onMouseWheel, this);
this.renderer.events.on("lhold", this.onMouseLeftButtonDown, this);
this.renderer.events.on("rhold", this.onMouseRightButtonDown, this);
this.renderer.events.on("ldown", this.onMouseLeftButtonClick, this);
this.renderer.events.on("lup", this.onMouseLeftButtonUp, this);
this.renderer.events.on("rdown", this.onMouseRightButtonClick, this);
this.renderer.events.on("ldblclick", this.onMouseLeftButtonDoubleClick, this);
this.renderer.events.on("draw", this.onDraw, this);
}
ondeactivate() {
this.renderer.events.off("mousewheel", this.onMouseWheel);
this.renderer.events.off("lhold", this.onMouseLeftButtonDown);
this.renderer.events.off("rhold", this.onMouseRightButtonDown);
this.renderer.events.off("ldown", this.onMouseLeftButtonClick);
this.renderer.events.off("lup", this.onMouseLeftButtonUp);
this.renderer.events.off("rdown", this.onMouseRightButtonClick);
this.renderer.events.off("ldblclick", this.onMouseLeftButtonDoubleClick);
this.renderer.events.off("draw", this.onDraw);
};
onMouseWheel(event) {
if (this.stepIndex)
return;
this.planet.stopFlying();
this.stopRotation();
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
var ms = this.renderer.events.mouseState;
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff, ms, event.wheelDelta > 0, ms.direction);
}
oninit() {
this.activate();
}
onMouseLeftButtonDoubleClick() {
this.planet.stopFlying();
this.stopRotation();
var p = this.planet.getCartesianFromPixelTerrain(this.renderer.events.mouseState, true),
g = this.planet.ellipsoid.cartesianToLonLat(p);
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 2.0));
} else {
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 0.57));
}
}
onMouseLeftButtonClick() {
if (this._active) {
this.renderer.handler.canvas.classList.add("ogGrabbingPoiner");
this.grabbedPoint = this.planet.getCartesianFromMouseTerrain(true);
if (this.grabbedPoint) {
this._eye0.copy(this.renderer.activeCamera.eye);
this.grabbedSpheroid.radius = this.grabbedPoint.length();
this.stopRotation();
}
}
}
stopRotation() {
this.qRot.clear();
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
onMouseLeftButtonUp(e) {
this.renderer.handler.canvas.classList.remove("ogGrabbingPoiner");
}
onMouseLeftButtonDown(e) {
if (this._active) {
if (!this.grabbedPoint)
return;
this.planet.stopFlying();
if (this.renderer.events.mouseState.moving) {
var cam = this.renderer.activeCamera;
if (cam.slope > 0.28) {
var targetPoint = new Ray(cam.eye, e.direction).hitSphere(this.grabbedSpheroid);
if (targetPoint) {
this.scaleRot = 1;
this.qRot = Quat.getRotationBetweenVectors(targetPoint.normal(), this.grabbedPoint.normal());
var rot = this.qRot;
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
} else {
var p0 = this.grabbedPoint,
p1 = Vec3.add(p0, cam._u),
p2 = Vec3.add(p0, p0.normal());
var px = new Vec3();
if (new Ray(cam.eye, e.direction).hitPlane(p0, p1, p2, px) === Ray.INSIDE) {
cam.eye = this._eye0.addA(px.subA(p0).negate());
cam.update();
}
}
} else {
this.scaleRot = 0;
}
}
}
onMouseRightButtonClick(e) {
this.stopRotation();
this.planet.stopFlying();
this.pointOnEarth = this.planet.getCartesianFromPixelTerrain({ x: e.x, y: e.y }, true);
if (this.pointOnEarth) {
this.earthUp = this.pointOnEarth.normal();
}
};
onMouseRightButtonDown(e) {
var cam = this.renderer.activeCamera;
if (this.pointOnEarth && this.renderer.events.mouseState.moving) {
this.renderer.controlsBag.scaleRot = 1;
var l = 0.5 / cam.eye.distance(this.pointOnEarth) * cam._lonLat.height * math.RADIANS;
if (l > 0.007) l = 0.007;
cam.rotateHorizontal(l * (e.x - e.prev_x), false, this.pointOnEarth, this.earthUp);
cam.rotateVertical(l * (e.y - e.prev_y), this.pointOnEarth);
cam.update();
}
}
onDraw(e) {
if (this._active) {
var r = this.renderer;
var cam = r.activeCamera;
var prevEye = cam.eye.clone();
if (this.stepIndex) {
r.controlsBag.scaleRot = 1;
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
} else {
if (this._deactivate) {
this._deactivate = false;
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
if (r.events.mouseState.leftButtonDown || !this.scaleRot)
return;
this.scaleRot -= this.inertia;
if (this.scaleRot <= 0) {
this.scaleRot = 0;
} else {
r.controlsBag.scaleRot = this.scaleRot;
var rot = this.qRot.slerp(Quat.IDENTITY, 1 - this.scaleRot * this.scaleRot * this.scaleRot).normalize();
if (!(rot.x || rot.y || rot.z)) {
this.scaleRot = 0;
}
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
if (cam.eye.distance(prevEye) / cam._terrainAltitude > 0.01) {
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
} else {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
}
};
export { MouseNavigation };

View File

@ -1,39 +0,0 @@
/**
* @module og/control/ShowFps
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { print2d } from '../utils/Shared.js';
/**
* Frame per second(FPS) display control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class ShowFps extends BaseControl {
constructor(options) {
super(options);
}
oninit() {
var d = document.createElement('div');
d.className = 'defaultText ';
d.id = "ogShowFpsControl";
document.body.appendChild(d);
this.renderer.events.on("draw", this._draw, this);
}
_draw() {
print2d("ogShowFpsControl", (1000.0 / this.renderer.handler.deltaTime).toFixed(1), this.renderer.handler.canvas.clientWidth - 60, 0);
}
};
export function showFps(options) {
return new ShowFps(options);
};
export { ShowFps };

View File

@ -1,110 +0,0 @@
/**
* @module og/control/SimpleNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
/**
* Simple keyboard camera navigation with W,S,A,D and shift keys to fly around the scene.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class SimpleNavigation extends BaseControl {
constructor(options) {
options = options || {};
super(options);
this.camera = null;
this.speed = options.speed || 1.0;
}
oninit() {
this.camera = this.renderer.activeCamera;
this.renderer.events.on("keypress", input.KEY_W, this.onCameraMoveForward, this);
this.renderer.events.on("keypress", input.KEY_S, this.onCameraMoveBackward, this);
this.renderer.events.on("keypress", input.KEY_A, this.onCameraStrifeLeft, this);
this.renderer.events.on("keypress", input.KEY_D, this.onCameraStrifeRight, this);
this.renderer.events.on("keypress", input.KEY_UP, this.onCameraLookUp, this);
this.renderer.events.on("keypress", input.KEY_DOWN, this.onCameraLookDown, this);
this.renderer.events.on("keypress", input.KEY_LEFT, this.onCameraTurnLeft, this);
this.renderer.events.on("keypress", input.KEY_RIGHT, this.onCameraTurnRight, this);
this.renderer.events.on("keypress", input.KEY_Q, this.onCameraRollLeft, this);
this.renderer.events.on("keypress", input.KEY_E, this.onCameraRollRight, this);
}
onCameraMoveForward(event) {
var camera = this.camera;
camera.slide(0, 0, -this.speed);
camera.update();
}
onCameraMoveBackward(event) {
var camera = this.camera;
camera.slide(0, 0, this.speed);
camera.update();
}
onCameraStrifeLeft(event) {
var camera = this.camera;
camera.slide(-this.speed, 0, 0);
camera.update();
}
onCameraStrifeRight(event) {
var camera = this.camera;
camera.slide(this.speed, 0, 0);
camera.update();
}
onCameraLookUp(event) {
var cam = this.camera;
cam.pitch(0.5);
cam.update();
}
onCameraLookDown(event) {
var cam = this.camera;
cam.pitch(-0.5);
cam.update();
}
onCameraTurnLeft(event) {
var cam = this.camera;
cam.yaw(0.5);
cam.update();
}
onCameraTurnRight(event) {
var cam = this.camera;
cam.yaw(-0.5);
cam.update();
}
onCameraRollLeft(event) {
var cam = this.camera;
cam.roll(-0.5);
cam.update();
}
onCameraRollRight(event) {
var cam = this.camera;
cam.roll(0.5);
cam.update();
}
};
/**
* Creates simple navigation control instance.
*/
export function simpleNavigation(options) {
return new SimpleNavigation(options);
};
export { SimpleNavigation };

View File

@ -1,153 +0,0 @@
/**
* @module og/control/Sun
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { getSunPosition } from '../astro/earth.js';
import { input } from '../input/input.js';
import { LightSource } from '../light/LightSource.js';
import { Quat } from '../math/Quat.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Real Sun geocentric position control that place the Sun on the right place by the Earth.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class Sun extends BaseControl {
constructor(options) {
super(options);
options = options || {};
/**
* Earth planet node.
* @public
* @type {og.scene.Planet}
*/
this.planet = null;
/**
* Sunlight position placed in the camera eye.
* @private
* @type {boolean}
*/
//this._isCameraSunlight = false;
this.offsetVertical = options.offsetVertical || -5000000;
this.offsetHorizontal = options.offsetHorizontal || 5000000;
/**
* Light source.
* @public
* @type {og.LightSource}
*/
this.sunlight = null;
/**
* Current frame handler clock date and time.
* @private
* @type {Number}
*/
this._currDate = 0;
/**
* Previous frame handler clock date and time.
* @private
* @type {Number}
*/
this._prevDate = 0;
this._clockPtr = null;
this._lightOn = false;
this._stopped = options.stopped || false;
}
oninit() {
this.planet.lightEnabled = true;
//sunlight initialization
this.sunlight = new LightSource("Sun", {
'ambient': new Vec3(0.15, 0.15, 0.25),
'diffuse': new Vec3(0.9, 0.9, 0.8),
'specular': new Vec3(0.1, 0.1, 0.06),
'shininess': 110
});
this.sunlight.addTo(this.planet);
var that = this;
this.renderer.events.on("draw", this._draw, this);
this.renderer.events.on("charkeypress", input.KEY_L, function () {
that.planet.lightEnabled = !that.planet.lightEnabled;
});
if (!this._clockPtr)
this._clockPtr = this.renderer.handler.defaultClock;
}
stop() {
this._stopped = true;
}
onactivate() {
this._stopped = false;
}
bindClock(clock) {
this._clockPtr = clock;
}
_draw() {
if (!this._stopped) {
this._currDate = this._clockPtr.currentDate;
var cam = this.renderer.activeCamera;
if (cam.getHeight() < 4650000 || !this._active) {
this._lightOn = true;
this._f = 1;
var n = cam.eye.normal();
var tu = Vec3.proj_b_to_plane(cam._v, n, cam._v).normalize().scale(this.offsetVertical);
var tr = Vec3.proj_b_to_plane(cam._u, n, cam._u).normalize().scale(this.offsetHorizontal);
var d = tu.add(tr);
var pos = cam.eye.add(d);
if (this._k > 0) {
this._k -= 0.01;
var rot = Quat.getRotationBetweenVectors(this.sunlight._position.normal(), pos.normal());
var r = rot.slerp(Quat.IDENTITY, this._k).normalize();
this.sunlight.setPosition(r.mulVec3(this.sunlight._position));
} else {
this.sunlight.setPosition(pos);
}
} else {
this._k = 1;
if (this._f > 0) {
this._f -= 0.01;
var rot = Quat.getRotationBetweenVectors(this.sunlight._position.normal(), getSunPosition(this._currDate).normal());
var r = rot.slerp(Quat.IDENTITY, this._f).normalize();
this.sunlight.setPosition(r.mulVec3(this.sunlight._position));
} else {
if (Math.abs(this._currDate - this._prevDate) > 0.00034 && this._active || this._lightOn) {
this._lightOn = false;
this._prevDate = this._currDate;
this.sunlight.setPosition(getSunPosition(this._currDate));
this._f = 0;
}
}
}
}
}
};
export function sun(options) {
return Sun(options);
};
export { Sun };

View File

@ -1,35 +0,0 @@
/**
* @module og/control/ToggleWireframe
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
/**
* Planet GL draw mode(TRIANGLE_STRIP/LINE_STRING) changer.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class ToggleWireframe extends BaseControl {
constructor(options) {
super(options);
}
oninit() {
this.renderer.events.on("charkeypress", input.KEY_X, this.toogleWireframe, this);
}
toogleWireframe(e) {
if (this.planet.drawMode === this.renderer.handler.gl.LINE_STRIP) {
this.planet.setDrawMode(this.renderer.handler.gl.TRIANGLE_STRIP);
} else {
this.planet.setDrawMode(this.renderer.handler.gl.LINE_STRIP);
}
}
};
export { ToggleWireframe };

View File

@ -1,310 +0,0 @@
/**
* @module og/control/TouchNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Quat } from '../math/Quat.js';
import { Ray } from '../math/Ray.js';
import { Sphere } from '../bv/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Touch pad planet camera dragging control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class TouchNavigation extends BaseControl {
constructor(options) {
super(options);
this.grabbedPoint = new Vec3();
this.inertia = 0.007;
this.grabbedSpheroid = new Sphere();
this.planet = null;
this.qRot = new Quat();
this.scaleRot = 0;
this.rot = 1;
this._eye0 = new Vec3();
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
var Touch = function () {
this.x = 0;
this.y = 0;
this.prev_x = 0;
this.prev_y = 0;
this.grabbedPoint = new Vec3();
this.grabbedSpheroid = new Sphere();
this.dX = function () { return this.x - this.prev_x; };
this.dY = function () { return this.y - this.prev_y; };
};
this.pointOnEarth = null;
this.earthUp = null;
this.touches = [new Touch(), new Touch()];
this._keyLock = new Key();
}
oninit() {
this.renderer.events.on("touchstart", this.onTouchStart, this);
this.renderer.events.on("touchend", this.onTouchEnd, this);
this.renderer.events.on("doubletouch", this.onDoubleTouch, this);
this.renderer.events.on("touchcancel", this.onTouchCancel, this);
this.renderer.events.on("touchmove", this.onTouchMove, this);
this.renderer.events.on("draw", this.onDraw, this);
}
onTouchStart(e) {
this._touching = true;
if (e.sys.touches.length === 2) {
var t0 = this.touches[0],
t1 = this.touches[1];
t0.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t0.prev_x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.prev_y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t0.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t0, true);
t1.x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
t1.prev_x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.prev_y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
t1.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t1, true);
//this.planet._viewChanged = true;
this.pointOnEarth = this.planet.getCartesianFromPixelTerrain(this.renderer.handler.getCenter(), true);
if (this.pointOnEarth) {
this.earthUp = this.pointOnEarth.normal();
}
if (t0.grabbedPoint && t1.grabbedPoint) {
t0.grabbedSpheroid.radius = t0.grabbedPoint.length();
t1.grabbedSpheroid.radius = t1.grabbedPoint.length();
this.stopRotation();
}
} else if (e.sys.touches.length === 1) {
this._startTouchOne(e);
}
}
_startTouchOne(e) {
var t = this.touches[0];
t.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t.prev_x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.prev_y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t, true);
this._eye0.copy(this.renderer.activeCamera.eye);
if (t.grabbedPoint) {
t.grabbedSpheroid.radius = t.grabbedPoint.length();
this.stopRotation();
}
}
stopRotation() {
this.qRot.clear();
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
onDoubleTouch(e) {
if (this.stepIndex)
return;
this.planet.stopFlying();
this.stopRotation();
var p = this.planet.getCartesianFromPixelTerrain(this.touches[0], true),
g = this.planet.ellipsoid.cartesianToLonLat(p);
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 0.57));
}
onTouchEnd(e) {
if (e.sys.touches.length === 0)
this._touching = false;
if (e.sys.touches.length === 1) {
this._startTouchOne(e);
}
if (Math.abs(this.touches[0].x - this.touches[0].prev_x) < 3 &&
Math.abs(this.touches[0].y - this.touches[0].prev_y) < 3)
this.scaleRot = 0;
}
onTouchCancel(e) {
}
onTouchMove(e) {
var cam = this.renderer.activeCamera;
if (e.sys.touches.length === 2) {
this.renderer.controlsBag.scaleRot = 1;
var t0 = this.touches[0],
t1 = this.touches[1];
if (!t0.grabbedPoint || !t1.grabbedPoint)
return;
this.planet.stopFlying();
t0.prev_x = t0.x;
t0.prev_y = t0.y;
t0.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t1.prev_x = t1.x;
t1.prev_y = t1.y;
t1.x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
//var center_x = Math.round(t0.x + (t1.x - t0.x) * 0.5);
//var center_y = Math.round(t0.y + (t1.y - t0.y) * 0.5);
//var dirC = cam.unproject(center_x, center_y);
//var targetPointC = this.planet.getCartesianFromPixelTerrain(new og.math.Pixel(center_x, center_y));
//var dir0 = cam.unproject(t0.x, t0.y);
//var targetPoint0 = new og.math.Ray(cam.eye, dir0).hitSphere(t0.grabbedSpheroid);
//var dir1 = cam.unproject(t1.x, t1.y);
//var targetPoint1 = new og.math.Ray(cam.eye, dir1).hitSphere(t1.grabbedSpheroid);
//print2d("t1", center_x + "," + center_y, 100, 100);
//print2d("t2", targetPointC.x + "," + targetPointC.y + "," + targetPointC.z, 100, 120);
if (t0.dY() > 0 && t1.dY() > 0 || t0.dY() < 0 && t1.dY() < 0 ||
t0.dX() > 0 && t1.dX() > 0 || t0.dX() < 0 && t1.dX() < 0) {
var l = 0.5 / cam.eye.distance(this.pointOnEarth) * cam._lonLat.height * math.RADIANS;
if (l > 0.007) l = 0.007;
cam.rotateHorizontal(l * t0.dX(), false, this.pointOnEarth, this.earthUp);
cam.rotateVertical(l * t0.dY(), this.pointOnEarth);
cam.update();
}
this.scaleRot = 0;
} else if (e.sys.touches.length === 1) {
var t = this.touches[0];
t.prev_x = t.x;
t.prev_y = t.y;
t.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
if (!t.grabbedPoint)
return;
this.planet.stopFlying();
var direction = cam.unproject(t.x, t.y);
var targetPoint = new Ray(cam.eye, direction).hitSphere(t.grabbedSpheroid);
if (targetPoint) {
if (cam._n.dot(cam.eye.normal()) > 0.28) {
this.qRot = Quat.getRotationBetweenVectors(targetPoint.normal(), t.grabbedPoint.normal());
var rot = this.qRot;
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
this.scaleRot = 1;
} else {
var p0 = t.grabbedPoint,
p1 = Vec3.add(p0, cam._u),
p2 = Vec3.add(p0, p0.normal());
var dir = cam.unproject(t.x, t.y);
var px = new Vec3();
if (new Ray(cam.eye, dir).hitPlane(p0, p1, p2, px) === Ray.INSIDE) {
cam.eye = this._eye0.addA(px.subA(p0).negate());
cam.update();
this.scaleRot = 0;
}
}
}
}
};
onDraw(e) {
this.renderer.controlsBag.scaleRot = this.scaleRot;
if (this._touching)
return;
var r = this.renderer;
var cam = r.activeCamera;
var prevEye = cam.eye.clone();
if (this.stepIndex) {
r.controlsBag.scaleRot = 1;
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
var cam = this.renderer.activeCamera;
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
}
if (r.events.mouseState.leftButtonDown || !this.scaleRot)
return;
this.scaleRot -= this.inertia;
if (this.scaleRot <= 0)
this.scaleRot = 0;
else {
r.controlsBag.scaleRot = this.scaleRot;
var cam = r.activeCamera;
var rot = this.qRot.slerp(Quat.IDENTITY, 1 - this.scaleRot * this.scaleRot * this.scaleRot).normalize();
if (!(rot.x || rot.y || rot.z)) {
this.scaleRot = 0;
}
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
if (cam.eye.distance(prevEye) / cam._terrainAltitude > 0.01) {
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
} else {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
};
export { TouchNavigation };

View File

@ -1,122 +0,0 @@
/**
* @module og/control/ZoomControl
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { Key } from '../Lock.js';
import { MouseNavigation } from './MouseNavigation.js';
/**
* Planet zoom buttons control.
* @class
* @extends {og.control.BaseControl}
* @params {Object} [options] - Control options.
*/
class ZoomControl extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this.distDiff = 0.33;
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
this._keyLock = new Key();
this.planet = null;
}
oninit() {
var zoomDiv = document.createElement('div'),
btnZoomIn = document.createElement('button'),
btnZoomOut = document.createElement('button');
zoomDiv.className = 'ogZoomControl';
btnZoomIn.className = 'ogZoomButton ogZoomIn';
btnZoomOut.className = 'ogZoomButton ogZoomOut';
zoomDiv.appendChild(btnZoomIn);
zoomDiv.appendChild(btnZoomOut);
this.renderer.div.appendChild(zoomDiv);
var that = this;
btnZoomIn.onclick = function (e) {
that.zoomIn();
};
btnZoomOut.onclick = function (e) {
that.zoomOut();
};
this.renderer.events.on("draw", this._draw, this);
}
/**
* Planet zoom in.
* @public
*/
zoomIn() {
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff * 1.7, this.renderer.getCenter(), true, this.renderer.activeCamera._n.negateTo());
}
/**
* Planet zoom out.
* @public
*/
zoomOut() {
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff * 2, this.renderer.getCenter(), false, this.renderer.activeCamera._n.negateTo());
}
_draw(e) {
var cam = this.renderer.activeCamera;
if (this.stepIndex) {
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
} else if (!cam._flying) {
if (this._deactivate) {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
this._deactivate = false;
}
}
}
};
export function zoomControl(options) {
return new ZoomControl(options);
};
export { ZoomControl };

View File

@ -1,138 +0,0 @@
/**
* @module og/control/BaseControl
*/
'use strict';
/**
* Base control class for implementing renderer controls.
* All other controls extend from this class.
* @class
* @param {Object} [options] - Control activation options:
* @param {Boolean} [options.autoActivated=true] - If true - calls initialize function after the renderer assigning.
*/
class BaseControl {
constructor(options) {
options = options || {};
/**
* Control initialized.
* @protected
* @type {Boolean}
*/
this._initialized = false;
/**
* Assigned renderer.
* @public
* @type {og.Renderer}
*/
this.renderer = null;
/**
* Auto activation flag.
* @public
* @type {Boolean}
*/
this.autoActivate = options.autoActivate != undefined ? options.autoActivate : true;
/**
* Control activity.
* @protected
* @type {Boolean}
*/
this._active = false;
}
/**
* Control initialization function have to be overriden.
* @public
* @virtual
*/
oninit() { }
/**
* Control renderer assigning function have to be overriden.
* @public
* @virtual
*/
onadd() { }
/**
* Control remove function have to be overriden.
* @public
* @virtual
*/
onremove() { }
/**
* Control activation function have to be overriden.
* @public
* @virtual
*/
onactivate() { }
/**
* Control deactivation function have to be overriden.
* @public
* @virtual
*/
ondeactivate() { }
/**
* Assign renderer to the control.
* @public
* @type {og.Renderer}
*/
addTo(renderer) {
if (renderer) {
this.renderer = renderer;
renderer.controls.push(this);
this.onadd && this.onadd();
if (this.autoActivate) {
this.oninit && this.oninit();
this._initialized = true;
this._active = true;
}
}
}
/**
* Assign renderer to the control.
* @public
*/
remove() {
this.onremove && this.onremove();
this.renderer = null;
this._active = false;
this._initialized = false;
}
/**
* Activate control.
* @public
*/
activate() {
this._active = true;
this.onactivate && this.onactivate();
}
/**
* Deactivate control.
* @public
*/
deactivate() {
this._active = false;
this.ondeactivate && this.ondeactivate();
}
/**
* Is control active.
* @public
*/
isActive() {
return this._active;
}
};
export { BaseControl };

View File

@ -1,199 +0,0 @@
/**
* @module og/control/EarthCoordinates
*/
'use strict';
import { BaseControl } from './BaseControl.js';
function dec2deg(base) {
var t, t2;
var degrees = base < 0 ? Math.ceil(base) : Math.floor(base);
var minutes = Math.floor(t = Math.abs((base - degrees)) * 60);
var seconds = Math.floor(t2 = (t - minutes) * 6000);
seconds = seconds / 100.00;
return (numToFixedString(degrees, 3) + "\u00B0" +
numToFixedString(minutes, 2) + "\u0027" +
numToFixedString(seconds.toFixed(2), 2) + "\u0022");
};
function numToFixedString(num, fixed) {
var dl = num.toString().split('.')[0].length;
var white = "&nbsp;";
for (var i = dl; i < fixed; i++) {
white += '&nbsp;&nbsp;';
}
return white + num.toString();
};
function toDecimal(ll) {
return ll.lat.toFixed(5) + ", " + ll.lon.toFixed(5);
};
function toDegrees(ll) {
return dec2deg(ll.lat) + ", " + dec2deg(ll.lon);
};
function toMercator(ll) {
var m = ll.forwardMercator();
return m.lat.toFixed(5) + ", " + m.lon.toFixed(5);
};
const DisplayTypesConverters = [
toDecimal,
toDegrees,
toMercator
];
/**
* Control displays mouse or screen center Earth coordinates.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Options:
* @param {Boolean} [options.center] - Earth coordiantes by screen center otherwise mouse pointer. False is default.
* @param {Boolean} [options.type] - Coordinates shown: 0 - is decimal degrees, 1 - degrees, 2 - mercator geodetic coordinates.
*/
class EarthCoordinates extends BaseControl {
constructor(options) {
super(options);
options = options || {};
/**
* Display type.
* @private
* @type {Boolean}
*/
this._displayType = options.type || 0;
/**
* Current coordinates type converter.
* @private
* @function
*/
this._converter = DisplayTypesConverters[0];
/**
* Display dom element.
* @private
* @type {Object}
*/
this._display = null;
/**
* Screen center or mouse pointer coordinates show flag.
* @private
* @type {Boolean}
*/
var pad = false;
if (/Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent)) {
pad = true;
}
this._center = options.center || pad;
/**
* Current position.
* @public
* @type {og.math.Vector3}
*/
this.position = null;
}
oninit() {
this._display = document.createElement('div');
this._display.className = 'ogEarthCoordinatesControl';
var that = this;
function _refresh(el) {
if (that._displayType >= DisplayTypesConverters.length)
that._displayType = 0;
if (that._displayType == 0) {
el.style.width = "275px";
} else if (that._displayType == 1) {
el.style.width = "355px";
} else if (that._displayType == 2) {
el.style.width = "350px";
}
that._converter = DisplayTypesConverters[that._displayType];
that._showPosition();
};
this._display.onclick = function (e) {
that._displayType += 1;
_refresh(this);
};
this.renderer.div.appendChild(this._display);
_refresh(this._display);
let centerDiv = document.createElement('div');
centerDiv.className = 'ogCenterIcon';
centerDiv.innerHTML = '<svg width="12" height="12"><g><path stroke-width="1" stroke-opacity="1" d="M6 0L6 12M0 6L12 6" stroke="#009DFF"></path></g></svg>';
this.renderer.div.appendChild(centerDiv);
if (this._center) {
this.renderer.activeCamera.events.on("moveend", this._grabCoordinates, this);
centerDiv.style.display = "block";
} else {
this.renderer.events.on("mousemove", this._onMouseMove, this);
centerDiv.style.display = "none";
}
}
/**
* Sets coordinates capturing type.
* @public
* @param {Boolean} center - True - capture screen center, false - mouse pointer.
*/
setCenter(center) {
if (center != this._center) {
this._center = center;
if (center) {
this.renderer.events.off("mousemove", this._onMouseMove);
this.renderer.activeCamera.events.on("moveend", this._grabCoordinates, this);
centerDiv.style.display = "block";
} else {
this.renderer.events.off("draw", this._draw);
this.renderer.events.on("mousemove", this._onMouseMove, this);
centerDiv.style.display = "none";
}
}
}
_showPosition() {
if (this.position) {
this.position.height = ((this.position.height > 10000 || this.position.height < -10000) ? 0 : this.position.height);
this._display.innerHTML = "Lat/Lon: " + this._converter(this.position) + " h(km): " + (this.position.height > 0 ? "~" + (Math.round(this.position.height) / 1000).toFixed(2) : "-");
} else {
this._display.innerHTML = "Lat/Lon: " + "_____________________";
}
}
_grabCoordinates() {
var r = this.renderer;
var ts = r.events.touchState;
this.position = this.planet.getLonLatFromPixelTerrain(r.handler.getCenter());
this._showPosition();
}
_onMouseMove() {
var r = this.renderer;
var ms = r.events.mouseState;
if (!(ms.leftButtonDown || ms.rightButtonDown) &&
r.controlsBag.scaleRot <= 0 &&
!r.activeCamera._flying) {
this.position = this.planet.getLonLatFromPixelTerrain(ms, true);
this._showPosition();
}
}
};
export function earthCoordinates(options) {
return new EarthCoordinates(options);
};
export { EarthCoordinates };

View File

@ -1,62 +0,0 @@
/**
* @module og/control/GeoImageDragControl
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { BaseGeoImage } from '../layer/BaseGeoImage.js';
class GeoImageDragControl extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this._cornerIndex = -1;
this._catchCorner = false;
}
oninit() {
var that = this;
var p = this.planet;
p.events.on('layeradd', function (e) {
if (e instanceof BaseGeoImage) {
e.events.on('mousemove', function (ms) {
if (that._active) {
if (that._catchCorner) {
var corners = e.getCornersLonLat();
corners[that._cornerIndex] = p.getLonLatFromPixelTerrain(ms, true);
e.setCornersLonLat(corners);
} else {
that._cornerIndex = -1;
for (var i = 0; i < e._cornersWgs84.length; i++) {
var ground = p.getLonLatFromPixelTerrain(ms, true)
if (ground && p.ellipsoid.getGreatCircleDistance(e._cornersWgs84[i], ground) / p.getDistanceFromPixel(ms, true) <= 0.05) {
that._cornerIndex = i;
break;
}
}
}
}
});
e.events.on('ldown', function (ms) {
if (that._active && that._cornerIndex != -1) {
that._catchCorner = true;
p.renderer.controls[0]._active = false;
}
});
e.events.on('lup', function (ms) {
if (that._active) {
that._catchCorner = false;
p.renderer.controls[0]._active = true;
}
});
}
});
}
};
export { GeoImageDragControl };

View File

@ -1,117 +0,0 @@
/**
* @module og/control/KeyboardNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Planet camera keyboard navigation. Use W,S,A,D and left shift key for fly around a planet.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class KeyboardNavigation extends BaseControl {
constructor(options) {
options = options || {};
super(options);
}
oninit() {
this.renderer.events.on("keypress", input.KEY_W, this.onCameraMoveForward, this);
this.renderer.events.on("keypress", input.KEY_S, this.onCameraMoveBackward, this);
this.renderer.events.on("keypress", input.KEY_A, this.onCameraStrifeLeft, this);
this.renderer.events.on("keypress", input.KEY_D, this.onCameraStrifeRight, this);
this.renderer.events.on("keypress", input.KEY_UP, this.onCameraLookUp, this);
this.renderer.events.on("keypress", input.KEY_DOWN, this.onCameraLookDown, this);
this.renderer.events.on("keypress", input.KEY_LEFT, this.onCameraTurnLeft, this);
this.renderer.events.on("keypress", input.KEY_RIGHT, this.onCameraTurnRight, this);
this.renderer.events.on("keypress", input.KEY_Q, this.onCameraRollLeft, this);
this.renderer.events.on("keypress", input.KEY_E, this.onCameraRollRight, this);
}
onCameraMoveForward(event) {
var camera = this.renderer.activeCamera;
camera.slide(0, 0, -camera._lonLat.height / 30);
camera.update();
}
onCameraMoveBackward(event) {
var camera = this.renderer.activeCamera;
camera.slide(0, 0, camera._lonLat.height / 30);
camera.update();
}
onCameraStrifeLeft(event) {
var camera = this.renderer.activeCamera;
camera.slide(-camera._lonLat.height / 30, 0, 0);
camera.update();
}
onCameraStrifeRight(event) {
var camera = this.renderer.activeCamera;
camera.slide(camera._lonLat.height / 30, 0, 0);
camera.update();
}
onCameraLookUp(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.pitch(5);
} else {
cam.rotateVertical(cam._lonLat.height / 3000000 * math.RADIANS, Vec3.ZERO);
}
cam.update();
}
onCameraLookDown(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.pitch(-5);
} else {
cam.rotateVertical(-cam._lonLat.height / 3000000 * math.RADIANS, Vec3.ZERO);
}
cam.update();
}
onCameraTurnLeft(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.yaw(5);
} else {
cam.rotateHorizontal(cam._lonLat.height / 3000000 * math.RADIANS, false, Vec3.ZERO);
}
cam.update();
}
onCameraTurnRight(event) {
var cam = this.renderer.activeCamera;
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
cam.yaw(-5);
} else {
cam.rotateHorizontal(-cam._lonLat.height / 3000000 * math.RADIANS, false, Vec3.ZERO);
}
cam.update();
}
onCameraRollLeft(event) {
this.renderer.activeCamera.roll(-5);
this.renderer.activeCamera.update();
}
onCameraRollRight(event) {
this.renderer.activeCamera.roll(5);
this.renderer.activeCamera.update();
}
};
export function keyboardNavigation(options) {
return new KeyboardNavigation(options);
};
export { KeyboardNavigation };

View File

@ -1,159 +0,0 @@
/**
* @module og/control/LayerSwitcher
*/
'use strict';
import { BaseControl } from './BaseControl.js';
/**
* Simple(OpenLayers like)layer switcher, includes base layers, overlays, geo images etc. groups.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class LayerSwitcher extends BaseControl {
constructor(options) {
super(options);
this.dialog = null;
this.baseLayersDiv = null;
this.overlaysDiv = null;
this._id = LayerSwitcher.numSwitches++;
}
static get numSwitches() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set numSwitches(n) {
this._counter = n;
}
oninit() {
this.planet.events.on("layeradd", this.onLayerAdded, this);
this.planet.events.on("layerremove", this.onLayerRemoved, this);
this.createSwitcher();
this.createDialog();
}
onLayerAdded(layer) {
if (layer.displayInLayerSwitcher) {
if (layer.isBaseLayer()) {
this.addSwitcher("radio", layer, this.baseLayersDiv);
} else {
this.addSwitcher("checkbox", layer, this.overlaysDiv, this._id);
}
}
};
onLayerRemoved(layer) {
layer._removeCallback();
layer._removeCallback = null;
}
addSwitcher(type, obj, container, id) {
var lineDiv = document.createElement('div');
var that = this;
var center = document.createElement('div');
center.classList.add('ogViewExtentBtn');
center.onclick = function () {
that.planet.flyExtent(obj.getExtent());
};
var inp = document.createElement('input');
inp.type = type;
inp.name = "ogBaseLayerRadiosId" + (id || "");
inp.checked = obj.getVisibility();
inp.className = "ogLayerSwitcherInput";
inp.onclick = function () {
obj.setVisibility(this.checked);
};
obj.events && obj.events.on("visibilitychange", function (e) {
inp.checked = e.getVisibility();
});
var lbl = document.createElement('label');
lbl.className = "ogLayerSwitcherLabel";
lbl.innerHTML = (obj.name || obj.src || "noname") + "</br>";
obj._removeCallback = function () {
container.removeChild(lineDiv);
}
lineDiv.appendChild(center);
lineDiv.appendChild(inp);
lineDiv.appendChild(lbl);
container.appendChild(lineDiv);
}
createBaseLayersContainer() {
var layersDiv = document.createElement('div');
layersDiv.className = "layersDiv";
this.dialog.appendChild(layersDiv);
var baseLayersLbl = document.createElement('div');
baseLayersLbl.className = "layersDiv";
baseLayersLbl.innerHTML = "Base Layer";
layersDiv.appendChild(baseLayersLbl);
this.baseLayersDiv = document.createElement('div');
layersDiv.appendChild(this.baseLayersDiv);
}
createOverlaysContainer() {
var overlaysDiv = document.createElement('div');
overlaysDiv.className = "layersDiv";
this.dialog.appendChild(overlaysDiv);
var overlaysLbl = document.createElement('div');
overlaysLbl.className = "layersDiv";
overlaysLbl.innerHTML = "Overlays";
overlaysDiv.appendChild(overlaysLbl);
this.overlaysDiv = document.createElement('div');
overlaysDiv.appendChild(this.overlaysDiv);
}
createDialog() {
this.dialog = document.createElement('div');
this.dialog.id = "ogLayerSwitcherDialog";
this.dialog.className = "displayNone";
this.renderer.div.appendChild(this.dialog);
this.createBaseLayersContainer();
this.createOverlaysContainer();
if (this.planet) {
for (var i = 0; i < this.planet.layers.length; i++) {
this.onLayerAdded(this.planet.layers[i]);
}
}
}
createSwitcher() {
var button = document.createElement('div');
button.className = 'ogLayerSwitcherButton';
button.id = "ogLayerSwitcherButtonMaximize";
var that = this;
button.onclick = function (e) {
if (this.id === "ogLayerSwitcherButtonMaximize") {
this.id = "ogLayerSwitcherButtonMinimize";
that.dialog.className = "displayBlock";
} else {
this.id = "ogLayerSwitcherButtonMaximize";
that.dialog.className = "displayNone";
}
};
this.renderer.div.appendChild(button);
}
};
export { LayerSwitcher };

View File

@ -1,327 +0,0 @@
/**
* @module og/control/MouseNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Quat } from '../math/Quat.js';
import { Ray } from '../math/Ray.js';
import { Sphere } from '../bv/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Mouse planet camera dragging control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class MouseNavigation extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this.grabbedPoint = new Vec3();
this._eye0 = new Vec3();
this.pointOnEarth = new Vec3();
this.earthUp = new Vec3();
this.inertia = 0.007;
this.grabbedSpheroid = new Sphere();
this.planet = null;
this.qRot = new Quat();
this.scaleRot = 0;
this.distDiff = 0.33;
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
this._keyLock = new Key();
}
static getMovePointsFromPixelTerrain(cam, planet, stepsCount, delta, point, forward, dir) {
var steps = []
var eye = cam.eye.clone(),
n = cam._n.clone(),
u = cam._u.clone(),
v = cam._v.clone();
var a = planet.getCartesianFromPixelTerrain(point, true);
if (!dir) {
dir = Vec3.sub(a, cam.eye).normalize();
}
var d = a ? delta * cam.eye.distance(a) / stepsCount : 1000;
if (forward) {
d = -d;
} else {
d *= 2;
}
var scaled_n = n.scaleTo(d);
if (a && cam._lonLat.height > 9000 && cam.slope > 0.6) {
var grabbedSpheroid = new Sphere();
grabbedSpheroid.radius = a.length();
var rotArr = [],
eyeArr = []
var breaked = false;
for (var i = 0; i < stepsCount; i++) {
eye.addA(scaled_n);
var b = new Ray(eye, dir).hitSphere(grabbedSpheroid);
eyeArr[i] = eye.clone();
if (b) {
rotArr[i] = new Mat4().rotateBetweenVectors(a.normal(), b.normal());
} else {
breaked = true;
break;
}
}
if (!breaked) {
for (var i = 0; i < stepsCount; i++) {
var rot = rotArr[i];
steps[i] = {};
steps[i].eye = rot.mulVec3(eyeArr[i]);
steps[i].v = rot.mulVec3(v);
steps[i].u = rot.mulVec3(u);
steps[i].n = rot.mulVec3(n);
}
} else {
eye = cam.eye.clone();
for (var i = 0; i < stepsCount; i++) {
steps[i] = {};
steps[i].eye = eye.addA(scaled_n).clone();
steps[i].v = v;
steps[i].u = u;
steps[i].n = n;
}
}
} else {
for (var i = 0; i < stepsCount; i++) {
steps[i] = {};
steps[i].eye = eye.addA(dir.scaleTo(-d)).clone();
steps[i].v = v;
steps[i].u = u;
steps[i].n = n;
}
}
return steps;
}
onactivate() {
this.renderer.events.on("mousewheel", this.onMouseWheel, this);
this.renderer.events.on("lhold", this.onMouseLeftButtonDown, this);
this.renderer.events.on("rhold", this.onMouseRightButtonDown, this);
this.renderer.events.on("ldown", this.onMouseLeftButtonClick, this);
this.renderer.events.on("lup", this.onMouseLeftButtonUp, this);
this.renderer.events.on("rdown", this.onMouseRightButtonClick, this);
this.renderer.events.on("ldblclick", this.onMouseLeftButtonDoubleClick, this);
this.renderer.events.on("draw", this.onDraw, this);
}
ondeactivate() {
this.renderer.events.off("mousewheel", this.onMouseWheel);
this.renderer.events.off("lhold", this.onMouseLeftButtonDown);
this.renderer.events.off("rhold", this.onMouseRightButtonDown);
this.renderer.events.off("ldown", this.onMouseLeftButtonClick);
this.renderer.events.off("lup", this.onMouseLeftButtonUp);
this.renderer.events.off("rdown", this.onMouseRightButtonClick);
this.renderer.events.off("ldblclick", this.onMouseLeftButtonDoubleClick);
this.renderer.events.off("draw", this.onDraw);
};
onMouseWheel(event) {
if (this.stepIndex)
return;
this.planet.stopFlying();
this.stopRotation();
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
var ms = this.renderer.events.mouseState;
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff, ms, event.wheelDelta > 0, ms.direction);
}
oninit() {
this.activate();
}
onMouseLeftButtonDoubleClick() {
this.planet.stopFlying();
this.stopRotation();
var p = this.planet.getCartesianFromPixelTerrain(this.renderer.events.mouseState, true),
g = this.planet.ellipsoid.cartesianToLonLat(p);
if (this.renderer.events.isKeyPressed(input.KEY_SHIFT)) {
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 2.0));
} else {
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 0.57));
}
}
onMouseLeftButtonClick() {
if (this._active) {
this.renderer.handler.canvas.classList.add("ogGrabbingPoiner");
this.grabbedPoint = this.planet.getCartesianFromMouseTerrain(true);
if (this.grabbedPoint) {
this._eye0.copy(this.renderer.activeCamera.eye);
this.grabbedSpheroid.radius = this.grabbedPoint.length();
this.stopRotation();
}
}
}
stopRotation() {
this.qRot.clear();
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
onMouseLeftButtonUp(e) {
this.renderer.handler.canvas.classList.remove("ogGrabbingPoiner");
}
onMouseLeftButtonDown(e) {
if (this._active) {
if (!this.grabbedPoint)
return;
this.planet.stopFlying();
if (this.renderer.events.mouseState.moving) {
var cam = this.renderer.activeCamera;
if (cam.slope > 0.28) {
var targetPoint = new Ray(cam.eye, e.direction).hitSphere(this.grabbedSpheroid);
if (targetPoint) {
this.scaleRot = 1;
this.qRot = Quat.getRotationBetweenVectors(targetPoint.normal(), this.grabbedPoint.normal());
var rot = this.qRot;
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
} else {
var p0 = this.grabbedPoint,
p1 = Vec3.add(p0, cam._u),
p2 = Vec3.add(p0, p0.normal());
var px = new Vec3();
if (new Ray(cam.eye, e.direction).hitPlane(p0, p1, p2, px) === Ray.INSIDE) {
cam.eye = this._eye0.addA(px.subA(p0).negate());
cam.update();
}
}
} else {
this.scaleRot = 0;
}
}
}
onMouseRightButtonClick(e) {
this.stopRotation();
this.planet.stopFlying();
this.pointOnEarth = this.planet.getCartesianFromPixelTerrain({ x: e.x, y: e.y }, true);
if (this.pointOnEarth) {
this.earthUp = this.pointOnEarth.normal();
}
};
onMouseRightButtonDown(e) {
var cam = this.renderer.activeCamera;
if (this.pointOnEarth && this.renderer.events.mouseState.moving) {
this.renderer.controlsBag.scaleRot = 1;
var l = 0.5 / cam.eye.distance(this.pointOnEarth) * cam._lonLat.height * math.RADIANS;
if (l > 0.007) l = 0.007;
cam.rotateHorizontal(l * (e.x - e.prev_x), false, this.pointOnEarth, this.earthUp);
cam.rotateVertical(l * (e.y - e.prev_y), this.pointOnEarth);
cam.update();
}
}
onDraw(e) {
if (this._active) {
var r = this.renderer;
var cam = r.activeCamera;
var prevEye = cam.eye.clone();
if (this.stepIndex) {
r.controlsBag.scaleRot = 1;
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
} else {
if (this._deactivate) {
this._deactivate = false;
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
if (r.events.mouseState.leftButtonDown || !this.scaleRot)
return;
this.scaleRot -= this.inertia;
if (this.scaleRot <= 0) {
this.scaleRot = 0;
} else {
r.controlsBag.scaleRot = this.scaleRot;
var rot = this.qRot.slerp(Quat.IDENTITY, 1 - this.scaleRot * this.scaleRot * this.scaleRot).normalize();
if (!(rot.x || rot.y || rot.z)) {
this.scaleRot = 0;
}
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
if (cam.eye.distance(prevEye) / cam._terrainAltitude > 0.01) {
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
} else {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
}
};
export { MouseNavigation };

View File

@ -1,39 +0,0 @@
/**
* @module og/control/ShowFps
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { print2d } from '../utils/Shared.js';
/**
* Frame per second(FPS) display control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class ShowFps extends BaseControl {
constructor(options) {
super(options);
}
oninit() {
var d = document.createElement('div');
d.className = 'defaultText ';
d.id = "ogShowFpsControl";
document.body.appendChild(d);
this.renderer.events.on("draw", this._draw, this);
}
_draw() {
print2d("ogShowFpsControl", (1000.0 / this.renderer.handler.deltaTime).toFixed(1), this.renderer.handler.canvas.clientWidth - 60, 0);
}
};
export function showFps(options) {
return new ShowFps(options);
};
export { ShowFps };

View File

@ -1,110 +0,0 @@
/**
* @module og/control/SimpleNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
/**
* Simple keyboard camera navigation with W,S,A,D and shift keys to fly around the scene.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class SimpleNavigation extends BaseControl {
constructor(options) {
options = options || {};
super(options);
this.camera = null;
this.speed = options.speed || 1.0;
}
oninit() {
this.camera = this.renderer.activeCamera;
this.renderer.events.on("keypress", input.KEY_W, this.onCameraMoveForward, this);
this.renderer.events.on("keypress", input.KEY_S, this.onCameraMoveBackward, this);
this.renderer.events.on("keypress", input.KEY_A, this.onCameraStrifeLeft, this);
this.renderer.events.on("keypress", input.KEY_D, this.onCameraStrifeRight, this);
this.renderer.events.on("keypress", input.KEY_UP, this.onCameraLookUp, this);
this.renderer.events.on("keypress", input.KEY_DOWN, this.onCameraLookDown, this);
this.renderer.events.on("keypress", input.KEY_LEFT, this.onCameraTurnLeft, this);
this.renderer.events.on("keypress", input.KEY_RIGHT, this.onCameraTurnRight, this);
this.renderer.events.on("keypress", input.KEY_Q, this.onCameraRollLeft, this);
this.renderer.events.on("keypress", input.KEY_E, this.onCameraRollRight, this);
}
onCameraMoveForward(event) {
var camera = this.camera;
camera.slide(0, 0, -this.speed);
camera.update();
}
onCameraMoveBackward(event) {
var camera = this.camera;
camera.slide(0, 0, this.speed);
camera.update();
}
onCameraStrifeLeft(event) {
var camera = this.camera;
camera.slide(-this.speed, 0, 0);
camera.update();
}
onCameraStrifeRight(event) {
var camera = this.camera;
camera.slide(this.speed, 0, 0);
camera.update();
}
onCameraLookUp(event) {
var cam = this.camera;
cam.pitch(0.5);
cam.update();
}
onCameraLookDown(event) {
var cam = this.camera;
cam.pitch(-0.5);
cam.update();
}
onCameraTurnLeft(event) {
var cam = this.camera;
cam.yaw(0.5);
cam.update();
}
onCameraTurnRight(event) {
var cam = this.camera;
cam.yaw(-0.5);
cam.update();
}
onCameraRollLeft(event) {
var cam = this.camera;
cam.roll(-0.5);
cam.update();
}
onCameraRollRight(event) {
var cam = this.camera;
cam.roll(0.5);
cam.update();
}
};
/**
* Creates simple navigation control instance.
*/
export function simpleNavigation(options) {
return new SimpleNavigation(options);
};
export { SimpleNavigation };

View File

@ -1,153 +0,0 @@
/**
* @module og/control/Sun
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { getSunPosition } from '../astro/earth.js';
import { input } from '../input/input.js';
import { LightSource } from '../light/LightSource.js';
import { Quat } from '../math/Quat.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Real Sun geocentric position control that place the Sun on the right place by the Earth.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class Sun extends BaseControl {
constructor(options) {
super(options);
options = options || {};
/**
* Earth planet node.
* @public
* @type {og.scene.Planet}
*/
this.planet = null;
/**
* Sunlight position placed in the camera eye.
* @private
* @type {boolean}
*/
//this._isCameraSunlight = false;
this.offsetVertical = options.offsetVertical || -5000000;
this.offsetHorizontal = options.offsetHorizontal || 5000000;
/**
* Light source.
* @public
* @type {og.LightSource}
*/
this.sunlight = null;
/**
* Current frame handler clock date and time.
* @private
* @type {Number}
*/
this._currDate = 0;
/**
* Previous frame handler clock date and time.
* @private
* @type {Number}
*/
this._prevDate = 0;
this._clockPtr = null;
this._lightOn = false;
this._stopped = options.stopped || false;
}
oninit() {
this.planet.lightEnabled = true;
//sunlight initialization
this.sunlight = new LightSource("Sun", {
'ambient': new Vec3(0.15, 0.15, 0.25),
'diffuse': new Vec3(0.9, 0.9, 0.8),
'specular': new Vec3(0.1, 0.1, 0.06),
'shininess': 110
});
this.sunlight.addTo(this.planet);
var that = this;
this.renderer.events.on("draw", this._draw, this);
this.renderer.events.on("charkeypress", input.KEY_L, function () {
that.planet.lightEnabled = !that.planet.lightEnabled;
});
if (!this._clockPtr)
this._clockPtr = this.renderer.handler.defaultClock;
}
stop() {
this._stopped = true;
}
onactivate() {
this._stopped = false;
}
bindClock(clock) {
this._clockPtr = clock;
}
_draw() {
if (!this._stopped) {
this._currDate = this._clockPtr.currentDate;
var cam = this.renderer.activeCamera;
if (cam.getHeight() < 4650000 || !this._active) {
this._lightOn = true;
this._f = 1;
var n = cam.eye.normal();
var tu = Vec3.proj_b_to_plane(cam._v, n, cam._v).normalize().scale(this.offsetVertical);
var tr = Vec3.proj_b_to_plane(cam._u, n, cam._u).normalize().scale(this.offsetHorizontal);
var d = tu.add(tr);
var pos = cam.eye.add(d);
if (this._k > 0) {
this._k -= 0.01;
var rot = Quat.getRotationBetweenVectors(this.sunlight._position.normal(), pos.normal());
var r = rot.slerp(Quat.IDENTITY, this._k).normalize();
this.sunlight.setPosition(r.mulVec3(this.sunlight._position));
} else {
this.sunlight.setPosition(pos);
}
} else {
this._k = 1;
if (this._f > 0) {
this._f -= 0.01;
var rot = Quat.getRotationBetweenVectors(this.sunlight._position.normal(), getSunPosition(this._currDate).normal());
var r = rot.slerp(Quat.IDENTITY, this._f).normalize();
this.sunlight.setPosition(r.mulVec3(this.sunlight._position));
} else {
if (Math.abs(this._currDate - this._prevDate) > 0.00034 && this._active || this._lightOn) {
this._lightOn = false;
this._prevDate = this._currDate;
this.sunlight.setPosition(getSunPosition(this._currDate));
this._f = 0;
}
}
}
}
}
};
export function sun(options) {
return Sun(options);
};
export { Sun };

View File

@ -1,35 +0,0 @@
/**
* @module og/control/ToggleWireframe
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
/**
* Planet GL draw mode(TRIANGLE_STRIP/LINE_STRING) changer.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class ToggleWireframe extends BaseControl {
constructor(options) {
super(options);
}
oninit() {
this.renderer.events.on("charkeypress", input.KEY_X, this.toogleWireframe, this);
}
toogleWireframe(e) {
if (this.planet.drawMode === this.renderer.handler.gl.LINE_STRIP) {
this.planet.setDrawMode(this.renderer.handler.gl.TRIANGLE_STRIP);
} else {
this.planet.setDrawMode(this.renderer.handler.gl.LINE_STRIP);
}
}
};
export { ToggleWireframe };

View File

@ -1,310 +0,0 @@
/**
* @module og/control/TouchNavigation
*/
'use strict';
import * as math from '../math.js';
import { BaseControl } from './BaseControl.js';
import { input } from '../input/input.js';
import { Key } from '../Lock.js';
import { LonLat } from '../LonLat.js';
import { Mat4 } from '../math/Mat4.js';
import { Quat } from '../math/Quat.js';
import { Ray } from '../math/Ray.js';
import { Sphere } from '../bv/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Touch pad planet camera dragging control.
* @class
* @extends {og.control.BaseControl}
* @param {Object} [options] - Control options.
*/
class TouchNavigation extends BaseControl {
constructor(options) {
super(options);
this.grabbedPoint = new Vec3();
this.inertia = 0.007;
this.grabbedSpheroid = new Sphere();
this.planet = null;
this.qRot = new Quat();
this.scaleRot = 0;
this.rot = 1;
this._eye0 = new Vec3();
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
var Touch = function () {
this.x = 0;
this.y = 0;
this.prev_x = 0;
this.prev_y = 0;
this.grabbedPoint = new Vec3();
this.grabbedSpheroid = new Sphere();
this.dX = function () { return this.x - this.prev_x; };
this.dY = function () { return this.y - this.prev_y; };
};
this.pointOnEarth = null;
this.earthUp = null;
this.touches = [new Touch(), new Touch()];
this._keyLock = new Key();
}
oninit() {
this.renderer.events.on("touchstart", this.onTouchStart, this);
this.renderer.events.on("touchend", this.onTouchEnd, this);
this.renderer.events.on("doubletouch", this.onDoubleTouch, this);
this.renderer.events.on("touchcancel", this.onTouchCancel, this);
this.renderer.events.on("touchmove", this.onTouchMove, this);
this.renderer.events.on("draw", this.onDraw, this);
}
onTouchStart(e) {
this._touching = true;
if (e.sys.touches.length === 2) {
var t0 = this.touches[0],
t1 = this.touches[1];
t0.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t0.prev_x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.prev_y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t0.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t0, true);
t1.x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
t1.prev_x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.prev_y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
t1.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t1, true);
//this.planet._viewChanged = true;
this.pointOnEarth = this.planet.getCartesianFromPixelTerrain(this.renderer.handler.getCenter(), true);
if (this.pointOnEarth) {
this.earthUp = this.pointOnEarth.normal();
}
if (t0.grabbedPoint && t1.grabbedPoint) {
t0.grabbedSpheroid.radius = t0.grabbedPoint.length();
t1.grabbedSpheroid.radius = t1.grabbedPoint.length();
this.stopRotation();
}
} else if (e.sys.touches.length === 1) {
this._startTouchOne(e);
}
}
_startTouchOne(e) {
var t = this.touches[0];
t.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t.prev_x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.prev_y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t.grabbedPoint = this.planet.getCartesianFromPixelTerrain(t, true);
this._eye0.copy(this.renderer.activeCamera.eye);
if (t.grabbedPoint) {
t.grabbedSpheroid.radius = t.grabbedPoint.length();
this.stopRotation();
}
}
stopRotation() {
this.qRot.clear();
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
onDoubleTouch(e) {
if (this.stepIndex)
return;
this.planet.stopFlying();
this.stopRotation();
var p = this.planet.getCartesianFromPixelTerrain(this.touches[0], true),
g = this.planet.ellipsoid.cartesianToLonLat(p);
this.planet.flyLonLat(new LonLat(g.lon, g.lat, this.renderer.activeCamera.eye.distance(p) * 0.57));
}
onTouchEnd(e) {
if (e.sys.touches.length === 0)
this._touching = false;
if (e.sys.touches.length === 1) {
this._startTouchOne(e);
}
if (Math.abs(this.touches[0].x - this.touches[0].prev_x) < 3 &&
Math.abs(this.touches[0].y - this.touches[0].prev_y) < 3)
this.scaleRot = 0;
}
onTouchCancel(e) {
}
onTouchMove(e) {
var cam = this.renderer.activeCamera;
if (e.sys.touches.length === 2) {
this.renderer.controlsBag.scaleRot = 1;
var t0 = this.touches[0],
t1 = this.touches[1];
if (!t0.grabbedPoint || !t1.grabbedPoint)
return;
this.planet.stopFlying();
t0.prev_x = t0.x;
t0.prev_y = t0.y;
t0.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t0.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
t1.prev_x = t1.x;
t1.prev_y = t1.y;
t1.x = e.sys.touches.item(1).clientX - e.sys.offsetLeft;
t1.y = e.sys.touches.item(1).clientY - e.sys.offsetTop;
//var center_x = Math.round(t0.x + (t1.x - t0.x) * 0.5);
//var center_y = Math.round(t0.y + (t1.y - t0.y) * 0.5);
//var dirC = cam.unproject(center_x, center_y);
//var targetPointC = this.planet.getCartesianFromPixelTerrain(new og.math.Pixel(center_x, center_y));
//var dir0 = cam.unproject(t0.x, t0.y);
//var targetPoint0 = new og.math.Ray(cam.eye, dir0).hitSphere(t0.grabbedSpheroid);
//var dir1 = cam.unproject(t1.x, t1.y);
//var targetPoint1 = new og.math.Ray(cam.eye, dir1).hitSphere(t1.grabbedSpheroid);
//print2d("t1", center_x + "," + center_y, 100, 100);
//print2d("t2", targetPointC.x + "," + targetPointC.y + "," + targetPointC.z, 100, 120);
if (t0.dY() > 0 && t1.dY() > 0 || t0.dY() < 0 && t1.dY() < 0 ||
t0.dX() > 0 && t1.dX() > 0 || t0.dX() < 0 && t1.dX() < 0) {
var l = 0.5 / cam.eye.distance(this.pointOnEarth) * cam._lonLat.height * math.RADIANS;
if (l > 0.007) l = 0.007;
cam.rotateHorizontal(l * t0.dX(), false, this.pointOnEarth, this.earthUp);
cam.rotateVertical(l * t0.dY(), this.pointOnEarth);
cam.update();
}
this.scaleRot = 0;
} else if (e.sys.touches.length === 1) {
var t = this.touches[0];
t.prev_x = t.x;
t.prev_y = t.y;
t.x = e.sys.touches.item(0).clientX - e.sys.offsetLeft;
t.y = e.sys.touches.item(0).clientY - e.sys.offsetTop;
if (!t.grabbedPoint)
return;
this.planet.stopFlying();
var direction = cam.unproject(t.x, t.y);
var targetPoint = new Ray(cam.eye, direction).hitSphere(t.grabbedSpheroid);
if (targetPoint) {
if (cam._n.dot(cam.eye.normal()) > 0.28) {
this.qRot = Quat.getRotationBetweenVectors(targetPoint.normal(), t.grabbedPoint.normal());
var rot = this.qRot;
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
this.scaleRot = 1;
} else {
var p0 = t.grabbedPoint,
p1 = Vec3.add(p0, cam._u),
p2 = Vec3.add(p0, p0.normal());
var dir = cam.unproject(t.x, t.y);
var px = new Vec3();
if (new Ray(cam.eye, dir).hitPlane(p0, p1, p2, px) === Ray.INSIDE) {
cam.eye = this._eye0.addA(px.subA(p0).negate());
cam.update();
this.scaleRot = 0;
}
}
}
}
};
onDraw(e) {
this.renderer.controlsBag.scaleRot = this.scaleRot;
if (this._touching)
return;
var r = this.renderer;
var cam = r.activeCamera;
var prevEye = cam.eye.clone();
if (this.stepIndex) {
r.controlsBag.scaleRot = 1;
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
var cam = this.renderer.activeCamera;
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
}
if (r.events.mouseState.leftButtonDown || !this.scaleRot)
return;
this.scaleRot -= this.inertia;
if (this.scaleRot <= 0)
this.scaleRot = 0;
else {
r.controlsBag.scaleRot = this.scaleRot;
var cam = r.activeCamera;
var rot = this.qRot.slerp(Quat.IDENTITY, 1 - this.scaleRot * this.scaleRot * this.scaleRot).normalize();
if (!(rot.x || rot.y || rot.z)) {
this.scaleRot = 0;
}
cam.eye = rot.mulVec3(cam.eye);
cam._v = rot.mulVec3(cam._v);
cam._u = rot.mulVec3(cam._u);
cam._n = rot.mulVec3(cam._n);
cam.update();
}
if (cam.eye.distance(prevEye) / cam._terrainAltitude > 0.01) {
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
} else {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
}
}
};
export { TouchNavigation };

View File

@ -1,122 +0,0 @@
/**
* @module og/control/ZoomControl
*/
'use strict';
import { BaseControl } from './BaseControl.js';
import { Key } from '../Lock.js';
import { MouseNavigation } from './MouseNavigation.js';
/**
* Planet zoom buttons control.
* @class
* @extends {og.control.BaseControl}
* @params {Object} [options] - Control options.
*/
class ZoomControl extends BaseControl {
constructor(options) {
super(options);
options = options || {};
this.distDiff = 0.33;
this.stepsCount = 5;
this.stepsForward = null;
this.stepIndex = 0;
this._keyLock = new Key();
this.planet = null;
}
oninit() {
var zoomDiv = document.createElement('div'),
btnZoomIn = document.createElement('button'),
btnZoomOut = document.createElement('button');
zoomDiv.className = 'ogZoomControl';
btnZoomIn.className = 'ogZoomButton ogZoomIn';
btnZoomOut.className = 'ogZoomButton ogZoomOut';
zoomDiv.appendChild(btnZoomIn);
zoomDiv.appendChild(btnZoomOut);
this.renderer.div.appendChild(zoomDiv);
var that = this;
btnZoomIn.onclick = function (e) {
that.zoomIn();
};
btnZoomOut.onclick = function (e) {
that.zoomOut();
};
this.renderer.events.on("draw", this._draw, this);
}
/**
* Planet zoom in.
* @public
*/
zoomIn() {
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff * 1.7, this.renderer.getCenter(), true, this.renderer.activeCamera._n.negateTo());
}
/**
* Planet zoom out.
* @public
*/
zoomOut() {
this._deactivate = true;
this.planet.layerLock.lock(this._keyLock);
this.planet.terrainLock.lock(this._keyLock);
this.planet._normalMapCreator.lock(this._keyLock);
this.stepIndex = this.stepsCount;
this.stepsForward = MouseNavigation.getMovePointsFromPixelTerrain(this.renderer.activeCamera,
this.planet, this.stepsCount, this.distDiff * 2, this.renderer.getCenter(), false, this.renderer.activeCamera._n.negateTo());
}
_draw(e) {
var cam = this.renderer.activeCamera;
if (this.stepIndex) {
var sf = this.stepsForward[this.stepsCount - this.stepIndex--];
cam.eye = sf.eye;
cam._v = sf.v;
cam._u = sf.u;
cam._n = sf.n;
cam.update();
} else if (!cam._flying) {
if (this._deactivate) {
this.planet.layerLock.free(this._keyLock);
this.planet.terrainLock.free(this._keyLock);
this.planet._normalMapCreator.free(this._keyLock);
this._deactivate = false;
}
}
}
};
export function zoomControl(options) {
return new ZoomControl(options);
};
export { ZoomControl };

View File

@ -1,393 +0,0 @@
/**
* @module og/ellipsoid/Ellipsoid
*/
'use strict';
import * as math from '../math.js';
import { Vec3 } from '../math/Vec3.js';
import { LonLat } from '../LonLat.js';
/**
* Class represents a plant ellipsoid.
* @class
* @param {number} equatorialSize - Equatorial ellipsoid size.
* @param {number} polarSize - Polar ellipsoid size.
*/
class Ellipsoid {
constructor(equatorialSize, polarSize) {
this._a = equatorialSize;
this._b = polarSize;
this._flattening = equatorialSize / polarSize;
this._a2 = equatorialSize * equatorialSize;
this._b2 = polarSize * polarSize;
var qa2b2 = Math.sqrt(this._a2 - this._b2);
this._e = qa2b2 / equatorialSize;
this._e2 = this._e * this._e;
this._e22 = this._e2 * this._e2;
this._k = qa2b2 / polarSize;
this._k2 = this._k * this._k;
this._radii = new Vec3(equatorialSize, polarSize, equatorialSize);
this._radii2 = new Vec3(this._a2, this._b2, this._a2);
this._invRadii = new Vec3(1 / equatorialSize, 1 / polarSize, 1 / equatorialSize);
this._invRadii2 = new Vec3(1 / this._a2, 1 / this._b2, 1 / this._a2);
}
/**
* Gets ellipsoid equatorial size.
* @public
* @returns {number} -
*/
getEquatorialSize() {
return this._a;
}
/**
* Gets ellipsoid polar size.
* @public
* @returns {number} -
*/
getPolarSize() {
return this._b;
}
/**
* Gets cartesian ECEF from Wgs84 geodetic coordiantes.
* @public
* @param {og.LonLat} lonlat - Degrees geodetic coordiantes.
* @returns {og.math.Vector3} -
*/
lonLatToCartesian(lonlat) {
var latrad = math.RADIANS * lonlat.lat,
lonrad = math.RADIANS * lonlat.lon;
var slt = Math.sin(latrad);
var N = this._a / Math.sqrt(1 - this._e2 * slt * slt);
var nc = (N + lonlat.height) * Math.cos(latrad);
return new Vec3(
nc * Math.sin(lonrad),
(N * (1 - this._e2) + lonlat.height) * slt,
nc * Math.cos(lonrad));
}
/**
* Gets Wgs84 geodetic coordiantes from cartesian ECEF.
* @public
* @param {og.math.Vector3} cartesian - Cartesian coordinates.
* @returns {og.LonLat} -
*/
cartesianToLonLat(cartesian) {
var x = cartesian.z, y = cartesian.x, z = cartesian.y;
var ecc2 = this._e2;
var ecc22 = this._e22;
var r2 = x * x + y * y;
var r = Math.sqrt(r2);
var e2 = this._a2 - this._b2;
var z2 = z * z;
var f = 54.0 * this._b2 * z2;
var g = r2 + (1 - ecc2) * z2 + ecc2 * e2;
var g2 = g * g;
var c = ecc22 * f * r2 / (g2 * g);
var s = Math.pow((1 + c + Math.sqrt(c * (c + 2))), 0.33333333333333333);
var p = f / (3 * Math.pow((1 + s + 1 / s), 2) * g2);
var q = Math.sqrt(1 + 2 * ecc22 * p);
var r0 = -(p * ecc2 * r) / 1 + q + Math.sqrt(0.5 * this._a2 * (1 + 1 / q) - p * (1 - ecc2) * z2 / (q * (1 + q)) - 0.5 * p * r2);
var recc2r0 = r - ecc2 * r0;
var recc2r02 = recc2r0 * recc2r0;
var u = Math.sqrt(recc2r02 + z2);
var v = Math.sqrt(recc2r02 + (1 - ecc2) * z2);
var z0 = this._b2 * z / (this._a * v);
var h = u * (1 - this._b2 / (this._a * v));
var phi = Math.atan((z + this._k2 * z0) / r);
var lambda = Math.atan2(y, x);
var lat = phi * math.DEGREES;
var lon = lambda * math.DEGREES;
return new LonLat(lon, lat, h);
}
/**
* Gets ellipsoid surface normal.
* @public
* @param {og.math.Vector3} coord - Spatial coordiantes.
* @returns {og.math.Vector3} -
*/
getSurfaceNormal3v(coord) {
var r2 = this._invRadii2;
var nx = coord.x * r2.x, ny = coord.y * r2.y, nz = coord.z * r2.z;
var l = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);
return new Vec3(nx * l, ny * l, nz * l);
}
/**
* Gets the cartesian point on the height over the ellipsoid surface.
* @public
* @param {og.math.Vector3} coord - Spatial ellipsoid coordiantes.
* @param {number} h - Height this spatial coordinates.
* @return {og.math.Vector3} -
*/
getSurfaceHeight3v(coord, h) {
var r2 = this._invRadii2;
var nx = coord.x * r2.x, ny = coord.y * r2.y, nz = coord.z * r2.z;
var l = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);
return new Vec3(coord.x + h * nx * l, coord.y + h * ny * l, coord.z + h * nz * l);
}
/**
* Returns the distance from one point to another(using haversine formula) on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Distance between points.
*/
getGreatCircleDistance(lonLat1, lonLat2) {
var dLat = (lonLat2.lat - lonLat1.lat) * math.RADIANS;
var dLon = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lonLat1.lat * math.RADIANS) * Math.cos(lonLat2.lat * math.RADIANS);
return this._a * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
/**
* Returns the midpoint between two points on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of first point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of second point.
* @return {og.LonLat} Midpoint between points.
*/
getMiddlePointOnGreatCircle(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS,
l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS;
var dl = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var Bx = Math.cos(f2) * Math.cos(dl);
var By = Math.cos(f2) * Math.sin(dl);
var x = Math.sqrt((Math.cos(f1) + Bx) * (Math.cos(f1) + Bx) + By * By);
var y = Math.sin(f1) + Math.sin(f2);
var f3 = Math.atan2(y, x);
var l3 = l1 + Math.atan2(By, Math.cos(f1) + Bx);
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
/**
* Returns the point at given fraction between two points on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/Latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/Latitude of destination point.
* @param {number} fraction - Fraction between the two points (0 = source point, 1 = destination point).
* @returns {og.LonLat} Intermediate point between points.
*/
getIntermediatePointOnGreatCircle(lonLat1, lonLat2, fraction) {
var f1 = lonLat1.lat * math.RADIANS, l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS, l2 = lonLat2.lon * math.RADIANS;
var sinf1 = Math.sin(f1), cosf1 = Math.cos(f1), sinl1 = Math.sin(l1), cosl1 = Math.cos(l1);
var sinf2 = Math.sin(f2), cosf2 = Math.cos(f2), sinl2 = Math.sin(l2), cosl2 = Math.cos(l2);
var df = f2 - f1,
dl = l2 - l1;
var a = Math.sin(df / 2) * Math.sin(df / 2) + Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2);
var d = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var A = Math.sin((1 - fraction) * d) / Math.sin(d);
var B = Math.sin(fraction * d) / Math.sin(d);
var x = A * cosf1 * cosl1 + B * cosf2 * cosl2;
var y = A * cosf1 * sinl1 + B * cosf2 * sinl2;
var z = A * sinf1 + B * sinf2;
var f3 = Math.atan2(z, Math.sqrt(x * x + y * y));
var l3 = Math.atan2(y, x);
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
getRhumbBearing(lonLat1, lonLat2) {
var dLon = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var dPhi = Math.log(Math.tan(lonLat2.lat * math.RADIANS / 2 + Math.PI / 4) / Math.tan(lonLat1.lat * math.RADIANS / 2 + Math.PI / 4));
if (Math.abs(dLon) > Math.PI) {
if (dLon > 0) {
dLon = (2 * Math.PI - dLon) * -1;
}
else {
dLon = 2 * Math.PI + dLon;
}
}
return (Math.atan2(dLon, dPhi) * math.DEGREES + 360) % 360;
}
getBearing(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS, l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS, l2 = lonLat2.lon * math.RADIANS;
var y = Math.sin(l2 - l1) * Math.cos(f2);
var x = Math.cos(f1) * Math.sin(f2) - Math.sin(f1) * Math.cos(f2) * Math.cos(l2 - l1);
return Math.atan2(y, x) * math.DEGREES;
}
getBearingDestination(lonLat1, bearing, distance) {
bearing = bearing * math.RADIANS;
var nlon = (lonLat1.lon + 540) % 360 - 180;
var f1 = lonLat1.lat * math.RADIANS, l1 = nlon * math.RADIANS;
var dR = distance / this._a;
var f2 = Math.asin(Math.sin(f1) * Math.cos(dR) + Math.cos(f1) * Math.sin(dR) * Math.cos(bearing));
return new og.LonLat((l1 + Math.atan2(Math.sin(bearing) * Math.sin(dR) * Math.cos(f1), Math.cos(dR) - Math.sin(f1) * Math.sin(f2)))
* math.DEGREES, f2 * math.DEGREES);
}
/**
* Returns the (initial) bearing from source to destination point on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Initial bearing in degrees from north.
*/
getInitialBearing(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS,
f2 = lonLat2.lat * math.RADIANS;
var dl = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var y = Math.sin(dl) * Math.cos(f2);
var x = Math.cos(f1) * Math.sin(f2) -
Math.sin(f1) * Math.cos(f2) * Math.cos(dl);
var D = Math.atan2(y, x);
return (D * math.DEGREES + 360) % 360;
}
/**
* Returns final bearing arriving at destination destination point from lonLat1 point; the final bearing
* will differ from the initial bearing by varying degrees according to distance and latitude.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Final bearing in degrees from north.
*/
getFinalBearing(lonLat1, lonLat2) {
// get initial bearing from destination lonLat2 to lonLat1 & reverse it by adding 180°
return (this.getInitialBearing(lonLat2, lonLat1) + 180) % 360;
}
/**
* Returns the point of intersection of two paths defined by point and bearing.
* @param {og.LonLat} p1 - First point.
* @param {number} brng1 - Initial bearing from first point.
* @param {og.LonLat} p2 - Second point.
* @param {number} brng2 - Initial bearing from second point.
* @return {og.LonLat|null} Destination point (null if no unique intersection defined).
*/
intersection(p1, brng1, p2, brng2) {
var f1 = p1.lat * math.RADIANS,
l1 = p1.lon * math.RADIANS;
var f2 = p2.lat * math.RADIANS,
l2 = p2.lon * math.RADIANS;
var D13 = brng1 * math.RADIANS,
D23 = brng2 * math.RADIANS;
var df = f2 - f1,
dl = l2 - l1;
var d12 = 2 * Math.asin(Math.sqrt(Math.sin(df / 2) * Math.sin(df / 2)
+ Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2)));
if (d12 == 0) return null;
// initial/final bearings between points
var Da = Math.acos((Math.sin(f2) - Math.sin(f1) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f1)));
if (isNaN(Da)) Da = 0; // protect against rounding
var Db = Math.acos((Math.sin(f1) - Math.sin(f2) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f2)));
var D12 = Math.sin(l2 - l1) > 0 ? Da : 2 * Math.PI - Da;
var D21 = Math.sin(l2 - l1) > 0 ? 2 * Math.PI - Db : Db;
var a1 = (D13 - D12 + Math.PI) % (2 * Math.PI) - Math.PI;
var a2 = (D21 - D23 + Math.PI) % (2 * Math.PI) - Math.PI;
if (Math.sin(a1) == 0 && Math.sin(a2) == 0) return null; // infinite intersections
if (Math.sin(a1) * Math.sin(a2) < 0) return null; // ambiguous intersection
//a1 = Math.abs(a1);
//a2 = Math.abs(a2);
// ... Ed Williams takes abs of a1/a2, but seems to break calculation?
var a3 = Math.acos(-Math.cos(a1) * Math.cos(a2) + Math.sin(a1) * Math.sin(a2) * Math.cos(d12));
var d13 = Math.atan2(Math.sin(d12) * Math.sin(a1) * Math.sin(a2), Math.cos(a2) + Math.cos(a1) * Math.cos(a3));
var f3 = Math.asin(Math.sin(f1) * Math.cos(d13) + Math.cos(f1) * Math.sin(d13) * Math.cos(D13));
var dl13 = Math.atan2(Math.sin(D13) * Math.sin(d13) * Math.cos(f1), Math.cos(d13) - Math.sin(f1) * Math.sin(f3));
var l3 = l1 + dl13;
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
/**
* Returns ray vector hit ellipsoid coordinates.
* If the ray doesn't hit ellipsoid returns null.
* @public
* @param {og.math.Vector3} origin - Ray origin point.
* @param {og.math.Vector3} direction - Ray direction.
* @returns {og.math.Vector3} -
*/
hitRay(origin, direction) {
var q = this._invRadii.mul(origin);
var w = this._invRadii.mul(direction);
var q2 = q.dot(q);
var qw = q.dot(w);
var difference, w2, product, discriminant, temp;
if (q2 > 1.0) {
// Outside ellipsoid.
if (qw >= 0.0) {
// Looking outward or tangent (0 intersections).
return null;
}
// qw < 0.0.
var qw2 = qw * qw;
difference = q2 - 1.0; // Positively valued.
w2 = w.dot(w);
product = w2 * difference;
if (qw2 < product) {
// Imaginary roots (0 intersections).
return null;
} else if (qw2 > product) {
// Distinct roots (2 intersections).
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant); // Avoid cancellation.
var root0 = temp / w2;
var root1 = difference / temp;
if (root0 < root1) {
return origin.add(direction.scaleTo(root0));
}
return origin.add(direction.scaleTo(root1));
} else {
// qw2 == product. Repeated roots (2 intersections).
var root = Math.sqrt(difference / w2);
return origin.add(direction.scaleTo(root));
}
} else if (q2 < 1.0) {
// Inside ellipsoid (2 intersections).
difference = q2 - 1.0; // Negatively valued.
w2 = w.dot(w);
product = w2 * difference; // Negatively valued.
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant); // Positively valued.
return origin.add(direction.scaleTo(temp / w2));
} else {
// q2 == 1.0. On ellipsoid.
if (qw < 0.0) {
// Looking inward.
w2 = w.dot(w);
return origin.add(direction.scaleTo(-qw / w2));
}
// qw >= 0.0. Looking outward or tangent.
return null;
}
}
};
export { Ellipsoid };

View File

@ -1,393 +0,0 @@
/**
* @module og/ellipsoid/Ellipsoid
*/
'use strict';
import * as math from '../math.js';
import { Vec3 } from '../math/Vec3.js';
import { LonLat } from '../LonLat.js';
/**
* Class represents a plant ellipsoid.
* @class
* @param {number} equatorialSize - Equatorial ellipsoid size.
* @param {number} polarSize - Polar ellipsoid size.
*/
class Ellipsoid {
constructor(equatorialSize, polarSize) {
this._a = equatorialSize;
this._b = polarSize;
this._flattening = equatorialSize / polarSize;
this._a2 = equatorialSize * equatorialSize;
this._b2 = polarSize * polarSize;
var qa2b2 = Math.sqrt(this._a2 - this._b2);
this._e = qa2b2 / equatorialSize;
this._e2 = this._e * this._e;
this._e22 = this._e2 * this._e2;
this._k = qa2b2 / polarSize;
this._k2 = this._k * this._k;
this._radii = new Vec3(equatorialSize, polarSize, equatorialSize);
this._radii2 = new Vec3(this._a2, this._b2, this._a2);
this._invRadii = new Vec3(1 / equatorialSize, 1 / polarSize, 1 / equatorialSize);
this._invRadii2 = new Vec3(1 / this._a2, 1 / this._b2, 1 / this._a2);
}
/**
* Gets ellipsoid equatorial size.
* @public
* @returns {number} -
*/
getEquatorialSize() {
return this._a;
}
/**
* Gets ellipsoid polar size.
* @public
* @returns {number} -
*/
getPolarSize() {
return this._b;
}
/**
* Gets cartesian ECEF from Wgs84 geodetic coordiantes.
* @public
* @param {og.LonLat} lonlat - Degrees geodetic coordiantes.
* @returns {og.math.Vector3} -
*/
lonLatToCartesian(lonlat) {
var latrad = math.RADIANS * lonlat.lat,
lonrad = math.RADIANS * lonlat.lon;
var slt = Math.sin(latrad);
var N = this._a / Math.sqrt(1 - this._e2 * slt * slt);
var nc = (N + lonlat.height) * Math.cos(latrad);
return new Vec3(
nc * Math.sin(lonrad),
(N * (1 - this._e2) + lonlat.height) * slt,
nc * Math.cos(lonrad));
}
/**
* Gets Wgs84 geodetic coordiantes from cartesian ECEF.
* @public
* @param {og.math.Vector3} cartesian - Cartesian coordinates.
* @returns {og.LonLat} -
*/
cartesianToLonLat(cartesian) {
var x = cartesian.z, y = cartesian.x, z = cartesian.y;
var ecc2 = this._e2;
var ecc22 = this._e22;
var r2 = x * x + y * y;
var r = Math.sqrt(r2);
var e2 = this._a2 - this._b2;
var z2 = z * z;
var f = 54.0 * this._b2 * z2;
var g = r2 + (1 - ecc2) * z2 + ecc2 * e2;
var g2 = g * g;
var c = ecc22 * f * r2 / (g2 * g);
var s = Math.pow((1 + c + Math.sqrt(c * (c + 2))), 0.33333333333333333);
var p = f / (3 * Math.pow((1 + s + 1 / s), 2) * g2);
var q = Math.sqrt(1 + 2 * ecc22 * p);
var r0 = -(p * ecc2 * r) / 1 + q + Math.sqrt(0.5 * this._a2 * (1 + 1 / q) - p * (1 - ecc2) * z2 / (q * (1 + q)) - 0.5 * p * r2);
var recc2r0 = r - ecc2 * r0;
var recc2r02 = recc2r0 * recc2r0;
var u = Math.sqrt(recc2r02 + z2);
var v = Math.sqrt(recc2r02 + (1 - ecc2) * z2);
var z0 = this._b2 * z / (this._a * v);
var h = u * (1 - this._b2 / (this._a * v));
var phi = Math.atan((z + this._k2 * z0) / r);
var lambda = Math.atan2(y, x);
var lat = phi * math.DEGREES;
var lon = lambda * math.DEGREES;
return new LonLat(lon, lat, h);
}
/**
* Gets ellipsoid surface normal.
* @public
* @param {og.math.Vector3} coord - Spatial coordiantes.
* @returns {og.math.Vector3} -
*/
getSurfaceNormal3v(coord) {
var r2 = this._invRadii2;
var nx = coord.x * r2.x, ny = coord.y * r2.y, nz = coord.z * r2.z;
var l = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);
return new Vec3(nx * l, ny * l, nz * l);
}
/**
* Gets the cartesian point on the height over the ellipsoid surface.
* @public
* @param {og.math.Vector3} coord - Spatial ellipsoid coordiantes.
* @param {number} h - Height this spatial coordinates.
* @return {og.math.Vector3} -
*/
getSurfaceHeight3v(coord, h) {
var r2 = this._invRadii2;
var nx = coord.x * r2.x, ny = coord.y * r2.y, nz = coord.z * r2.z;
var l = 1 / Math.sqrt(nx * nx + ny * ny + nz * nz);
return new Vec3(coord.x + h * nx * l, coord.y + h * ny * l, coord.z + h * nz * l);
}
/**
* Returns the distance from one point to another(using haversine formula) on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Distance between points.
*/
getGreatCircleDistance(lonLat1, lonLat2) {
var dLat = (lonLat2.lat - lonLat1.lat) * math.RADIANS;
var dLon = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var a = Math.sin(dLat / 2) * Math.sin(dLat / 2) +
Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lonLat1.lat * math.RADIANS) * Math.cos(lonLat2.lat * math.RADIANS);
return this._a * 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}
/**
* Returns the midpoint between two points on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of first point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of second point.
* @return {og.LonLat} Midpoint between points.
*/
getMiddlePointOnGreatCircle(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS,
l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS;
var dl = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var Bx = Math.cos(f2) * Math.cos(dl);
var By = Math.cos(f2) * Math.sin(dl);
var x = Math.sqrt((Math.cos(f1) + Bx) * (Math.cos(f1) + Bx) + By * By);
var y = Math.sin(f1) + Math.sin(f2);
var f3 = Math.atan2(y, x);
var l3 = l1 + Math.atan2(By, Math.cos(f1) + Bx);
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
/**
* Returns the point at given fraction between two points on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/Latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/Latitude of destination point.
* @param {number} fraction - Fraction between the two points (0 = source point, 1 = destination point).
* @returns {og.LonLat} Intermediate point between points.
*/
getIntermediatePointOnGreatCircle(lonLat1, lonLat2, fraction) {
var f1 = lonLat1.lat * math.RADIANS, l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS, l2 = lonLat2.lon * math.RADIANS;
var sinf1 = Math.sin(f1), cosf1 = Math.cos(f1), sinl1 = Math.sin(l1), cosl1 = Math.cos(l1);
var sinf2 = Math.sin(f2), cosf2 = Math.cos(f2), sinl2 = Math.sin(l2), cosl2 = Math.cos(l2);
var df = f2 - f1,
dl = l2 - l1;
var a = Math.sin(df / 2) * Math.sin(df / 2) + Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2);
var d = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
var A = Math.sin((1 - fraction) * d) / Math.sin(d);
var B = Math.sin(fraction * d) / Math.sin(d);
var x = A * cosf1 * cosl1 + B * cosf2 * cosl2;
var y = A * cosf1 * sinl1 + B * cosf2 * sinl2;
var z = A * sinf1 + B * sinf2;
var f3 = Math.atan2(z, Math.sqrt(x * x + y * y));
var l3 = Math.atan2(y, x);
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
getRhumbBearing(lonLat1, lonLat2) {
var dLon = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var dPhi = Math.log(Math.tan(lonLat2.lat * math.RADIANS / 2 + Math.PI / 4) / Math.tan(lonLat1.lat * math.RADIANS / 2 + Math.PI / 4));
if (Math.abs(dLon) > Math.PI) {
if (dLon > 0) {
dLon = (2 * Math.PI - dLon) * -1;
}
else {
dLon = 2 * Math.PI + dLon;
}
}
return (Math.atan2(dLon, dPhi) * math.DEGREES + 360) % 360;
}
getBearing(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS, l1 = lonLat1.lon * math.RADIANS;
var f2 = lonLat2.lat * math.RADIANS, l2 = lonLat2.lon * math.RADIANS;
var y = Math.sin(l2 - l1) * Math.cos(f2);
var x = Math.cos(f1) * Math.sin(f2) - Math.sin(f1) * Math.cos(f2) * Math.cos(l2 - l1);
return Math.atan2(y, x) * math.DEGREES;
}
getBearingDestination(lonLat1, bearing, distance) {
bearing = bearing * math.RADIANS;
var nlon = (lonLat1.lon + 540) % 360 - 180;
var f1 = lonLat1.lat * math.RADIANS, l1 = nlon * math.RADIANS;
var dR = distance / this._a;
var f2 = Math.asin(Math.sin(f1) * Math.cos(dR) + Math.cos(f1) * Math.sin(dR) * Math.cos(bearing));
return new og.LonLat((l1 + Math.atan2(Math.sin(bearing) * Math.sin(dR) * Math.cos(f1), Math.cos(dR) - Math.sin(f1) * Math.sin(f2)))
* math.DEGREES, f2 * math.DEGREES);
}
/**
* Returns the (initial) bearing from source to destination point on the great circle.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Initial bearing in degrees from north.
*/
getInitialBearing(lonLat1, lonLat2) {
var f1 = lonLat1.lat * math.RADIANS,
f2 = lonLat2.lat * math.RADIANS;
var dl = (lonLat2.lon - lonLat1.lon) * math.RADIANS;
var y = Math.sin(dl) * Math.cos(f2);
var x = Math.cos(f1) * Math.sin(f2) -
Math.sin(f1) * Math.cos(f2) * Math.cos(dl);
var D = Math.atan2(y, x);
return (D * math.DEGREES + 360) % 360;
}
/**
* Returns final bearing arriving at destination destination point from lonLat1 point; the final bearing
* will differ from the initial bearing by varying degrees according to distance and latitude.
* @param {og.LonLat} lonLat1 - Longitude/latitude of source point.
* @param {og.LonLat} lonLat2 - Longitude/latitude of destination point.
* @return {number} Final bearing in degrees from north.
*/
getFinalBearing(lonLat1, lonLat2) {
// get initial bearing from destination lonLat2 to lonLat1 & reverse it by adding 180°
return (this.getInitialBearing(lonLat2, lonLat1) + 180) % 360;
}
/**
* Returns the point of intersection of two paths defined by point and bearing.
* @param {og.LonLat} p1 - First point.
* @param {number} brng1 - Initial bearing from first point.
* @param {og.LonLat} p2 - Second point.
* @param {number} brng2 - Initial bearing from second point.
* @return {og.LonLat|null} Destination point (null if no unique intersection defined).
*/
intersection(p1, brng1, p2, brng2) {
var f1 = p1.lat * math.RADIANS,
l1 = p1.lon * math.RADIANS;
var f2 = p2.lat * math.RADIANS,
l2 = p2.lon * math.RADIANS;
var D13 = brng1 * math.RADIANS,
D23 = brng2 * math.RADIANS;
var df = f2 - f1,
dl = l2 - l1;
var d12 = 2 * Math.asin(Math.sqrt(Math.sin(df / 2) * Math.sin(df / 2)
+ Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2)));
if (d12 == 0) return null;
// initial/final bearings between points
var Da = Math.acos((Math.sin(f2) - Math.sin(f1) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f1)));
if (isNaN(Da)) Da = 0; // protect against rounding
var Db = Math.acos((Math.sin(f1) - Math.sin(f2) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f2)));
var D12 = Math.sin(l2 - l1) > 0 ? Da : 2 * Math.PI - Da;
var D21 = Math.sin(l2 - l1) > 0 ? 2 * Math.PI - Db : Db;
var a1 = (D13 - D12 + Math.PI) % (2 * Math.PI) - Math.PI;
var a2 = (D21 - D23 + Math.PI) % (2 * Math.PI) - Math.PI;
if (Math.sin(a1) == 0 && Math.sin(a2) == 0) return null; // infinite intersections
if (Math.sin(a1) * Math.sin(a2) < 0) return null; // ambiguous intersection
//a1 = Math.abs(a1);
//a2 = Math.abs(a2);
// ... Ed Williams takes abs of a1/a2, but seems to break calculation?
var a3 = Math.acos(-Math.cos(a1) * Math.cos(a2) + Math.sin(a1) * Math.sin(a2) * Math.cos(d12));
var d13 = Math.atan2(Math.sin(d12) * Math.sin(a1) * Math.sin(a2), Math.cos(a2) + Math.cos(a1) * Math.cos(a3));
var f3 = Math.asin(Math.sin(f1) * Math.cos(d13) + Math.cos(f1) * Math.sin(d13) * Math.cos(D13));
var dl13 = Math.atan2(Math.sin(D13) * Math.sin(d13) * Math.cos(f1), Math.cos(d13) - Math.sin(f1) * Math.sin(f3));
var l3 = l1 + dl13;
return new LonLat((l3 * math.DEGREES + 540) % 360 - 180, f3 * math.DEGREES);
}
/**
* Returns ray vector hit ellipsoid coordinates.
* If the ray doesn't hit ellipsoid returns null.
* @public
* @param {og.math.Vector3} origin - Ray origin point.
* @param {og.math.Vector3} direction - Ray direction.
* @returns {og.math.Vector3} -
*/
hitRay(origin, direction) {
var q = this._invRadii.mul(origin);
var w = this._invRadii.mul(direction);
var q2 = q.dot(q);
var qw = q.dot(w);
var difference, w2, product, discriminant, temp;
if (q2 > 1.0) {
// Outside ellipsoid.
if (qw >= 0.0) {
// Looking outward or tangent (0 intersections).
return null;
}
// qw < 0.0.
var qw2 = qw * qw;
difference = q2 - 1.0; // Positively valued.
w2 = w.dot(w);
product = w2 * difference;
if (qw2 < product) {
// Imaginary roots (0 intersections).
return null;
} else if (qw2 > product) {
// Distinct roots (2 intersections).
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant); // Avoid cancellation.
var root0 = temp / w2;
var root1 = difference / temp;
if (root0 < root1) {
return origin.add(direction.scaleTo(root0));
}
return origin.add(direction.scaleTo(root1));
} else {
// qw2 == product. Repeated roots (2 intersections).
var root = Math.sqrt(difference / w2);
return origin.add(direction.scaleTo(root));
}
} else if (q2 < 1.0) {
// Inside ellipsoid (2 intersections).
difference = q2 - 1.0; // Negatively valued.
w2 = w.dot(w);
product = w2 * difference; // Negatively valued.
discriminant = qw * qw - product;
temp = -qw + Math.sqrt(discriminant); // Positively valued.
return origin.add(direction.scaleTo(temp / w2));
} else {
// q2 == 1.0. On ellipsoid.
if (qw < 0.0) {
// Looking inward.
w2 = w.dot(w);
return origin.add(direction.scaleTo(-qw / w2));
}
// qw >= 0.0. Looking outward or tangent.
return null;
}
}
};
export { Ellipsoid };

View File

@ -1,13 +0,0 @@
/**
* @module og/ellipsoid/wgs84
*/
'use strict';
import { Ellipsoid } from './Ellipsoid.js';
/**
* WGS84 ellipsoid object.
* @type {og.Ellipsoid}
*/
export const wgs84 = new Ellipsoid(6378137.000, 6356752.3142);

View File

@ -1,352 +0,0 @@
/**
* @module og/entity/BaseBillboard
*/
'use strict';
import * as utils from '../utils/shared.js';
/**
* Base prototype for billboard and label classes.
* @class
* @param {Object} [options] - Options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
*/
class BaseBillboard {
constructor(options) {
options = options || {};
/**
* Object unic identifier.
* @public
* @readonly
* @type {number}
*/
this.id = BaseBillboard._staticCounter++;
/**
* Billboard center cartesian position.
* @protected
* @type {og.math.Vector3}
*/
this._position = utils.createVector3(options.position);
/**
* Screen space rotation angle.
* @protected
* @type {number}
*/
this._rotation = options.rotation || 0;
/**
* RGBA color.
* @protected
* @type {og.math.Vector4}
*/
this._color = utils.createColorRGBA(options.color);
/**
* Cartesian aligned axis vector.
* @protected
* @type {og.math.Vector3}
*/
this._alignedAxis = utils.createVector3(options.alignedAxis);
/**
* Billboard center screen space offset. Where x,y - screen space offset and z - depth offset.
* @protected
* @type {og.math.Vecto3}
*/
this._offset = utils.createVector3(options.offset);
/**
* Billboard visibility.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility != undefined ? options.visibility : true;
/**
* Billboard scale.
* @protected
* @type {number}
*/
this._scale = options.scale || 1.0;
/**
* Entity instance that holds this billboard.
* @protected
* @type {og.Entity}
*/
this._entity = null;
/**
* Handler that stores and renders this billboard object.
* @protected
* @type {og.BillboardHandler}
*/
this._handler = null;
/**
* Billboard handler array index.
* @protected
* @type {number}
*/
this._handlerIndex = -1;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Sets billboard position.
* @public
* @param {number} x - X coordinate.
* @param {number} y - Y coordinate.
* @param {number} z - Z coordinate.
*/
setPosition(x, y, z) {
this._position.x = x;
this._position.y = y;
this._position.z = z;
this._handler && this._handler.setPositionArr(this._handlerIndex, this._position);
}
/**
* Sets billboard position.
* @public
* @param {og.math.Vector3} position - Cartesian coordinates.
*/
setPosition3v(position) {
this._position.x = position.x;
this._position.y = position.y;
this._position.z = position.z;
this._handler && this._handler.setPositionArr(this._handlerIndex, position);
}
/**
* Returns billboard position.
* @public
* @returns {og.math.Vector3}
*/
getPosition() {
return this._position;
}
/**
* Sets screen space offset.
* @public
* @param {number} x - X offset.
* @param {number} y - Y offset.
* @param {number} [z] - Z offset.
*/
setOffset(x, y, z) {
this._offset.x = x;
this._offset.y = y;
(z != undefined) && (this._offset.z = z);
this._handler && this._handler.setOffsetArr(this._handlerIndex, this._offset);
}
/**
* Sets billboard scale.
* @public
* @param {number} scale - Scale.
*/
setScale(scale) {
this._scale = scale;
this._handler && this._handler.setScaleArr(this._handlerIndex, scale);
}
/**
* Gets billboard scale.
* @public
* @returns {number}
*/
getScale() {
return this._scale;
}
/**
* Sets screen space offset.
* @public
* @param {og.math.Vector2} offset - Offset size.
*/
setOffset3v(offset) {
this._offset.x = offset.x;
this._offset.y = offset.y;
(offset.z != undefined) && (this._offset.z = offset.z);
this._handler && this._handler.setOffsetArr(this._handlerIndex, offset);
}
/**
* Returns billboard screen space offset size.
* @public
* @returns {og.math.Vector3}
*/
getOffset() {
return this._offset;
}
/**
* Sets billboard screen space rotation in radians.
* @public
* @param {number} rotation - Screen space rotation in radians.
*/
setRotation(rotation) {
this._rotation = rotation;
this._handler && this._handler.setRotationArr(this._handlerIndex, rotation);
}
/**
* Gets screen space rotation.
* @public
* @returns {number}
*/
getRotation() {
return this._rotation;
}
/**
* Sets billboard opacity.
* @public
* @param {number} a - Billboard opacity.
*/
setOpacity(a) {
this._color.w = a;
this.setColor(this._color.x, this._color.y, this._color.z, a);
}
/**
* Sets RGBA color. Each channel from 0.0 to 1.0.
* @public
* @param {number} r - Red.
* @param {number} g - Green.
* @param {number} b - Blue.
* @param {number} a - Alpha.
*/
setColor(r, g, b, a) {
this._color.x = r;
this._color.y = g;
this._color.z = b;
(a != undefined) && (this._color.w = a);
this._handler && this._handler.setRgbaArr(this._handlerIndex, this._color);
}
/**
* Sets RGBA color. Each channel from 0.0 to 1.0.
* @public
* @param {og.math.Vector4} color - RGBA vector.
*/
setColor4v(color) {
this._color.x = color.x;
this._color.y = color.y;
this._color.z = color.z;
(color.w != undefined) && (this._color.w = color.w);
this._handler && this._handler.setRgbaArr(this._handlerIndex, color);
}
/**
* Sets billboard color.
* @public
* @param {string} color - HTML style color.
*/
setColorHTML(color) {
this.setColor4v(og.utils.htmlColorToRgba(color));
}
/**
* Returns RGBA color.
* @public
* @returns {og.math.Vector4}
*/
getColor() {
return this._color;
}
/**
* Sets billboard visibility.
* @public
* @param {boolean} visibility - Visibility flag.
*/
setVisibility(visibility) {
this._visibility = visibility;
this._handler && this._handler.setVisibility(this._handlerIndex, visibility);
}
/**
* Returns billboard visibility.
* @public
* @returns {boolean}
*/
getVisibility() {
return this._visibility;
}
/**
* Sets billboard cartesian aligned vector.
* @public
* @param {number} x - Aligned vector X coordinate.
* @param {number} y - Aligned vector Y coordinate.
* @param {number} z - Aligned vector Z coordinate.
*/
setAlignedAxis(x, y, z) {
this._alignedAxis.x = x;
this._alignedAxis.y = y;
this._alignedAxis.z = z;
this._handler && this._handler.setAlignedAxisArr(this._handlerIndex, this._alignedAxis);
}
/**
* Sets billboard aligned vector.
* @public
* @param {og.math.Vecto3} alignedAxis - Vector to align.
*/
setAlignedAxis3v(alignedAxis) {
this._alignedAxis.x = alignedAxis.x;
this._alignedAxis.y = alignedAxis.y;
this._alignedAxis.z = alignedAxis.z;
this._handler && this._handler.setAlignedAxisArr(this._handlerIndex, alignedAxis);
}
/**
* Returns aligned vector.
* @public
* @returns {og.math.Vector3}
*/
getAlignedAxis() {
return this._alignedAxis;
}
/**
* Removes billboard from hander.
* @public
*/
remove() {
this._entity = null;
this._handler && this._handler.remove(this);
}
/**
* Sets billboard picking color.
* @public
* @param {og.math.Vector3} color - Picking color.
*/
setPickingColor3v(color) {
this._handler && this._handler.setPickingColorArr(this._handlerIndex, color);
}
};
export { BaseBillboard };

View File

@ -1,160 +0,0 @@
/**
* @module og/entity/Billboard
*/
'use strict';
import { BaseBillboard } from './BaseBillboard.js';
/**
* Represents basic quad billboard image.
* @class
* @extends {og.BaseBillboard}
* @param {Object} [options] - Options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
* @param {string} [options.src] - Billboard image url source.
* @param {Image} [options.image] - Billboard image object.
* @param {number} [options.width] - Screen width.
* @param {number} [options.height] - Screen height.
* @param {number} [options.scale] - Billboard scale.
*/
class Billboard extends BaseBillboard {
constructor(options) {
super(options);
options = options || {};
/**
* Image src.
* @protected
* @type {string}
*/
this._src = options.src || null;
/**
* Image object.
* @protected
* @type {Object}
*/
this._image = options.image || null;
/**
* Billboard screen width.
* @protected
* @type {number}
*/
this._width = options.width || (options.size ? options.size[0] : 30);
/**
* Billboard screen height.
* @protected
* @type {number}
*/
this._height = options.height || (options.size ? options.size[1] : 30);
}
/**
* Sets billboard image url source.
* @public
* @param {string} src - Image url.
*/
setSrc(src) {
this._src = src;
var bh = this._handler;
if (bh && src) {
var rn = bh._entityCollection.renderNode;
if (rn) {
var ta = rn.billboardsTextureAtlas;
var that = this;
ta.loadImage(src, function (img) {
if (ta.nodes[img.__nodeIndex]) {
that._image = img;
bh.setTexCoordArr(that._handlerIndex, ta.nodes[that._image.__nodeIndex].texCoords);
} else {
ta.addImage(img);
ta.createTexture();
that._image = img;
rn.updateBillboardsTexCoords();
}
});
}
}
}
/**
* Sets image object.
* @public
* @param {Object} image - JavaScript image object.
*/
setImage(image) {
this.setSrc(image.src);
}
/**
* Sets billboard screen size in pixels.
* @public
* @param {number} width - Billboard width.
* @param {number} height - Billboard height.
*/
setSize(width, height) {
this._width = width;
this._height = height;
this._handler && this._handler.setSizeArr(this._handlerIndex, width * this._scale, height * this._scale);
}
/**
* Returns billboard screen size.
* @public
* @returns {Object}
*/
getSize() {
return {
"width": this._width,
"height": this._height
};
}
/**
* Sets billboard screen width.
* @public
* @param {number} width - Width.
*/
setWidth(width) {
this.setSize(width, this._height);
}
/**
* Gets billboard screen width.
* @public
* @returns {number}
*/
getWidth() {
return this._width;
}
/**
* Sets billboard screen heigh.
* @public
* @param {number} height - Height.
*/
setHeight(height) {
this.setSize(this._width, height);
}
/**
* Gets billboard screen height.
* @public
* @returns {number}
*/
getHeight() {
return this._height;
}
};
export { Billboard };

View File

@ -1,736 +0,0 @@
/**
* @module og/entity/BillboardHandler
*/
'use strict';
import * as shaders from '../shaders/billboard.js';
const PICKINGCOLOR_BUFFER = 0;
const POSITION_BUFFER = 1;
const SIZE_BUFFER = 2;
const OFFSET_BUFFER = 3;
const RGBA_BUFFER = 4;
const ROTATION_BUFFER = 5;
const TEXCOORD_BUFFER = 6;
const VERTEX_BUFFER = 7;
const ALIGNEDAXIS_BUFFER = 8;
/*
* og.BillboardHandler
*
*
*/
class BillboardHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
this._entityCollection = entityCollection;
this._renderer = null;
this._billboards = [];
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._texCoordBuffer = null;
this._vertexBuffer = null;
this._alignedAxisBuffer = null;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._pickingColorBuffer = null;
this._pickingColorArr = [];
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[PICKINGCOLOR_BUFFER] = this.createPickingColorBuffer;
this._buffersUpdateCallbacks[POSITION_BUFFER] = this.createPositionBuffer;
this._buffersUpdateCallbacks[SIZE_BUFFER] = this.createSizeBuffer;
this._buffersUpdateCallbacks[OFFSET_BUFFER] = this.createOffsetBuffer;
this._buffersUpdateCallbacks[RGBA_BUFFER] = this.createRgbaBuffer;
this._buffersUpdateCallbacks[ROTATION_BUFFER] = this.createRotationBuffer;
this._buffersUpdateCallbacks[TEXCOORD_BUFFER] = this.createTexCoordBuffer;
this._buffersUpdateCallbacks[VERTEX_BUFFER] = this.createVertexBuffer;
this._buffersUpdateCallbacks[ALIGNEDAXIS_BUFFER] = this.createAlignedAxisBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this.__staticId = BillboardHandler.staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static concArr(dest, curr) {
for (var i = 0; i < curr.length; i++) {
dest.push(curr[i]);
}
}
initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.billboard) {
var isSingleBuffer = !this._renderer.isMultiFramebufferCompatible();
this._renderer.handler.addShaderProgram(shaders.billboard(isSingleBuffer));
}
if (!this._renderer.handler.shaderPrograms.billboardPicking) {
this._renderer.handler.addShaderProgram(shaders.billboardPicking());
}
}
}
setRenderer(renderer) {
this._renderer = renderer;
this.initShaderProgram();
}
refresh() {
var i = this._changedBuffers.length;
while (i--) {
this._changedBuffers[i] = true;
}
}
_removeBillboards() {
var i = this._billboards.length;
while (i--) {
var bi = this._billboards[i];
bi._handlerIndex = -1;
bi._handler = null;
}
this._billboards.length = 0;
this._billboards = [];
}
clear() {
this._texCoordArr.length = 0;
this._vertexArr.length = 0;
this._positionArr.length = 0;
this._sizeArr.length = 0;
this._offsetArr.length = 0;
this._rgbaArr.length = 0;
this._rotationArr.length = 0;
this._alignedAxisArr.length = 0;
this._pickingColorArr.length = 0;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._pickingColorArr = [];
this._removeBillboards();
this._deleteBuffers();
this.refresh();
}
_deleteBuffers() {
var gl = this._renderer.handler.gl;
gl.deleteBuffer(this._positionBuffer);
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._offsetBuffer);
gl.deleteBuffer(this._rgbaBuffer);
gl.deleteBuffer(this._rotationBuffer);
gl.deleteBuffer(this._vertexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._alignedAxisBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._vertexBuffer = null;
this._texCoordBuffer = null;
this._alignedAxisBuffer = null;
this._pickingColorBuffer = null;
}
update() {
if (this._renderer) {
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
}
}
add(billboard) {
if (billboard._handlerIndex == -1) {
billboard._handler = this;
billboard._handlerIndex = this._billboards.length;
this._billboards.push(billboard);
this._addBillboardToArrays(billboard);
this.refresh();
billboard.setSrc(billboard._src || billboard._image && billboard._image.src);
}
}
_addBillboardToArrays(billboard) {
if (billboard._visibility) {
BillboardHandler.concArr(this._vertexArr, [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
} else {
BillboardHandler.concArr(this._vertexArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
BillboardHandler.concArr(this._texCoordArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
var x = billboard._position.x, y = billboard._position.y, z = billboard._position.z, w = billboard._scale;
BillboardHandler.concArr(this._positionArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = billboard._width; y = billboard._height;
BillboardHandler.concArr(this._sizeArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = billboard._offset.x; y = billboard._offset.y; z = billboard._offset.z;
BillboardHandler.concArr(this._offsetArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = billboard._color.x; y = billboard._color.y; z = billboard._color.z; w = billboard._color.w;
BillboardHandler.concArr(this._rgbaArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = billboard._rotation;
BillboardHandler.concArr(this._rotationArr, [x, x, x, x, x, x]);
x = billboard._alignedAxis.x, y = billboard._alignedAxis.y, z = billboard._alignedAxis.z;
BillboardHandler.concArr(this._alignedAxisArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = billboard._entity._pickingColor.x / 255, y = billboard._entity._pickingColor.y / 255, z = billboard._entity._pickingColor.z / 255;
BillboardHandler.concArr(this._pickingColorArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
}
_displayPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.billboard.activate();
var sh = h.shaderPrograms.billboard._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniform1i(shu.u_texture._pName, 0);
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rgbaBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._rgbaBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_pickingPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.billboardPicking.activate();
var sh = h.shaderPrograms.billboardPicking._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.a_pickingColor._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
};
draw() {
if (this._billboards.length) {
this.update();
this._displayPASS();
}
}
drawPicking() {
if (this._billboards.length && this.pickingEnabled) {
this._pickingPASS();
}
}
reindexBillbordsArray(startIndex) {
var b = this._billboards;
for (var i = startIndex; i < b.length; i++) {
b[i]._handlerIndex = i;
}
}
_removeBillboard(billboard) {
var bi = billboard._handlerIndex;
this._billboards.splice(bi, 1);
var i = bi * 24;
this._rgbaArr.splice(i, 24);
this._positionArr.splice(i, 24);
i = bi * 18;
this._offsetArr.splice(i, 18);
this._alignedAxisArr.splice(i, 18);
this._pickingColorArr.splice(i, 18);
i = bi * 12;
this._vertexArr.splice(i, 12);
this._sizeArr.splice(i, 12);
this._texCoordArr.splice(i, 12);
i = bi * 6;
this._rotationArr.splice(i, 6);
this.reindexBillbordsArray(bi);
this.refresh();
billboard._handlerIndex = -1;
billboard._handler = null;
}
remove(billboard) {
if (billboard._handler && this.__staticId == billboard._handler.__staticId) {
this._removeBillboard(billboard);
}
}
setPositionArr(index, position) {
var i = index * 24;
var a = this._positionArr, x = position.x, y = position.y, z = position.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = z;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 16] = x;
a[i + 17] = y;
a[i + 18] = z;
a[i + 20] = x;
a[i + 21] = y;
a[i + 22] = z;
this._changedBuffers[POSITION_BUFFER] = true;
}
setScaleArr(index, scale) {
var i = index * 24;
var a = this._positionArr;
a[i + 3] = scale;
a[i + 7] = scale;
a[i + 11] = scale;
a[i + 15] = scale;
a[i + 19] = scale;
a[i + 23] = scale;
this._changedBuffers[POSITION_BUFFER] = true;
}
setPickingColorArr(index, color) {
var i = index * 18;
var a = this._pickingColorArr, x = color.x / 255, y = color.y / 255, z = color.z / 255;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[PICKINGCOLOR_BUFFER] = true;
}
setSizeArr(index, width, height) {
var i = index * 12;
var a = this._sizeArr, x = width, y = height;
a[i] = x;
a[i + 1] = y;
a[i + 2] = x;
a[i + 3] = y;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = x;
a[i + 11] = y;
this._changedBuffers[SIZE_BUFFER] = true;
}
setOffsetArr(index, offset) {
var i = index * 18;
var a = this._offsetArr, x = offset.x, y = offset.y, z = offset.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[OFFSET_BUFFER] = true;
}
setRgbaArr(index, rgba) {
var i = index * 24;
var a = this._rgbaArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = w;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = z;
a[i + 7] = w;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = z;
a[i + 11] = w;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = w;
a[i + 16] = x;
a[i + 17] = y;
a[i + 18] = z;
a[i + 19] = w;
a[i + 20] = x;
a[i + 21] = y;
a[i + 22] = z;
a[i + 23] = w;
this._changedBuffers[RGBA_BUFFER] = true;
}
setRotationArr(index, rotation) {
var i = index * 6;
var a = this._rotationArr;
a[i] = rotation;
a[i + 1] = rotation;
a[i + 2] = rotation;
a[i + 3] = rotation;
a[i + 4] = rotation;
a[i + 5] = rotation;
this._changedBuffers[ROTATION_BUFFER] = true
}
setTexCoordArr(index, tcoordArr) {
var i = index * 12;
var a = this._texCoordArr;
a[i] = tcoordArr[0];
a[i + 1] = tcoordArr[1];
a[i + 2] = tcoordArr[2];
a[i + 3] = tcoordArr[3];
a[i + 4] = tcoordArr[4];
a[i + 5] = tcoordArr[5];
a[i + 6] = tcoordArr[6];
a[i + 7] = tcoordArr[7];
a[i + 8] = tcoordArr[8];
a[i + 9] = tcoordArr[9];
a[i + 10] = tcoordArr[10];
a[i + 11] = tcoordArr[11];
this._changedBuffers[TEXCOORD_BUFFER] = true;
}
setVisibility(index, visibility) {
var vArr;
if (visibility) {
vArr = [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5];
} else {
vArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
this.setVertexArr(index, vArr);
}
setVertexArr(index, vertexArr) {
var i = index * 12;
var a = this._vertexArr;
a[i] = vertexArr[0];
a[i + 1] = vertexArr[1];
a[i + 2] = vertexArr[2];
a[i + 3] = vertexArr[3];
a[i + 4] = vertexArr[4];
a[i + 5] = vertexArr[5];
a[i + 6] = vertexArr[6];
a[i + 7] = vertexArr[7];
a[i + 8] = vertexArr[8];
a[i + 9] = vertexArr[9];
a[i + 10] = vertexArr[10];
a[i + 11] = vertexArr[11];
this._changedBuffers[VERTEX_BUFFER] = true;
}
setAlignedAxisArr(index, alignedAxis) {
var i = index * 18;
var a = this._alignedAxisArr, x = alignedAxis.x, y = alignedAxis.y, z = alignedAxis.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[ALIGNEDAXIS_BUFFER] = true;
}
createPositionBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._positionBuffer);
this._positionBuffer = h.createArrayBuffer(new Float32Array(this._positionArr), 4, this._positionArr.length / 4, h.gl.DYNAMIC_DRAW);
}
createSizeBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._sizeBuffer);
this._sizeBuffer = h.createArrayBuffer(new Float32Array(this._sizeArr), 2, this._sizeArr.length / 2);
}
createOffsetBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._offsetBuffer);
this._offsetBuffer = h.createArrayBuffer(new Float32Array(this._offsetArr), 3, this._offsetArr.length / 3);
}
createRgbaBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._rgbaBuffer);
this._rgbaBuffer = h.createArrayBuffer(new Float32Array(this._rgbaArr), 4, this._rgbaArr.length / 4);
}
createRotationBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._rotationBuffer);
this._rotationBuffer = h.createArrayBuffer(new Float32Array(this._rotationArr), 1, this._rotationArr.length, h.gl.DYNAMIC_DRAW);
}
createVertexBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._vertexBuffer);
this._vertexBuffer = h.createArrayBuffer(new Float32Array(this._vertexArr), 2, this._vertexArr.length / 2, h.gl.DYNAMIC_DRAW);
}
createTexCoordBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._texCoordBuffer);
this._texCoordBuffer = h.createArrayBuffer(new Float32Array(this._texCoordArr), 2, this._texCoordArr.length / 2, h.gl.DYNAMIC_DRAW);
}
createAlignedAxisBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._alignedAxisBuffer);
this._alignedAxisBuffer = h.createArrayBuffer(new Float32Array(this._alignedAxisArr), 3, this._alignedAxisArr.length / 3);
}
createPickingColorBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._pickingColorBuffer);
this._pickingColorBuffer = h.createArrayBuffer(new Float32Array(this._pickingColorArr), 3, this._pickingColorArr.length / 3);
}
refreshTexCoordsArr() {
var bc = this._entityCollection;
if (bc && bc.renderNode) {
var ta = bc.renderNode.billboardsTextureAtlas;
for (var i = 0; i < this._billboards.length; i++) {
var bi = this._billboards[i];
var img = bi._image;
if (img) {
var imageNode = ta.nodes[bi._image.__nodeIndex];
if (imageNode) {
this.setTexCoordArr(bi._handlerIndex, imageNode.texCoords);
}
}
}
}
}
};
export { BillboardHandler };

View File

@ -1,607 +0,0 @@
/**
* @module og/entity/Entity
*/
'use strict';
import * as mercator from '../mercator.js';
import * as utils from '../utils/shared.js';
import { Billboard } from './Billboard.js';
//import { Box } from '../shapes/Box.js';
import { Extent } from '../Extent.js';
import { Geometry } from './Geometry.js';
import { Label } from './Label.js';
import { LonLat } from '../LonLat.js';
import { Polyline } from './Polyline.js';
import { PointCloud } from './PointCloud.js';
//import { Sphere } from '../shapes/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Entity instances aggregate multiple forms of visualization into a single high-level object.
* They can be created manually and added to entity collection.
*
* @class
* @param {Object} [options] - Entity options:
* @param {string} [options.name] - A human readable name to display to users. It does not have to be unique.
* @param {og.math.Vector3|Array.<number>} [options.cartesian] - Spatial entities like billboard, label, sphere etc. cartesian position.
* @param {og.LonLat} [options.lonlat] - Geodetic coordiantes for an entities like billboard, label, sphere etc.
* @param {boolean} [options.aground] - True for entities that have to be placed on the relief.
* @param {boolean} [options.visibility] - Entity visibility.
* @param {*} [options.billboard] - Billboard options(see {@link og.Billboard}).
* @param {*} [options.label] - Label options(see {@link og.Label}).
* @param {*} [options.sphere] - Sphere options(see {@link og.shape.Sphere}).
* @param {*} [options.box] - Sphere options(see {@link og.shape.Box}).
* @param {*} [options.Polyline] - Polyline options(see {@link og.Polyline}).
* @param {*} [options.pointCloud] - Point cloud options(see {@link og.PointCloud}).
* @param {*} [options.geometry] - Geometry options (see {@link og.Geometry}), available for vector layer only.
* @param {*} [options.properties] - Entity custom properties.
*/
class Entity {
constructor(options) {
options = options || {};
options.properties = options.properties || {};
/**
* Unic identifier.
* @public
* @readonly
*/
this.id = Entity.__staticCounter++;
/**
* Entity user defined properties.
* @public
* @type {Object}
*/
this.properties = options.properties || {};
/**
* Entity name.
* @public
* @type {string}
*/
this.properties.name = this.properties.name || "noname";
/**
* Children entities.
* @public
* @type {Array.<og.Entity>}
*/
this.childrenNodes = [];
/**
* Parent entity.
* @public
* @type {og.Entity}
*/
this.parent = null;
/**
* Entity cartesian position.
* @protected
* @type {og.math.Vector3}
*/
this._cartesian = utils.createVector3(options.cartesian);
/**
* Geodetic entity coordiantes.
* @protected
* @type {og.LonLat}
*/
this._lonlat = utils.createLonLat(options.lonlat);
/**
* World Mercator entity coordinates.
* @protected
* @type {og.LonLat}
*/
this._lonlatMerc = null;
/**
* Entity visible terrain altitude.
* @protected
* @type {number}
*/
this._altitude = options.altitude || 0.0;
/**
* Visibility flag.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility != undefined ? options.visibility : true;
/**
* Entity collection that this entity belongs to.
* @protected
* @type {og.EntityCollection}
*/
this._entityCollection = null;
/**
* Entity collection array store index.
* @protected
* @type {number}
*/
this._entityCollectionIndex = -1;
/**
* Assigned vector layer pointer.
* @protected
* @type {og.layer.Vector}
*/
this._layer = null;
/**
* Assigned vector layer entity array index.
* @protected
* @type {number}
*/
this._layerIndex = -1;
/**
* Picking color.
* @protected
* @type {og.math.Vector3}
*/
this._pickingColor = new Vec3(0, 0, 0);
this._featureConstructorArray = {
"billboard": [Billboard, this.setBillboard],
"label": [Label, this.setLabel],
"sphere": [Sphere, this.setShape],
"box": [Box, this.setShape],
"polyline": [Polyline, this.setPolyline],
"pointCloud": [PointCloud, this.setPointCloud],
"geometry": [Geometry, this.setGeometry],
};
/**
* Billboard entity.
* @public
* @type {og.Billboard}
*/
this.billboard = this._createOptionFeature('billboard', options.billboard);
/**
* Text label entity.
* @public
* @type {og.Label}
*/
this.label = this._createOptionFeature('label', options.label);
/**
* Shape entity.
* @public
* @type {og.shape.BaseShape}
*/
this.shape = this._createOptionFeature('sphere', options.sphere || options.box);
/**
* Polyline entity.
* @public
* @type {og.Polyline}
*/
this.polyline = this._createOptionFeature('polyline', options.polyline);
/**
* PointCloud entity.
* @public
* @type {og.PointCloud}
*/
this.pointCloud = this._createOptionFeature('pointCloud', options.pointCloud);
/**
* Geometry entity(available only for vector layer).
* @public
* @type {og.Geometry}
*/
this.geometry = this._createOptionFeature('geometry', options.geometry);
//this.model = null;
//...
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_createOptionFeature(featureName, options) {
if (options) {
var c = this._featureConstructorArray[featureName];
return c[1].call(this, new c[0](options));
}
return null;
}
/**
* Adds current entity into the specified entity collection.
* @public
* @param {og.EntityCollection|og.layer.Vector} collection - Specified entity collection or vector layer.
* @param {Boolean} [rightNow=false] - Entity insertion option for vector layer.
* @returns {og.Entity} - This object.
*/
addTo(collection, rightNow) {
collection.add(this, rightNow);
return this;
}
/**
* Removes current entity from collection and layer.
* @public
*/
remove() {
this._layer && this._layer.removeEntity(this);
this._entityCollection && this._entityCollection.removeEntity(this);
}
/**
* Sets the entity visibility.
* @public
* @param {boolean} visibility - Entity visibility.
*/
setVisibility(visibility) {
this._visibility = visibility;
//billboards
this.billboard && this.billboard.setVisibility(visibility);
//labels
this.label && this.label.setVisibility(visibility);
//shape
this.shape && this.shape.setVisibility(visibility);
//polyline
this.polyline && this.polyline.setVisibility(visibility);
//geometry
this.geometry && this.geometry.setVisibility(visibility);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setVisibility(visibility);
}
}
/**
* Returns entity visibility.
* @public
* @returns {boolean} -
*/
getVisibility() {
return this._visibility;
}
/**
* Sets entity cartesian position.
* @public
* @param {og.math.Vector3} cartesian - Cartesian position in 3d space.
*/
setCartesian3v(cartesian) {
this.setCartesian(cartesian.x, cartesian.y, cartesian.z);
}
/**
* Sets entity cartesian position.
* @public
* @param {number} x - 3d space X - position.
* @param {number} y - 3d space Y - position.
* @param {number} z - 3d space Z - position.
*/
setCartesian(x, y, z) {
var p = this._cartesian;
p.x = x;
p.y = y;
p.z = z;
//billboards
this.billboard && this.billboard.setPosition3v(p);
//labels
this.label && this.label.setPosition3v(p);
//shape
this.shape && this.shape.setPosition3v(p);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setCartesian(x, y, z);
}
var ec = this._entityCollection;
if (ec && ec.renderNode && ec.renderNode.ellipsoid) {
this._lonlat = ec.renderNode.ellipsoid.cartesianToLonLat(p);
if (Math.abs(this._lonlat.lat) < mercator.MAX_LAT) {
this._lonlatMerc = this._lonlat.forwardMercator();
} else {
this._lonlatMerc = null;
}
}
ec && ec.events.dispatch(ec.events.entitymove, this);
}
/**
* Sets entity cartesian position without moveentity event dispatching.
* @protected
* @param {og.math.Vector3} cartesian - Cartesian position in 3d space.
*/
_setCartesian3vSilent(cartesian) {
var p = this._cartesian;
p.x = cartesian.x;
p.y = cartesian.y;
p.z = cartesian.z;
//billboards
this.billboard && this.billboard.setPosition3v(p);
//labels
this.label && this.label.setPosition3v(p);
//shape
this.shape && this.shape.setPosition3v(p);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setCartesian(x, y, z);
}
}
/**
* Gets entity geodetic coordinates.
* @public
* @returns {og.LonLat} -
*/
getLonLat() {
return this._lonlat.clone();
}
/**
* Sets geodetic coordinates of the entity point object.
* @public
* @param {og.LonLat} lonlat - WGS84 coordinates.
*/
setLonLat(lonlat) {
var l = this._lonlat;
l.lon = lonlat.lon;
l.lat = lonlat.lat;
l.height = lonlat.height;
var ec = this._entityCollection;
if (ec && ec.renderNode && ec.renderNode.ellipsoid) {
if (Math.abs(lonlat.lat) < mercator.MAX_LAT) {
this._lonlatMerc = lonlat.forwardMercator();
} else {
this._lonlatMerc = null;
}
this._cartesian = ec.renderNode.ellipsoid.lonLatToCartesian(lonlat);
this.setCartesian3v(this._cartesian);
}
}
/**
* Sets entity altitude over the planet.
* @public
* @param {number} altitude - Altitude.
*/
setAltitude(altitude) {
this._altitude = altitude;
}
/**
* Returns carteain position.
* @public
* @returns {og.math.Vector3} -
*/
getCartesian() {
return this._cartesian;
}
/**
* Sets entity billboard.
* @public
* @param {og.Billboard} billboard - Billboard object.
* @returns {og.Billboard} -
*/
setBillboard(billboard) {
if (this.billboard) {
this.billboard.remove();
}
this.billboard = billboard;
this.billboard._entity = this;
this.billboard.setPosition3v(this._cartesian);
this.billboard.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._billboardHandler.add(billboard);
return billboard;
}
/**
* Sets entity label.
* @public
* @param {og.Label} label - Text label.
* @returns {og.Label} -
*/
setLabel(label) {
if (this.label) {
this.label.remove();
}
this.label = label;
this.label._entity = this;
this.label.setPosition3v(this._cartesian);
this.label.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._labelHandler.add(label);
return label;
}
/**
* Sets entity shape.
* @public
* @param {og.BaseShape} shape - Shape object.
* @returns {og.Polyline} -
*/
setShape(shape) {
if (this.shape) {
this.shape.remove();
}
this.shape = shape;
this.shape._entity = this;
this.shape.setPosition3v(this._cartesian);
this.shape.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._shapeHandler.add(shape);
return shape;
}
/**
* Sets entity polyline.
* @public
* @param {og.Polyline} polyline - Polyline object.
* @returns {og.Polyline} -
*/
setPolyline(polyline) {
if (this.polyline) {
this.polyline.remove();
}
this.polyline = polyline;
this.polyline._entity = this;
this.polyline.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._polylineHandler.add(polyline);
return polyline;
}
/**
* Sets entity pointCloud.
* @public
* @param {og.PointCloud} pointCloud - PointCloud object.
* @returns {og.PointCloud} -
*/
setPointCloud(pointCloud) {
if (this.pointCloud) {
this.pointCloud.remove();
}
this.pointCloud = pointCloud;
this.pointCloud._entity = this;
this.pointCloud.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._pointCloudHandler.add(pointCloud);
return pointCloud;
}
/**
* Sets entity geometry.
* @public
* @param {og.Geometry} geometry - Geometry object.
* @returns {og.Geometry} -
*/
setGeometry(geometry) {
if (this.geometry) {
this.geometry.remove();
}
this.geometry = geometry;
this.geometry._entity = this;
this.geometry.setVisibility(this._visibility);
this._layer && this._layer.add(this);
return geometry;
}
/**
* Append child entity.
* @public
* @param {og.Entity} entity - Child entity.
*/
appendChild(entity) {
entity._entityCollection = this._entityCollection;
entity._pickingColor = this._pickingColor;
entity.parent = this;
this.childrenNodes.push(entity);
this._entityCollection && this._entityCollection._addRecursively(entity);
}
/**
* Appends entity items(billboard, label etc.) picking color.
* @public
*/
setPickingColor() {
var c = this._pickingColor;
//billboard
this.billboard && this.billboard.setPickingColor3v(c);
//label
this.label && this.label.setPickingColor3v(c);
//shape
this.shape && this.shape.setPickingColor3v(c);
//polyline
this.polyline && this.polyline.setPickingColor3v(c);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setPickingColor();
}
}
/**
* Return geodethic extent.
* @returns {og.Extent} -
*/
getExtent() {
var res;
var c = this._lonlat;
if (this.billboard || this.label) {
res = new Extent(new LonLat(c.lon, c.lat), new LonLat(c.lon, c.lat));
} else {
res = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
}
var sw = res.southWest,
ne = res.northEast;
if (this.polyline) {
var e = this.polyline.getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
if (this.geometry) {
var e = this.geometry.getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
for (var i = 0; i < this.childrenNodes.length; i++) {
var e = this.childrenNodes[i].getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
return res;
}
};
export { Entity };

View File

@ -1,774 +0,0 @@
/**
* @module og/entity/EntityCollection
*/
'use strict';
import * as math from '../math.js';
import { BillboardHandler } from './BillboardHandler.js';
import { Events } from '../Events.js';
import { LabelHandler } from './LabelHandler.js';
import { PolylineHandler } from './PolylineHandler.js';
import { PointCloudHandler } from './PointCloudHandler.js';
import { ShapeHandler } from './ShapeHandler.js';
/**
* An observable collection of og.Entity instances where each entity has a unique id.
* Entity collection provide handlers for an each type of entity like billboard, label or 3ds object.
* @constructor
* @param {Object} [options] - Entity options:
* @param {Array.<og.Entity>} [options.entities] - Entities array.
* @param {boolean} [options.visibility=true] - Entity visibility.
* @param {Array.<number,number,number>} [options.scaleByDistance] - Entity scale by distance parameters.
* First index - near distance to the entity, after entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @param {number} [options.opacity] - Entity global opacity.
* @param {boolean} [options.pickingEnabled=true] - Entity picking enable.
* @fires og.EntityCollection#entitymove
* @fires og.EntityCollection#draw
* @fires og.EntityCollection#drawend
* @fires og.EntityCollection#add
* @fires og.EntityCollection#remove
* @fires og.EntityCollection#entityadd
* @fires og.EntityCollection#entityremove
* @fires og.EntityCollection#visibilitychange
* @fires og.EntityCollection#mousemove
* @fires og.EntityCollection#mouseenter
* @fires og.EntityCollection#mouseleave
* @fires og.EntityCollection#lclick
* @fires og.EntityCollection#rclick
* @fires og.EntityCollection#mclick
* @fires og.EntityCollection#ldblclick
* @fires og.EntityCollection#rdblclick
* @fires og.EntityCollection#mdblclick
* @fires og.EntityCollection#lup
* @fires og.EntityCollection#rup
* @fires og.EntityCollection#mup
* @fires og.EntityCollection#ldown
* @fires og.EntityCollection#rdown
* @fires og.EntityCollection#mdown
* @fires og.EntityCollection#lhold
* @fires og.EntityCollection#rhold
* @fires og.EntityCollection#mhold
* @fires og.EntityCollection#mousewheel
* @fires og.EntityCollection#touchmove
* @fires og.EntityCollection#touchstart
* @fires og.EntityCollection#touchend
* @fires og.EntityCollection#doubletouch
* @fires og.EntityCollection#touchleave
* @fires og.EntityCollection#touchenter
*/
class EntityCollection {
constructor(options) {
options = options || {};
/**
* Unic identifier.
* @public
* @readonly
*/
this.id = EntityCollection.__staticCounter++;
/**
* Render node collections array index.
* @protected
* @type {number}
*/
this._renderNodeIndex = -1;
/**
* Render node context.
* @public
* @type {og.scene.RenderNode}
*/
this.renderNode = null;
/**
* Visibility option.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility == undefined ? true : options.visibility;
/**
* Billboards handler
* @public
* @type {og.BillboardHandler}
*/
this.billboardHandler = new BillboardHandler(this);
/**
* Labels handler
* @public
* @type {og.LabelHandler}
*/
this.labelHandler = new LabelHandler(this);
/**
* Shape handler
* @public
* @type {og.ShapeHandler}
*/
this.shapeHandler = new ShapeHandler(this);
/**
* Polyline handler
* @public
* @type {og.PolylineHandler}
*/
this.polylineHandler = new PolylineHandler(this);
/**
* PointCloud handler
* @public
* @type {og.PointCloudHandler}
*/
this.pointCloudHandler = new PointCloudHandler(this);
//
//...
if (options.pickingEnabled != undefined) {
this.setPickingEnabled(options.pickingEnabled);
}
/**
* Entities array.
* @protected
* @type {Array.<og.Entity>}
*/
this._entities = options.entities || [];
/**
* First index - near distance to the entity, after entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @public
* @type {Array.<number,number,number>}
*/
this.scaleByDistance = options.scaleByDistance || [math.MAX32, math.MAX32, math.MAX32];
/**
* Global opacity.
* @protected
* @type {number}
*/
this._opacity = options.opacity == undefined ? 1.0 : options.opacity;
/**
* Opacity state during the animated opacity.
* @protected
* @type {number}
*/
this._animatedOpacity = this._opacity;
/**
* Entity collection events handler.
* @public
* @type {og.Events}
*/
this.events = new Events(EVENT_NAMES);
//initialize current entities
this.addEntities(this._entities);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Sets collection visibility.
* @public
* @param {boolean} visibility - Visibility flag.
*/
setVisibility(visibility) {
this._visibility = visibility;
this._animatedOpacity = this._opacity * (visibility ? 1 : 0);
this.events.dispatch(this.events.visibilitychange, this);
}
/**
* Returns collection visibility.
* @public
* @returns {boolean}
*/
getVisibility() {
return this._visibility;
}
/**
* Sets collection opacity.
* @public
* @param {number} opacity - Opacity.
*/
setOpacity(opacity) {
this._opacity = opacity;
}
/**
* Sets collection picking ability.
* @public
* @param {boolean} enable - Picking enable flag.
*/
setPickingEnabled(enable) {
this.billboardHandler.pickingEnabled = enable;
this.labelHandler.pickingEnabled = enable;
this.polylineHandler.pickingEnabled = enable;
this.shapeHandler.pickingEnabled = enable;
this.pointCloudHandler.pickingEnabled = enable;
}
/**
* Gets collection opacity.
* @public
* @param {number} opacity - Opacity.
*/
getOpacity() {
return this._opacity;
}
/**
* Sets scale by distance parameters.
* @public
* @param {number} near - Full scale entity distance.
* @param {number} far - Zerol scale entity distance.
* @param {number} [farInvisible] - Entity visibility distance.
*/
setScaleByDistance(near, far, farInvisible) {
this.scaleByDistance[0] = near;
this.scaleByDistance[1] = far;
this.scaleByDistance[2] = farInvisible || math.MAX32;
}
_addRecursively(entity) {
//billboard
entity.billboard && this.billboardHandler.add(entity.billboard);
//label
entity.label && this.labelHandler.add(entity.label);
//shape
entity.shape && this.shapeHandler.add(entity.shape);
//polyline
entity.polyline && this.polylineHandler.add(entity.polyline);
//pointCloud
entity.pointCloud && this.pointCloudHandler.add(entity.pointCloud);
this.events.dispatch(this.events.entityadd, entity);
for (var i = 0; i < entity.childrenNodes.length; i++) {
entity.childrenNodes[i]._entityCollection = this;
entity.childrenNodes[i]._entityCollectionIndex = entity._entityCollectionIndex;
entity.childrenNodes[i]._pickingColor = entity._pickingColor;
this._addRecursively(entity.childrenNodes[i]);
}
}
/**
* Adds entity to the collection and returns collection.
* @public
* @param {og.Entity} entity - Entity.
* @returns {og.EntityCollection}
*/
add(entity) {
if (!entity._entityCollection) {
entity._entityCollection = this;
entity._entityCollectionIndex = this._entities.length;
this._entities.push(entity);
var rn = this.renderNode;
if (rn) {
rn.renderer && rn.renderer.assignPickingColor(entity);
rn.ellipsoid && entity._lonlat && entity.setCartesian3v(rn.ellipsoid.lonLatToCartesian(entity._lonlat));
}
this._addRecursively(entity);
}
return this;
}
/**
* Adds entities array to the collection and returns collection.
* @public
* @param {Array.<og.Entity>} entities - Entities array.
* @returns {og.EntityCollection}
*/
addEntities(entities) {
var i = entities.length;
while (i--) {
this.add(entities[i]);
}
return this;
}
/**
* Returns true if the entity belongs this collection, otherwise returns false.
* @public
* @param {og.Entity} entity - Entity.
* @returns {boolean}
*/
belongs(entity) {
return (entity._entityCollection && this._renderNodeIndex == entity._entityCollection._renderNodeIndex);
}
_removeRecursively(entity) {
entity._entityCollection = null;
entity._entityCollectionIndex = -1;
//billboard
entity.billboard && this.billboardHandler.remove(entity.billboard);
//label
entity.label && this.labelHandler.remove(entity.label);
//shape
entity.shape && this.shapeHandler.remove(entity.shape);
//polyline
entity.polyline && this.polylineHandler.remove(entity.polyline);
//pointCloud
entity.pointCloud && this.pointCloudHandler.remove(entity.pointCloud);
for (var i = 0; i < entity.childrenNodes.length; i++) {
this._removeRecursively(entity.childrenNodes[i]);
}
}
/**
* Removes entity from this collection.
* @public
* @param {og.Entity} entity - Entity to remove.
*/
removeEntity(entity) {
this._entities.splice(entity._entityCollectionIndex, 1);
this.reindexEntitiesArray(entity._entityCollectionIndex);
//clear picking color
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(entity);
entity._pickingColor.clear();
}
if (this.belongs(entity)) {
this._removeRecursively(entity);
}
this.events.dispatch(this.events.entityremove, entity);
}
_removeEntitySilent(entity) {
this._entities.splice(entity._entityCollectionIndex, 1);
this.reindexEntitiesArray(entity._entityCollectionIndex);
//clear picking color
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(entity);
entity._pickingColor.clear();
}
if (this.belongs(entity)) {
this._removeRecursively(entity);
}
}
/**
* Creates or refresh collected entities picking color.
* @public
*/
createPickingColors() {
var e = this._entities;
for (var i = 0; i < e.length; i++) {
if (!e[i].parent) {
this.renderNode.renderer.assignPickingColor(e[i]);
e[i].setPickingColor();
}
}
}
/**
* Refresh collected entities indexes from startIndex entitytes collection array position.
* @public
* @param {number} startIndex - Entities collection array index.
*/
reindexEntitiesArray(startIndex) {
var e = this._entities;
for (var i = startIndex; i < e.length; i++) {
e[i]._entityCollectionIndex = i;
}
}
/**
* Adds this collection to render node.
* @public
* @param {og.scene.RenderNode} renderNode - Render node.
* @param {boolean} [isHidden] - Uses in vector layers that render in planet render specific function.
* @returns {og.EntityCollection}
*/
addTo(renderNode, isHidden) {
if (!this.renderNode) {
this.renderNode = renderNode;
if (!isHidden) {
this._renderNodeIndex = renderNode.entityCollections.length;
renderNode.entityCollections.push(this);
}
renderNode.ellipsoid && this._updateGeodeticCoordinates(renderNode.ellipsoid);
this.setRenderer(renderNode.renderer);
this.shapeHandler.setRenderNode(renderNode);
this.polylineHandler.setRenderNode(renderNode);
this.pointCloudHandler.setRenderNode(renderNode);
this.events.dispatch(this.events.add, this);
}
return this;
}
/**
* Updates coordiantes all lonLat entities in collection after collecction attached to the planet node.
* @private
* @param {og.Ellipsoid} ellipsoid - Globe ellipsoid.
*/
_updateGeodeticCoordinates(ellipsoid) {
var e = this._entities;
var i = e.length;
while (i--) {
var ei = e[i];
ei._lonlat && ei.setCartesian3v(ellipsoid.lonLatToCartesian(ei._lonlat));
}
}
/**
* Sets renderer. Used in renderer initialization, when entity collection starts before renderer has initialized.
* @public
* @param {og.Renderer} renderer - Renderer.
*/
setRenderer(renderer) {
//todo: better to replace to setRenderNode function
if (renderer) {
this.billboardHandler.setRenderer(renderer);
this.labelHandler.setRenderer(renderer);
this.updateBillboardsTextureAtlas();
this.updateLabelsFontAtlas();
this.createPickingColors();
}
}
/**
* Updates billboard texture atlas.
* @public
*/
updateBillboardsTextureAtlas() {
var b = this.billboardHandler._billboards;
for (var i = 0; i < b.length; i++) {
b[i].setSrc(b[i]._src);
}
}
/**
* Updates labels font atlas.
* @public
*/
updateLabelsFontAtlas() {
if (this.renderNode) {
var l = this.labelHandler._billboards;
for (var i = 0; i < l.length; i++) {
l[i].assignFontAtlas(this.renderNode.fontAtlas);
}
}
}
/**
* Removes collection from render node.
* @public
*/
remove() {
if (this.renderNode) {
if (this._renderNodeIndex != -1) {
this.renderNode.entityCollections.splice(this._renderNodeIndex, 1);
//reindex in the renderNode
for (var i = this._renderNodeIndex; i < this.renderNode.entityCollections.length; i++) {
this.renderNode.entityCollections._renderNodeIndex = i;
}
}
this.renderNode = null;
this._renderNodeIndex = -1;
this.events.dispatch(this.events.remove, this);
}
}
/**
* Gets entities.
* @public
* @returns {Array.<og.Entity>}
*/
getEntities() {
return [].concat(this._entities);
}
/**
* Safety entities loop.
* @public
* @param {function} callback - Entity callback.
*/
each(callback) {
var i = this._entities.length;
while (i--) {
var ei = this._entities[i];
ei && callback(ei);
}
}
/**
* Removes all entities from colection and clear handlers.
* @public
*/
clear() {
//TODO: Optimize by replace delete
//code to the clearEntity function.
this.billboardHandler.clear();
this.labelHandler.clear();
this.shapeHandler.clear();
this.polylineHandler.clear();
this.pointCloudHandler.clear();
var i = this._entities.length;
while (i--) {
var ei = this._entities[i];
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(ei);
ei._pickingColor.clear();
}
this._clearEntity(ei);
}
this._entities.length = 0;
this._entities = [];
}
/**
* Clears entity recursevely.
* @private
* @param {og.Entity} entity - Entity to clear.
*/
_clearEntity(entity) {
entity._entityCollection = null;
entity._entityCollectionIndex = -1;
for (var i = 0; i < entity.childrenNodes.length; i++) {
this._clearEntity(entity.childrenNodes[i]);
}
}
};
const EVENT_NAMES = [
/**
* Triggered when entity has moved.
* @event og.EntityCollection#entitymove
*/
"entitymove",
/**
* Triggered when collection entities begin draw.
* @event og.EntityCollection#draw
*/
"draw",
/**
* Triggered after collection has drawn.
* @event og.EntityCollection#drawend
*/
"drawend",
/**
* Triggered when added to the render node.
* @event og.EntityCollection#add
*/
"add",
/**
* Triggered when removed from the render node.
* @event og.EntityCollection#remove
*/
"remove",
/**
* Triggered when new entity added to the collection.
* @event og.EntityCollection#entityadd
*/
"entityadd",
/**
* Triggered when entity removes from the collection.
* @event og.EntityCollection#entityremove
*/
"entityremove",
/**
* Triggered when visibility changes.
* @event og.EntityCollection#visibilitychange
*/
"visibilitychange",
/**
* Triggered when mouse moves over the entity.
* @event og.EntityCollection#mousemove
*/
"mousemove",
/**
* Triggered when mouse has entered over the entity.
* @event og.EntityCollection#mouseenter
*/
"mouseenter",
/**
* Triggered when mouse leaves the entity.
* @event og.EntityCollection#mouseleave
*/
"mouseleave",
/**
* Mouse left button clicked.
* @event og.EntityCollection#lclick
*/
"lclick",
/**
* Mouse right button clicked.
* @event og.EntityCollection#rclick
*/
"rclick",
/**
* Mouse right button clicked.
* @event og.EntityCollection#mclick
*/
"mclick",
/**
* Mouse left button double click.
* @event og.EntityCollection#ldblclick
*/
"ldblclick",
/**
* Mouse right button double click.
* @event og.EntityCollection#rdblclick
*/
"rdblclick",
/**
* Mouse middle button double click.
* @event og.EntityCollection#mdblclick
*/
"mdblclick",
/**
* Mouse left button up(stop pressing).
* @event og.EntityCollection#lup
*/
"lup",
/**
* Mouse right button up(stop pressing).
* @event og.EntityCollection#rup
*/
"rup",
/**
* Mouse middle button up(stop pressing).
* @event og.EntityCollection#mup
*/
"mup",
/**
* Mouse left button is just pressed down(start pressing).
* @event og.EntityCollection#ldown
*/
"ldown",
/**
* Mouse right button is just pressed down(start pressing).
* @event og.EntityCollection#rdown
*/
"rdown",
/**
* Mouse middle button is just pressed down(start pressing).
* @event og.EntityCollection#mdown
*/
"mdown",
/**
* Mouse left button is pressing.
* @event og.EntityCollection#lhold
*/
"lhold",
/**
* Mouse right button is pressing.
* @event og.EntityCollection#rhold
*/
"rhold",
/**
* Mouse middle button is pressing.
* @event og.EntityCollection#mhold
*/
"mhold",
/**
* Mouse wheel is rotated.
* @event og.EntityCollection#mousewheel
*/
"mousewheel",
/**
* Triggered when touch moves over the entity.
* @event og.EntityCollection#touchmove
*/
"touchmove",
/**
* Triggered when entity begins to touch.
* @event og.EntityCollection#touchstart
*/
"touchstart",
/**
* Triggered when entity ends touching.
* @event og.EntityCollection#touchend
*/
"touchend",
/**
* Triggered entity double touch.
* @event og.EntityCollection#doubletouch
*/
"doubletouch",
/**
* Triggered when touching leaves entity.
* @event og.EntityCollection#touchleave
*/
"touchleave",
/**
* Triggered when touch enters over the entity.
* @event og.EntityCollection#touchenter
*/
"touchenter"
];
export { EntityCollection };

View File

@ -1,317 +0,0 @@
/**
* @module og/entity/Geometry
*/
'use strict';
import * as utils from '../utils/shared.js';
import { Extent } from '../Extent.js';
import { Vec4 } from '../math/Vec4.js';
import { LonLat } from '../LonLat.js';
const GeometryType = {
POINT: 1,
LINESTRING: 2,
POLYGON: 3,
MULTIPOLYGON: 4,
MULTILINESTRING: 5
};
class Geometry {
constructor(options) {
this._id = Geometry._staticCounter++;
options = options || {};
options.style = options.style || {};
/**
* Entity instance that holds this geometry.
* @protected
* @type {og.Entity}
*/
this._entity = null;
this._handler = null;
this._handlerIndex = -1;
//Polygon
this._polyVerticesMerc = [];
this._polyVerticesLength = -1;
this._polyIndexesLength = -1;
this._polyVerticesHandlerIndex = -1;
this._polyIndexesHandlerIndex = -1;
//Line(Linestring and polygon's stroke(s)
this._lineVerticesMerc = [];
this._lineVerticesLength = -1;
this._lineOrdersLength = -1;
this._lineIndexesLength = -1;
this._lineColorsLength = -1;
this._lineThicknessLength = -1;
this._lineVerticesHandlerIndex = -1;
this._lineOrdersHandlerIndex = -1;
this._lineIndexesHandlerIndex = -1;
this._lineThicknessHandlerIndex = -1;
this._lineColorsHandlerIndex = -1;
this._type = options.type && Geometry.getType(options.type) || GeometryType.POINT;
this._coordinates = [];
this._extent = Geometry.getExtent({
'type': options.type || "Point",
'coordinates': options.coordinates || []
}, this._coordinates);
this._style = options.style || {};
this._style.fillColor = utils.createColorRGBA(options.style.fillColor, new Vec4(0.19, 0.62, 0.85, 0.4));
this._style.lineColor = utils.createColorRGBA(options.style.lineColor, new Vec4(0.19, 0.62, 0.85, 1));
this._style.strokeColor = utils.createColorRGBA(options.style.strokeColor, new Vec4(1, 1, 1, 0.95));
this._style.lineWidth = options.style.lineWidth || 3;
this._style.strokeWidth = options.style.strokeWidth || 0;
this._visibility = options.visibility || true;
//optimization flag for picking mask rendering pass
this._pickingReady = false;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static getType(typeStr) {
return GeometryType[typeStr.toUpperCase()];
}
/**
* Returns geometry feature extent.
@static
@param {Object} geometryObj - GeoJSON style geometry feature.
@param {Array} outoordinates - Geometry feature coordinates clone.
@returns {og.Extent}
*/
static getExtent(geometryObj, outCoordinates) {
var res = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
var t = Geometry.getType(geometryObj.type);
if (t === GeometryType.POINT) {
var lon = res.coordinates[0],
lat = res.coordinates[1];
res.southWest.lon = lon;
res.southWest.lat = lat;
res.northEast.lon = lon;
res.northEast.lat = lat;
outCoordinates && (outCoordinates[0] = lon) && (outCoordinates[1] = lat);
} else if (t === GeometryType.LINESTRING) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var lon = c[i][0],
lat = c[i][1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i] = [lon, lat]);
}
} else if (t === GeometryType.POLYGON) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var ci = c[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < ci.length; j++) {
var cij = ci[j];
var lon = cij[0],
lat = cij[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j] = [lon, lat]);
}
}
} else if (t === GeometryType.MULTIPOLYGON) {
var p = geometryObj.coordinates;
for (var i = 0; i < p.length; i++) {
var pi = p[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < pi.length; j++) {
var pij = pi[j];
outCoordinates && (outCoordinates[i][j] = []);
for (var k = 0; k < pij.length; k++) {
var pijk = pij[k];
var lon = pijk[0],
lat = pijk[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j][k] = [lon, lat]);
}
}
}
} else if (t === GeometryType.MULTILINESTRING) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var ci = c[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < ci.length; j++) {
var cij = ci[j];
var lon = cij[0],
lat = cij[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j] = [lon, lat]);
}
}
} else {
res.southWest.lon = res.southWest.lat = res.northEast.lon = res.northEast.lat = 0.0;
outCoordinates && (outCoordinates[0] = lon) && (outCoordinates[1] = lat);
}
return res;
}
/**
*/
setGeometry(geoJson) {
var h = this._handler;
this.remove();
this._type = Geometry.getType(geoJson.type || "Point");
this._extent = Geometry.getExtent(geoJson, this._coordinates);
h.add(this);
return this;
}
setFillColor(r, g, b, a) {
var c = this._style.fillColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setPolyColorArr(this, c);
return this;
}
setFillColor4v(rgba) {
return this.setFillColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setStrokeColor(r, g, b, a) {
var c = this._style.strokeColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setStrokeColorArr(this, c);
return this;
}
setLineColor(r, g, b, a) {
var c = this._style.lineColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setLineColorArr(this, c);
return this;
}
setStrokeColor4v(rgba) {
return this.setStrokeColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setLineColor4v(rgba) {
return this.setLineColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setStrokeOpacity(opacity) {
var c = this._style.strokeColor;
c.w = opacity;
return this.setStrokeColor(c.x, c.y, c.z, opacity);
}
setLineOpacity(opacity) {
var c = this._style.lineColor;
c.w = opacity;
return this.setLineColor(c.x, c.y, c.z, opacity);
}
setStrokeWidth(width) {
this._style.strokeWidth = width;
this._pickingReady = false;
this._handler && this._handler.setLineStrokeArr(this, width);
return this;
}
bringToFront() {
this._handler && this._handler.bringToFront(this);
return this;
}
setLineWidth(width) {
this._style.lineWidth = width;
this._pickingReady = false;
this._handler && this._handler.setLineThicknessArr(this, width);
return this;
}
setFillOpacity(opacity) {
var c = this._style.fillColor;
if (c.w === 0.0 && opacity !== 0.0 || c.w !== 0.0 && opacity === 0.0) {
this._pickingReady = false;
}
c.w = opacity;
this._handler && this._handler.setPolyColorArr(this, c);
return this;
}
setVisibility(visibility) {
this._visibility = visibility;
this._handler && this._handler.setGeometryVisibility(this);
return this;
}
getVisibility() {
return this._visibility;
}
remove() {
this._handler && this._handler.remove(this);
}
etExtent() {
return this._extent.clone();
}
getType() {
return this._type;
}
};
export { Geometry, GeometryType };

View File

@ -1,747 +0,0 @@
/**
* @module og/entity/GeometryHandler
*/
'use strict';
import * as mercator from '../mercator.js';
import * as quadTree from '../quadTree/quadTree.js';
import { earcut, flatten } from '../utils/earcut.js';
import { GeometryType } from './Geometry.js';
const POLYVERTICES_BUFFER = 0;
const POLYINDEXES_BUFFER = 1;
const POLYCOLORS_BUFFER = 2;
const LINEVERTICES_BUFFER = 3;
const LINEINDEXES_BUFFER = 4;
const LINEORDERS_BUFFER = 5;
const LINECOLORS_BUFFER = 6;
const LINETHICKNESS_BUFFER = 7;
const LINESTROKES_BUFFER = 8;
const LINESTROKECOLORS_BUFFER = 9;
const POLYPICKINGCOLORS_BUFFER = 10;
const LINEPICKINGCOLORS_BUFFER = 11;
class GeometryHandler {
constructor(layer) {
this.__staticId = GeometryHandler._staticCounter++;
this._layer = layer;
this._handler = null;
this._geometries = [];
this._updatedGeometryArr = [];
this._updatedGeometry = {};
this._removeGeometryExtentArr = [];
this._removeGeometryExtents = {};
//Polygon arrays
this._polyVerticesMerc = [];
this._polyColors = [];
this._polyPickingColors = [];
this._polyIndexes = [];
//Line arrays
this._lineVerticesMerc = [];
this._lineOrders = [];
this._lineIndexes = [];
this._lineColors = [];
this._linePickingColors = [];
this._lineThickness = [];
this._lineStrokes = [];
this._lineStrokeColors = [];
//Buffers
this._polyVerticesBufferMerc = null;
this._polyColorsBuffer = null;
this._polyPickingColorsBuffer = null;
this._polyIndexesBuffer = null;
this._lineVerticesBufferMerc = null;
this._lineColorsBuffer = null;
this._linePickingColorsBuffer = null;
this._lineThicknessBuffer = null;
this._lineStrokesBuffer = null;
this._lineStrokeColorsBuffer = null;
this._lineOrdersBuffer = null;
this._lineIndexesBuffer = null;
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[POLYVERTICES_BUFFER] = this.createPolyVerticesBuffer;
this._buffersUpdateCallbacks[POLYINDEXES_BUFFER] = this.createPolyIndexesBuffer;
this._buffersUpdateCallbacks[POLYCOLORS_BUFFER] = this.createPolyColorsBuffer;
this._buffersUpdateCallbacks[LINEVERTICES_BUFFER] = this.createLineVerticesBuffer;
this._buffersUpdateCallbacks[LINEINDEXES_BUFFER] = this.createLineIndexesBuffer;
this._buffersUpdateCallbacks[LINEORDERS_BUFFER] = this.createLineOrdersBuffer;
this._buffersUpdateCallbacks[LINECOLORS_BUFFER] = this.createLineColorsBuffer;
this._buffersUpdateCallbacks[LINETHICKNESS_BUFFER] = this.createLineThicknessBuffer;
this._buffersUpdateCallbacks[LINESTROKES_BUFFER] = this.createLineStrokesBuffer;
this._buffersUpdateCallbacks[LINESTROKECOLORS_BUFFER] = this.createLineStrokeColorsBuffer;
this._buffersUpdateCallbacks[POLYPICKINGCOLORS_BUFFER] = this.createPolyPickingColorsBuffer;
this._buffersUpdateCallbacks[LINEPICKINGCOLORS_BUFFER] = this.createLinePickingColorsBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static appendLineData(pathArr, isClosed, color, pickingColor, thickness, strokeColor, strokeSize,
outVertices, outOrders, outIndexes, outColors, outPickingColors, outThickness, outStrokeColors, outStrokes,
outVertices2) {
var index = 0;
if (outIndexes.length > 0) {
index = outIndexes[outIndexes.length - 5] + 9;
outIndexes.push(index, index);
} else {
outIndexes.push(0, 0);
}
var t = thickness,
c = [color.x, color.y, color.z, color.w],
s = strokeSize,
sc = [strokeColor.x, strokeColor.y, strokeColor.z, strokeColor.w],
p = [pickingColor.x, pickingColor.y, pickingColor.z, 1.0];
for (var j = 0; j < pathArr.length; j++) {
var path = pathArr[j];
var startIndex = index;
var last;
if (isClosed) {
last = path[path.length - 1];
} else {
var p0 = path[0],
p1 = path[1];
last = [p0[0] + p0[0] - p1[0], p0[1] + p0[1] - p1[1]];
}
outVertices.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
outVertices2.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
for (var i = 0; i < path.length; i++) {
var cur = path[i];
outVertices.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
outVertices2.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
outIndexes.push(index++, index++, index++, index++);
}
var first;
if (isClosed) {
first = path[0];
outIndexes.push(startIndex, startIndex + 1, startIndex + 1, startIndex + 1);
} else {
var p0 = path[path.length - 1],
p1 = path[path.length - 2];
first = [p0[0] + p0[0] - p1[0], p0[1] + p0[1] - p1[1]];
outIndexes.push(index - 1, index - 1, index - 1, index - 1);
}
outVertices.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
outVertices2.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
if (j < pathArr.length - 1) {
index += 8;
outIndexes.push(index, index);
}
}
}
assignHandler(handler) {
this._handler = handler;
this.refresh();
}
/**
* @public
* @param {og.Geometry} geometry - Geometry object.
*/
add(geometry) {
//
// Triangulates polygon and sets geometry data.
if (geometry._handlerIndex === -1) {
geometry._handler = this;
geometry._handlerIndex = this._geometries.length;
this._geometries.push(geometry);
var pickingColor = geometry._entity._pickingColor.scaleTo(1 / 255);
geometry._polyVerticesMerc = [];
geometry._lineVerticesMerc = [];
if (geometry._type === GeometryType.POLYGON) {
var coordinates = geometry._coordinates;
var ci = [];
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[j].length; k++) {
ci[j][k] = [mercator.forward_lon(coordinates[j][k][0]), mercator.forward_lat(coordinates[j][k][1])];
}
}
var data = earcut.flatten(ci);
var indexes = earcut(data.vertices, data.holes, 2);
geometry._polyVerticesMerc = data.vertices;
geometry._polyVerticesHandlerIndex = this._polyVerticesMerc.length;
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
this._polyVerticesMerc.push.apply(this._polyVerticesMerc, data.vertices);
for (var i = 0; i < indexes.length; i++) {
this._polyIndexes.push(indexes[i] + geometry._polyVerticesHandlerIndex * 0.5);
}
var color = geometry._style.fillColor;
for (var i = 0; i < data.vertices.length * 0.5; i++) {
this._polyColors.push(color.x, color.y, color.z, color.w);
this._polyPickingColors.push(pickingColor.x, pickingColor.y, pickingColor.z, 1.0);
}
geometry._polyVerticesLength = data.vertices.length;
geometry._polyIndexesLength = indexes.length;
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData(ci, true,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.MULTIPOLYGON) {
var coordinates = geometry._coordinates;
var vertices = [],
indexes = [],
colors = [];
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
for (var i = 0; i < coordinates.length; i++) {
var cci = coordinates[i];
var ci = [];
for (var j = 0; j < cci.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[i][j].length; k++) {
ci[j][k] = [mercator.forward_lon(cci[j][k][0]), mercator.forward_lat(cci[j][k][1])];
}
}
var data = flatten(ci);
var dataIndexes = earcut(data.vertices, data.holes, 2);
for (var j = 0; j < dataIndexes.length; j++) {
indexes.push(dataIndexes[j] + vertices.length * 0.5);
}
vertices.push.apply(vertices, data.vertices);
GeometryHandler.appendLineData(ci, true,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
}
geometry._polyVerticesMerc = vertices;
geometry._polyVerticesHandlerIndex = this._polyVerticesMerc.length;
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
this._polyVerticesMerc.push.apply(this._polyVerticesMerc, vertices);
for (var i = 0; i < indexes.length; i++) {
this._polyIndexes.push(indexes[i] + geometry._polyVerticesHandlerIndex * 0.5);
}
var color = geometry._style.fillColor;
for (var i = 0; i < vertices.length * 0.5; i++) {
this._polyColors.push(color.x, color.y, color.z, color.w);
this._polyPickingColors.push(pickingColor.x, pickingColor.y, pickingColor.z, 1.0);
}
geometry._polyVerticesLength = vertices.length;
geometry._polyIndexesLength = indexes.length;
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.LINESTRING) {
var coordinates = geometry._coordinates;
var ci = new Array(coordinates.length);
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [mercator.forward_lon(coordinates[j][0]), mercator.forward_lat(coordinates[j][1])];
}
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData([ci], false,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.MULTILINESTRING) {
var coordinates = geometry._coordinates;
var ci = [];
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[j].length; k++) {
ci[j][k] = [mercator.forward_lon(coordinates[j][k][0]), mercator.forward_lat(coordinates[j][k][1])];
}
}
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData(ci, false,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
}
//Refresh visibility
this.setGeometryVisibility(geometry);
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
this.refresh();
}
}
remove(geometry) {
var index = geometry._handlerIndex;
if (index !== -1) {
this._geometries.splice(index, 1);
//polygon
//this._polyVerticesLonLat.splice(geometry._polyVerticesHandlerIndex, geometry._polyVerticesLength);
this._polyVerticesMerc.splice(geometry._polyVerticesHandlerIndex, geometry._polyVerticesLength);
this._polyColors.splice(geometry._polyVerticesHandlerIndex * 2, geometry._polyVerticesLength * 2);
this._polyPickingColors.splice(geometry._polyVerticesHandlerIndex * 2, geometry._polyVerticesLength * 2);
this._polyIndexes.splice(geometry._polyIndexesHandlerIndex, geometry._polyIndexesLength);
var di = geometry._polyVerticesLength * 0.5;
for (var i = geometry._polyIndexesHandlerIndex; i < this._polyIndexes.length; i++) {
this._polyIndexes[i] -= di;
}
//line
//this._lineVerticesLonLat.splice(geometry._lineVerticesHandlerIndex, geometry._lineVerticesLength);
this._lineVerticesMerc.splice(geometry._lineVerticesHandlerIndex, geometry._lineVerticesLength);
this._lineOrders.splice(geometry._lineOrdersHandlerIndex, geometry._lineOrdersLength);
this._lineColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._linePickingColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._lineStrokeColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._lineThickness.splice(geometry._lineThicknessHandlerIndex, geometry._lineThicknessLength);
this._lineStrokes.splice(geometry._lineThicknessHandlerIndex, geometry._lineThicknessLength);
this._lineIndexes.splice(geometry._lineIndexesHandlerIndex, geometry._lineIndexesLength);
di = geometry._lineVerticesLength * 0.5;
for (var i = geometry._lineIndexesHandlerIndex; i < this._lineIndexes.length; i++) {
this._lineIndexes[i] -= di;
}
//reindex
var g = this._geometries;
for (i = index; i < g.length; i++) {
var gi = g[i];
gi._handlerIndex = i;
gi._polyVerticesHandlerIndex -= geometry._polyVerticesLength;
gi._polyIndexesHandlerIndex -= geometry._polyIndexesLength;
gi._lineVerticesHandlerIndex -= geometry._lineVerticesLength;
gi._lineOrdersHandlerIndex -= geometry._lineOrdersLength;
gi._lineColorsHandlerIndex -= geometry._lineColorsLength;
gi._lineThicknessHandlerIndex -= geometry._lineThicknessLength;
gi._lineIndexesHandlerIndex -= geometry._lineIndexesLength;
}
geometry._pickingReady = false;
geometry._handler = null;
geometry._handlerIndex = -1;
geometry._polyVerticesMerc = [];
geometry._polyVerticesLength = -1;
geometry._polyIndexesLength = -1;
geometry._polyVerticesHandlerIndex = -1;
geometry._polyIndexesHandlerIndex = -1;
geometry._lineVerticesMerc = [];
geometry._lineVerticesLength = -1;
geometry._lineOrdersLength = -1;
geometry._lineIndexesLength = -1;
geometry._lineColorsLength = -1;
geometry._lineThicknessLength = -1;
geometry._lineVerticesHandlerIndex = -1;
geometry._lineOrdersHandlerIndex = -1;
geometry._lineIndexesHandlerIndex = -1;
geometry._lineThicknessHandlerIndex = -1;
geometry._lineColorsHandlerIndex = -1;
!this._removeGeometryExtents[geometry._id] && this._removeGeometryExtentArr.push(geometry.getExtent());
this._removeGeometryExtents[geometry._id] = true;
this.refresh();
}
}
_refreshRecursevely(geometry, treeNode) {
var lid = this._layer._id;
for (var i = 0; i < treeNode.nodes.length; i++) {
var ni = treeNode.nodes[i];
if (geometry._extent.overlaps(ni.segment.getExtentLonLat())) {
this._refreshRecursevely(geometry, ni);
var m = ni.segment.materials[lid];
if (m && m.isReady) {
if (m.segment.node.getState() !== quadTree.RENDERING) {
m.layer.clearMaterial(m);
} else {
m.pickingReady = m.pickingReady && geometry._pickingReady;
m.isReady = false;
m._updateTexture = m.texture;
m._updatePickingMask = m.pickingMask;
}
geometry._pickingReady = true;
}
}
}
}
_refreshRecursevelyExt(extent, treeNode) {
var lid = this._layer._id;
for (var i = 0; i < treeNode.nodes.length; i++) {
var ni = treeNode.nodes[i];
if (extent.overlaps(ni.segment.getExtentLonLat())) {
this._refreshRecursevelyExt(extent, ni);
var m = ni.segment.materials[lid];
if (m && m.isReady) {
m.layer.clearMaterial(m);
// m.pickingReady = false;
// m.isReady = false;
// m._updateTexture = m.texture;
// m._updatePickingMask = m.pickingMask;
}
}
}
}
_refreshPlanetNode(treeNode) {
var i = 0;
var e = this._removeGeometryExtentArr;
for (i = 0; i < e.length; i++) {
this._refreshRecursevelyExt(e[i], treeNode);
}
var g = this._updatedGeometryArr;
for (i = 0; i < g.length; i++) {
this._refreshRecursevely(g[i], treeNode);
}
}
_updatePlanet() {
var p = this._layer._planet;
if (p) {
this._refreshPlanetNode(p._quadTree);
this._refreshPlanetNode(p._quadTreeNorth);
this._refreshPlanetNode(p._quadTreeSouth);
}
this._updatedGeometryArr.length = 0;
this._updatedGeometryArr = [];
this._updatedGeometry = {};
this._removeGeometryExtentArr.length = 0;
this._removeGeometryExtentArr = [];
this._removeGeometryExtents = {};
}
refresh() {
var i = this._changedBuffers.length;
while (i--) {
this._changedBuffers[i] = true;
}
}
update() {
if (this._handler) {
var needUpdate = false;
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
needUpdate = true;
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
needUpdate && this._updatePlanet();
}
}
setGeometryVisibility(geometry) {
var v = geometry._visibility ? 1.0 : 0.0;
var a = this._polyVerticesMerc;
var l = geometry._polyVerticesLength;
var ind = geometry._polyVerticesHandlerIndex;
for (var i = 0; i < l; i++) {
a[ind + i] = geometry._polyVerticesMerc[i] * v;
}
a = this._lineVerticesMerc;
l = geometry._lineVerticesLength;
ind = geometry._lineVerticesHandlerIndex;
for (i = 0; i < l; i++) {
a[ind + i] = geometry._lineVerticesMerc[i] * v;
}
this._changedBuffers[POLYVERTICES_BUFFER] = true;
this._changedBuffers[LINEVERTICES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setPolyColorArr(geometry, color) {
var index = geometry._polyVerticesHandlerIndex * 2, // ... / 2 * 4
size = index + geometry._polyVerticesLength * 2; // ... / 2 * 4
var a = this._polyColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[POLYCOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineStrokeColorArr(geometry, color) {
var index = geometry._lineColorsHandlerIndex,
size = index + geometry._lineColorsLength;
var a = this._lineStrokeColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[LINESTROKECOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineColorArr(geometry, color) {
var index = geometry._lineColorsHandlerIndex,
size = index + geometry._lineColorsLength;
var a = this._lineColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[LINECOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineStrokeArr(geometry, width) {
var index = geometry._lineStrokesHandlerIndex,
size = index + geometry._lineStrokesLength;
var a = this._lineStrokes;
for (var i = index; i < size; i++) {
a[i] = width;
}
this._changedBuffers[LINESTROKES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineThicknessArr(geometry, width) {
var index = geometry._lineThicknessHandlerIndex,
size = index + geometry._lineThicknessLength;
var a = this._lineThickness;
for (var i = index; i < size; i++) {
a[i] = width;
}
this._changedBuffers[LINETHICKNESS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
bringToFront(geometry) {
var polyIndexes = this._polyIndexes.splice(geometry._polyIndexesHandlerIndex, geometry._polyIndexesLength);
var lineIndexes = this._lineIndexes.splice(geometry._lineIndexesHandlerIndex, geometry._lineIndexesLength);
this._geometries.splice(geometry._handlerIndex, 1);
var g = this._geometries;
for (var i = geometry._handlerIndex; i < g.length; i++) {
var gi = g[i];
gi._handlerIndex = i;
gi._polyIndexesHandlerIndex -= geometry._polyIndexesLength;
gi._lineIndexesHandlerIndex -= geometry._lineIndexesLength;
}
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._handlerIndex = this._geometries.length;
this._geometries.push(geometry);
this._polyIndexes.push.apply(this._polyIndexes, polyIndexes);
this._lineIndexes.push.apply(this._lineIndexes, lineIndexes);
this._changedBuffers[POLYINDEXES_BUFFER] = true;
this._changedBuffers[LINEINDEXES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
createPolyVerticesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyVerticesBufferMerc);
this._polyVerticesBufferMerc = h.createArrayBuffer(new Float32Array(this._polyVerticesMerc), 2, this._polyVerticesMerc.length / 2);
}
createPolyIndexesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyIndexesBuffer);
this._polyIndexesBuffer = h.createElementArrayBuffer(new Uint32Array(this._polyIndexes), 1, this._polyIndexes.length);
}
createPolyColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyColorsBuffer);
this._polyColorsBuffer = h.createArrayBuffer(new Float32Array(this._polyColors), 4, this._polyColors.length / 4);
}
createPolyPickingColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyPickingColorsBuffer);
this._polyPickingColorsBuffer = h.createArrayBuffer(new Float32Array(this._polyPickingColors), 4, this._polyPickingColors.length / 4);
}
createLineVerticesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineVerticesBufferMerc);
this._lineVerticesBufferMerc = h.createArrayBuffer(new Float32Array(this._lineVerticesMerc), 2, this._lineVerticesMerc.length / 2);
}
createLineIndexesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineIndexesBuffer);
this._lineIndexesBuffer = h.createElementArrayBuffer(new Uint32Array(this._lineIndexes), 1, this._lineIndexes.length);
}
createLineOrdersBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineOrdersBuffer);
this._lineOrdersBuffer = h.createArrayBuffer(new Float32Array(this._lineOrders), 1, this._lineOrders.length / 2);
}
createLineColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineColorsBuffer);
this._lineColorsBuffer = h.createArrayBuffer(new Float32Array(this._lineColors), 4, this._lineColors.length / 4);
}
createLinePickingColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._linePickingColorsBuffer);
this._linePickingColorsBuffer = h.createArrayBuffer(new Float32Array(this._linePickingColors), 4, this._linePickingColors.length / 4);
}
createLineThicknessBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineThicknessBuffer);
this._lineThicknessBuffer = h.createArrayBuffer(new Float32Array(this._lineThickness), 1, this._lineThickness.length);
}
createLineStrokesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineStrokesBuffer);
this._lineStrokesBuffer = h.createArrayBuffer(new Float32Array(this._lineStrokes), 1, this._lineStrokes.length);
}
createLineStrokeColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineStrokeColorsBuffer);
this._lineStrokeColorsBuffer = h.createArrayBuffer(new Float32Array(this._lineStrokeColors), 4, this._lineStrokeColors.length / 4);
}
};
export { GeometryHandler };

View File

@ -1,372 +0,0 @@
/**
* @module og/entity/Label
*/
'use strict';
import * as utils from '../utils/shared.js';
import { BaseBillboard } from './BaseBillboard.js';
import { Vec4 } from '../math/Vec4.js';
const ALIGN = {
RIGHT: 0,
LEFT: 1,
CENTER: 2
};
/**
* Text align options.
* @readonly
* @enum {number}
*/
const STR2ALIGN = {
"left": ALIGN.LEFT,
"right": ALIGN.RIGHT,
"center": ALIGN.CENTER
};
/**
* Billboard text label.
* @class
* @extends {og.BaseBillboard}
* @param {Object} [options] - Label options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
* @param {string} [options.text] - Text string.
* @param {string} [options.face] - HTML5 font face.
* @param {number} [options.size] - Font size in pixels.
* @param {string} [options.style] - HTML5 font style. Example 'normal', 'italic'.
* @param {string} [options.weight] - HTML5 font weight. Example 'normal', 'bold'.
* @param {number} [options.outline] - Text outline size. 0 - no outline, 1 - maximum outline. Default 0.58.
* @param {og.math.Vector4|string|Array.<number>} [options.outlineColor] - Outline color.
* @param {og.Label.ALIGN} [options.align] - Text horizontal align: "left", "right" and "center".
*/
class Label extends BaseBillboard {
constructor(options) {
super(options);
options = options || {};
/**
* Label text string.
* @private
* @type {string}
*/
this._text = options.text;
/**
* HTML5 font face.
* @private
* @type {string}
*/
this._face = utils.defaultString(options.face, null);
/**
* Font size in pixels.
* @private
* @type {number}
*/
this._size = options.size || 33;
/**
* HTML5 font style. Example 'normal', 'italic'.
* @private
* @type {string}
*/
this._style = utils.defaultString(options.style, null);
/**
* HTML5 font weight style. Example 'normal', 'bold'.
* @private
* @type {string}
*/
this._weight = utils.defaultString(options.weight, null);
/**
* Label outline.
* @private
* @type {number}
*/
this._outline = options.outline != undefined ? options.outline : 0.5;
/**
* Label outline color.
* @private
* @type {og.math.Vector4}
*/
this._outlineColor = utils.createColorRGBA(options.outlineColor, new Vec4(0.0, 0.0, 0.0, 1.0));
/**
* Text horizontal align: "left", "right" and "center".
* @private
* @type {og.Label.ALIGN}
*/
this._align = options.align ? STR2ALIGN[options.align.trim().toLowerCase()] || ALIGN.RIGHT : ALIGN.RIGHT;
/**
* Label font atlas index.
* @private
* @type {number}
*/
this._fontIndex = 0;
/**
* Font atlas pointer.
* @private
* @type {og.utils.FontAtlas}
*/
this._fontAtlas = null;
}
/**
* Sets lablel text.
* @public
* @param {string} text - Text string.
* It can't be bigger than maximum labelHandler _maxLetters value.
*/
setText(text) {
this._text = text;
this._handler && this._handler.setText(this._handlerIndex, text, this._fontIndex, this._align);
}
/**
* Gets current text string.
* @public
* @returns {string}
*/
getText() {
return this._text;
}
/**
* Sets label text align. Could be center, left or right. Left is default.
* @public
* @param {og.Label.ALIGN} align - Text align.
*/
setAlign(align) {
this._align = STR2ALIGN[align.trim().toLowerCase()];
this._handler && this._handler.setText(this._handlerIndex, this._text, this._fontIndex, this._align);
};
/**
* Gets label text current alignment.
* @public
* @returns {og.Label.ALIGN}
*/
getAlign() {
return this._align;
}
/**
* Sets font face family.
* @public
* @param {string} face - Font face family.
*/
setFace(face) {
this._face = face.trim().toLowerCase();
this.update();
}
/**
* Gets current font face.
* @public
* @returns {string}
*/
getFace() {
return this._face;
}
/**
* Sets label font size in pixels.
* @public
* @param {number} size - Label size in pixels.
*/
setSize(size) {
this._size = size;
this._handler && this._handler.setSizeArr(this._handlerIndex, size);
}
/**
* Gets label size in pixels.
* @public
* @returns {number}
*/
getSize() {
return this._size;
}
/**
* Sets font HTML5 style. It's can be Italic or Normal values.
* @public
* @param {string} style - HTML5 font style.
*/
setStyle(style) {
this._style = style.trim().toLowerCase();
this.update();
}
/**
* Gets label font style.
* @public
* @returns {string}
*/
getStyle() {
return this._style;
}
/**
* Sets label font HTML5 weight style. It's can be bold or normal.
* @public
* @param {string} weight - HTML5 font weight style.
*/
setWeight(weight) {
this._weight = weight.trim().toLowerCase();
this.update();
}
/**
* Gets label font weight.
* @public
* @returns {string}
*/
getWeight() {
return this._wight;
}
/**
* Sets text outline border size. Where 0 - is no outline and 1 - is the maximum outline size.
* @public
* @param {number} outline - Text outline size.
*/
setOutline(outline) {
this._outline = outline;
this._handler && this._handler.setOutlineArr(this._handlerIndex, 1.0 - outline);
}
/**
* Gets text current outline size.
* @public
* @returns {number}
*/
getOutline() {
return this._outline;
}
/**
* Sets label opacity.
* @public
* @param {number} a - Label opacity.
*/
setOpacity(a) {
this._color.w = a;
this.setColor4v(this._color);
this._outlineColor.w = a;
this.setOutlineColor4v(this._outlineColor);
}
/**
* Sets text outline color.
* @public
* @param {number} r - Red.
* @param {number} g - Green.
* @param {number} b - Blue.
* @param {number} a - Alpha.
*/
setOutlineColor(r, g, b, a) {
this._outlineColor.x = r;
this._outlineColor.y = g;
this._outlineColor.z = b;
this._outlineColor.w = a;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, this._outlineColor);
}
/**
* Sets text outline color.
* @public
* @param {og.math.Vector4} rgba - Color vector.
*/
setOutlineColor4v(rgba) {
this._outlineColor.x = rgba.x;
this._outlineColor.y = rgba.y;
this._outlineColor.z = rgba.z;
this._outlineColor.w = rgba.w;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, rgba);
}
/**
* Sets text outline color HTML string.
* @public
* @param {string} color - HTML string color.
*/
setOutlineColorHTML(color) {
this.setOutlineColor4v(utils.htmlColorToRgba(color));
};
/**
* Gets outline color vector.
* @public
* @returns {og.math.Vector4}
*/
getOutlineColor() {
return this._outlineColor;
}
/**
* Sets outline opacity. Actually outline color alpha value.
* @public
* @param {number} opacity - Outline opacity.
*/
setOutlineOpacity(opacity) {
this._outlineColor.w = opacity;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, this._outlineColor);
}
/**
* Gets outline opacity value.
* @public
* @returns {number}
*/
getOutlineOpacity() {
return this._outlineColor.w;
}
/**
* Updates label parameters.
* @public
*/
update() {
if (this._fontAtlas) {
var fontIndex = this._fontAtlas.getFontIndex(this._face, this._style, this._weight);
if (fontIndex == undefined) {
this._fontAtlas.createFontAsync(this._face, this._style, this._weight, this._applyFontIndex.bind(this));
} else {
this._applyFontIndex(fontIndex);
}
}
}
_applyFontIndex(fontIndex) {
this._fontIndex = fontIndex;
if (this._handler) {
this._handler.setFontIndexArr(this._handlerIndex, this._fontIndex);
this._handler.setText(this._handlerIndex, this._text, this._fontIndex, this._align);
}
}
/**
* Assigns font atlas and update.
* @public
* @param {og.utils.FontAtlas} fontAtlas - Font atlas.
*/
assignFontAtlas(fontAtlas) {
!this._fontAtlas && (this._fontAtlas = fontAtlas);
this.update();
}
};
export { Label, ALIGN };

View File

@ -1,818 +0,0 @@
/**
* @module og/entity/LabelHandler
*/
'use strict';
import * as shaders from '../shaders/label.js';
import { ALIGN } from './Label.js';
import { BillboardHandler } from './BillboardHandler.js';
const FONTINDEX_BUFFER = 9;
const OUTLINE_BUFFER = 10;
const OUTLINECOLOR_BUFFER = 11;
/*
* og.LabelHandler
*
*
*/
class LabelHandler extends BillboardHandler {
constructor(entityCollection) {
super(entityCollection);
this._fontIndexBuffer = null;
this._noOutlineBuffer = null;
this._outlineBuffer = null;
this._outlineColorBuffer = null;
this._fontIndexArr = [];
this._noOutlineArr = [];
this._outlineArr = [];
this._outlineColorArr = [];
this._buffersUpdateCallbacks[FONTINDEX_BUFFER] = this.createFontIndexBuffer;
this._buffersUpdateCallbacks[OUTLINE_BUFFER] = this.createOutlineBuffer;
this._buffersUpdateCallbacks[OUTLINECOLOR_BUFFER] = this.createOutlineColorBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this._maxLetters = 25;
}
initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.label) {
var isSingleBuffer = !this._renderer.isMultiFramebufferCompatible();
this._renderer.handler.addShaderProgram(shaders.label(isSingleBuffer));
}
if (!this._renderer.handler.shaderPrograms.labelPicking) {
this._renderer.handler.addShaderProgram(shaders.labelPicking());
}
}
}
add(label) {
if (label._handlerIndex == -1) {
label._handler = this;
label._handlerIndex = this._billboards.length;
this._billboards.push(label);
this._addBillboardToArrays(label);
this.refresh();
this.assignFontAtlas(label);
}
}
assignFontAtlas(label) {
if (this._entityCollection && this._entityCollection.renderNode) {
label.assignFontAtlas(this._entityCollection.renderNode.fontAtlas);
}
}
clear() {
this._texCoordArr.length = 0;
this._vertexArr.length = 0;
this._positionArr.length = 0;
this._sizeArr.length = 0;
this._offsetArr.length = 0;
this._rgbaArr.length = 0;
this._rotationArr.length = 0;
this._alignedAxisArr.length = 0;
this._fontIndexArr.length = 0;
this._noOutlineArr.length = 0;
this._outlineArr.length = 0;
this._outlineColorArr.length = 0;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._fontIndexArr = [];
this._noOutlineArr = [];
this._outlineArr = [];
this._outlineColorArr = [];
this._removeBillboards();
this._deleteBuffers();
this.refresh();
}
_deleteBuffers() {
var gl = this._renderer.handler.gl;
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._fontIndexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._outlineBuffer);
gl.deleteBuffer(this._noOutlineBuffer);
gl.deleteBuffer(this._outlineColorBuffer);
gl.deleteBuffer(this._positionBuffer);
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._offsetBuffer);
gl.deleteBuffer(this._rgbaBuffer);
gl.deleteBuffer(this._rotationBuffer);
gl.deleteBuffer(this._vertexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._alignedAxisBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
this._sizeBuffer = null;
this._fontIndexBuffer = null;
this._texCoordBuffer = null;
this._outlineBuffer = null;
this._outlineColorBuffer = null;
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._vertexBuffer = null;
this._texCoordBuffer = null;
this._alignedAxisBuffer = null;
this._pickingColorBuffer = null;
}
_addBillboardToArrays(label) {
for (var i = 0; i < this._maxLetters; i++) {
if (label._visibility) {
BillboardHandler.concArr(this._vertexArr, [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
} else {
BillboardHandler.concArr(this._vertexArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
BillboardHandler.concArr(this._texCoordArr, [0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0]);
var x = label._position.x, y = label._position.y, z = label._position.z, w = label._scale;
BillboardHandler.concArr(this._positionArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._size;
BillboardHandler.concArr(this._sizeArr, [x, x, x, x, x, x]);
x = label._offset.x; y = label._offset.y; z = label._offset.z - 0.05;
BillboardHandler.concArr(this._offsetArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = label._color.x; y = label._color.y; z = label._color.z; w = label._color.w;
BillboardHandler.concArr(this._rgbaArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._rotation;
BillboardHandler.concArr(this._rotationArr, [x, x, x, x, x, x]);
x = label._alignedAxis.x, y = label._alignedAxis.y, z = label._alignedAxis.z;
BillboardHandler.concArr(this._alignedAxisArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = label._fontIndex;
BillboardHandler.concArr(this._fontIndexArr, [0, 0, 0, 0, 0, 0]);
x = 1.0 - label._outline, y = 0.0;
BillboardHandler.concArr(this._outlineArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = 0.75, y = 0.7;
BillboardHandler.concArr(this._noOutlineArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = label._outlineColor.x; y = label._outlineColor.y; z = label._outlineColor.z; w = label._outlineColor.w;
BillboardHandler.concArr(this._outlineColorArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._entity._pickingColor.x / 255, y = label._entity._pickingColor.y / 255, z = label._entity._pickingColor.z / 255;
BillboardHandler.concArr(this._pickingColorArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
}
};
_displayPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.label.activate();
var sh = h.shaderPrograms.label._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
var ec = this._entityCollection;
var rn = ec.renderNode;
gl.uniform1iv(shu.u_fontTextureArr._pName, rn.fontAtlas.samplerArr);
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, ec.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, ec._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [rn._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._fontIndexBuffer);
gl.vertexAttribPointer(sha.a_fontIndex._pName, this._fontIndexBuffer.itemSize, gl.FLOAT, false, 0, 0);
//buffer
gl.bindBuffer(gl.ARRAY_BUFFER, this._outlineColorBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._outlineColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._outlineBuffer);
gl.vertexAttribPointer(sha.a_bufferAA._pName, this._outlineBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform1f(shu.uZ._pName, -2.0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
//nobuffer
gl.bindBuffer(gl.ARRAY_BUFFER, this._rgbaBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._rgbaBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._noOutlineBuffer);
gl.vertexAttribPointer(sha.a_bufferAA._pName, this._noOutlineBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform1f(shu.uZ._pName, -10.0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_pickingPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.labelPicking.activate();
var sh = h.shaderPrograms.labelPicking._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.a_pickingColor._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_removeBillboard(label) {
var li = label._handlerIndex;
this._billboards.splice(li, 1);
var ml = 24 * this._maxLetters;
var i = li * ml;
this._rgbaArr.splice(i, ml);
this._outlineColorArr.splice(i, ml);
this._texCoordArr.splice(i, ml);
this._positionArr.splice(i, ml);
ml = 18 * this._maxLetters;
i = li * ml;
this._offsetArr.splice(i, ml);
this._alignedAxisArr.splice(i, ml);
this._pickingColorArr.splice(i, ml);
ml = 12 * this._maxLetters;
i = li * ml;
this._vertexArr.splice(i, ml);
this._outlineArr.splice(i, ml);
this._noOutlineArr.splice(i, ml);
ml = 6 * this._maxLetters;
i = li * ml;
this._sizeArr.splice(i, ml);
this._rotationArr.splice(i, ml);
this._fontIndexArr.splice(i, ml);
this.reindexBillbordsArray(li);
this.refresh();
label._handlerIndex = -1;
label._handler = null;
//label._fontIndex = 0;
//label._fontAtlas = null;
};
setText(index, text, fontIndex, align) {
var fa = this._entityCollection.renderNode.fontAtlas.atlasesArr[fontIndex];
if (!fa) return;
var i = index * 24 * this._maxLetters;
var a = this._texCoordArr;
var c = 0;
var j = i + c * 24;
var n = fa.nodes[text[c]];
var f = n ? n.emptySize : 0.0;
var offset = f;
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
var n = fa.nodes[text[c]] || fa.nodes[" "];
var tc = n.texCoords;
a[j] = tc[0];
a[j + 1] = tc[1];
a[j + 2] = offset;
a[j + 3] = 0.0;
a[j + 4] = tc[2];
a[j + 5] = tc[3];
a[j + 6] = offset;
a[j + 7] = 0.0;
a[j + 8] = tc[4];
a[j + 9] = tc[5];
a[j + 10] = offset;
a[j + 11] = 0.0;
a[j + 12] = tc[6];
a[j + 13] = tc[7];
a[j + 14] = offset;
a[j + 15] = 0.0;
a[j + 16] = tc[8];
a[j + 17] = tc[9];
a[j + 18] = offset;
a[j + 19] = 0.0;
a[j + 20] = tc[10];
a[j + 21] = tc[11];
a[j + 22] = offset;
a[j + 23] = 0.0;
offset += n.emptySize;
}
//49/512 - font atlas left border letter offset
if (align == ALIGN.CENTER) {
offset = (f + 49 / 512 - offset) * 0.5;
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
a[j + 3] = offset;
a[j + 7] = offset;
a[j + 11] = offset;
a[j + 15] = offset;
a[j + 19] = offset;
a[j + 23] = offset;
}
} else if (align == ALIGN.LEFT) {
offset = (f + 49 / 512 - offset);
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
a[j + 3] = offset;
a[j + 7] = offset;
a[j + 11] = offset;
a[j + 15] = offset;
a[j + 19] = offset;
a[j + 23] = offset;
}
}
for (var c = c; c < this._maxLetters; c++) {
var j = i + c * 24;
a[j + 2] = -1.0;
a[j + 6] = -1.0;
a[j + 10] = -1.0;
a[j + 14] = -1.0;
a[j + 18] = -1.0;
a[j + 17] = -1.0;
}
this._changedBuffers[TEXCOORD_BUFFER] = true;
}
setPositionArr(index, position) {
var i = index * 24 * this._maxLetters;
var a = this._positionArr, x = position.x, y = position.y, z = position.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
}
this._changedBuffers[POSITION_BUFFER] = true;
}
setScaleArr(index, scale) {
var i = index * 24 * this._maxLetters;
var a = this._positionArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j + 3] = scale;
a[j + 7] = scale;
a[j + 11] = scale;
a[j + 15] = scale;
a[j + 19] = scale;
a[j + 23] = scale;
}
this._changedBuffers[POSITION_BUFFER] = true;
}
setPickingColorArr(index, color) {
var i = index * 18 * this._maxLetters;
var a = this._pickingColorArr, x = color.x / 255, y = color.y / 255, z = color.z / 255;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[PICKINGCOLOR_BUFFER] = true;
}
setSizeArr(index, size) {
var i = index * 6 * this._maxLetters;
var a = this._sizeArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = size;
a[j + 1] = size;
a[j + 2] = size;
a[j + 3] = size;
a[j + 4] = size;
a[j + 5] = size;
}
this._changedBuffers[SIZE_BUFFER] = true;
}
setOffsetArr(index, offset) {
var i = index * 18 * this._maxLetters;
var a = this._offsetArr, x = offset.x, y = offset.y, z = offset.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[OFFSET_BUFFER] = true;
}
setRgbaArr(index, rgba) {
var i = index * 24 * this._maxLetters;
var a = this._rgbaArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = w;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 7] = w;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 11] = w;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = w;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 19] = w;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
a[j + 23] = w;
}
this._changedBuffers[RGBA_BUFFER] = true;
}
setOutlineColorArr(index, rgba) {
var i = index * 24 * this._maxLetters;
var a = this._outlineColorArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = w;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 7] = w;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 11] = w;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = w;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 19] = w;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
a[j + 23] = w;
}
this._changedBuffers[OUTLINECOLOR_BUFFER] = true;
}
setOutlineArr(index, outline) {
var i = index * 12 * this._maxLetters;
var a = this._outlineArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 12;
a[j] = outline;
a[j + 2] = outline;
a[j + 4] = outline;
a[j + 6] = outline;
a[j + 8] = outline;
a[j + 10] = outline;
}
this._changedBuffers[OUTLINE_BUFFER] = true;
}
setRotationArr(index, rotation) {
var i = index * 6 * this._maxLetters;
var a = this._rotationArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = rotation;
a[j + 1] = rotation;
a[j + 2] = rotation;
a[j + 3] = rotation;
a[j + 4] = rotation;
a[j + 5] = rotation;
}
this._changedBuffers[ROTATION_BUFFER] = true
}
setVertexArr(index, vertexArr) {
var i = index * 12 * this._maxLetters;
var a = this._vertexArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 12;
a[j] = vertexArr[0];
a[j + 1] = vertexArr[1];
a[j + 2] = vertexArr[2];
a[j + 3] = vertexArr[3];
a[j + 4] = vertexArr[4];
a[j + 5] = vertexArr[5];
a[j + 6] = vertexArr[6];
a[j + 7] = vertexArr[7];
a[j + 8] = vertexArr[8];
a[j + 9] = vertexArr[9];
a[j + 10] = vertexArr[10];
a[j + 11] = vertexArr[11];
}
this._changedBuffers[VERTEX_BUFFER] = true;
}
setAlignedAxisArr(index, alignedAxis) {
var i = index * 18 * this._maxLetters;
var a = this._alignedAxisArr, x = alignedAxis.x, y = alignedAxis.y, z = alignedAxis.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[ALIGNEDAXIS_BUFFER] = true;
}
setFontIndexArr(index, fontIndex) {
var i = index * 6 * this._maxLetters;
var a = this._fontIndexArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = fontIndex;
a[j + 1] = fontIndex;
a[j + 2] = fontIndex;
a[j + 3] = fontIndex;
a[j + 4] = fontIndex;
a[j + 5] = fontIndex;
}
this._changedBuffers[FONTINDEX_BUFFER] = true;
}
createSizeBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._sizeBuffer);
this._sizeBuffer = h.createArrayBuffer(new Float32Array(this._sizeArr), 1, this._sizeArr.length);
}
createFontIndexBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._fontIndexBuffer);
this._fontIndexBuffer = h.createArrayBuffer(new Float32Array(this._fontIndexArr), 1, this._fontIndexArr.length);
}
createTexCoordBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._texCoordBuffer);
this._texCoordBuffer = h.createArrayBuffer(new Float32Array(this._texCoordArr), 4, this._texCoordArr.length / 4);
}
createOutlineBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._outlineBuffer);
this._outlineBuffer = h.createArrayBuffer(new Float32Array(this._outlineArr), 2, this._outlineArr.length / 2);
h.gl.deleteBuffer(this._noOutlineBuffer);
this._noOutlineBuffer = h.createArrayBuffer(new Float32Array(this._noOutlineArr), 2, this._noOutlineArr.length / 2);
}
createOutlineColorBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._outlineColorBuffer);
this._outlineColorBuffer = h.createArrayBuffer(new Float32Array(this._outlineColorArr), 4, this._outlineColorArr.length / 4);
}
setMaxLetters(c) {
this._maxLetters = c;
//...
}
refreshTexCoordsArr() {
//it is empty
return null;
}
};
export { LabelHandler };

View File

@ -1,461 +0,0 @@
/**
* @module og/entity/PointCloud
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
import { Vec4 } from '../math/Vec4.js';
const COORDINATES_BUFFER = 0;
const COLOR_BUFFER = 1;
const PICKING_COLOR_BUFFER = 2;
/**
* PointCloud object.
* @class
* @param {*} [options] - Point cloud options:
* @param {Array.<Array.<number,number,number,number,number,number,number,*>>} [options.points] - Points cartesian coordinates array,
* where first three is cartesian coordinates, next fourth is a RGBA color, and last is an point properties.
* @param {number} [options.pointSize] - Point screen size in pixels.
* @param {number} [options.pickingDistance] - Point border picking size in screen pixels.
* @parar {boolean} [options.visibility] - Point cloud visibility.
* @example <caption>Creates point cloud with two ten pixel size points</caption>
* new og.Entity({
* pointCloud: {
* pointSize: 10,
* points: [
* [0, 0, 0, 255, 255, 255, 255, { 'name': 'White point' }],
* [100, 100, 0, 255, 0, 0, 255, { 'name': 'Red point' }]
* ]
* }
* });
*/
class PointCloud {
constructor(options) {
options = options || {};
/**
* Object unic identifier.
* @public
* @readonly
* @type {number}
*/
this.id = PointCloud._staticCounter++;
/**
* Cloud visibility.
* @public
* @type {boolean}
*/
this.visibility = (options.visibility != undefined ? options.visibility : true);
/**
* Point screen size in pixels.
* @public
* @type {number}
*/
this.pointSize = options.pointSize || 3;
/**
* Point picking border size in pixels.
* @public
* @type {number}
*/
this.pickingDistance = options.pickingDistance || 0;
/**
* Parent collection render node.
* @private
* @type {og.scene.RenderNode}
*/
this._renderNode = null;
/**
* Entity instance that holds this point cloud.
* @private
* @type {og.Entity}
*/
this._entity = null;
/**
* Points properties.
* @private
* @type {Array.<*>}
*/
this._points = [];
/**
* Coordinates array.
* @private
* @type {Array.<number>}
*/
this._coordinatesData = [];
/**
* Color array.
* @private
* @type {Array.<number>}
*/
this._colorData = [];
/**
* Picking color array.
* @private
* @type {Array.<number>}
*/
this._pickingColorData = [];
this._coordinatesBuffer = null;
this._colorBuffer = null;
this._pickingColorBuffer = null;
/**
* Handler that stores and renders this object.
* @private
* @type {og.PointCloudHandler}
*/
this._handler = null;
this._handlerIndex = -1;
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[COORDINATES_BUFFER] = this._createCoordinatesBuffer;
this._buffersUpdateCallbacks[COLOR_BUFFER] = this._createColorBuffer;
this._buffersUpdateCallbacks[PICKING_COLOR_BUFFER] = this._createPickingColorBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this.setPoints(options.points);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Clears point cloud data
* @public
*/
clear() {
this._points.length = 0;
this._points = [];
this._coordinatesData.length = 0;
this._coordinatesData = [];
this._colorData.length = 0;
this._colorData = [];
this._pickingColorData.length = 0;
this._pickingColorData = [];
this._deleteBuffers();
}
/**
* Set point cloud opacity.
* @public
* @param {number} opacity - Cloud opacity.
*/
setOpacity(opacity) {
this.opacity = opacity;
}
/**
* Sets cloud visibility.
* @public
* @param {number} visibility - Visibility flag.
*/
setVisibility(visibility) {
this.visibility = visibility;
}
/**
* @return {boolean} Point cloud visibily.
*/
getVisibility() {
return this.visibility;
}
/**
* Assign rendering scene node.
* @public
* @param {og.scene.RenderNode} renderNode - Assigned render node.
*/
setRenderNode(renderNode) {
this._renderNode = renderNode;
this._setPickingColors();
}
/**
* Removes from entity.
* @public
*/
remove() {
this._entity = null;
this._handler && this._handler.remove(this);
}
/**
* Adds points to render.
* @public
* @param {Array.<Array<number,number,number,number,number,number,number,*>>} points - Point cloud array.
* @example
* var points = [[0, 0, 0, 255, 255, 255, 255, { 'name': 'White point' }], [100, 100, 0, 255, 0, 0, 255, { 'name': 'Red point' }]];
*/
setPoints(points) {
this.clear();
for (var i = 0; i < points.length; i++) {
var pi = points[i];
var pos = new Vec3(pi[0], pi[1], pi[2]),
col = new Vec4(pi[3], pi[4], pi[5], (pi[6] == undefined ? 255.0 : pi[6]));
this._coordinatesData.push(pos.x, pos.y, pos.z);
this._colorData.push(col.x / 255.0, col.y / 255.0, col.z / 255.0, col.w / 255.0);
var p = {
'_pickingColor': new Vec3(),
'_entityCollection': this._entity && this._entity._entityCollection,
'index': i,
'position': pos,
'color': col,
'pointCloud': this,
'properties': pi[7] || {}
};
this._points.push(p);
if (this._renderNode) {
this._renderNode.renderer.assignPickingColor(p);
this._pickingColorData.push(p._pickingColor.x / 255.0, p._pickingColor.y / 255.0, p._pickingColor.z / 255.0, 1.0);
}
}
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
setPointPosition(index, x, y, z) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
}
/**
* @todo
*/
setPointColor(index, r, g, b, a) {
//...
this._changedBuffers[COLOR_BUFFER] = true;
}
/**
* @todo
*/
addPoints(points) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
addPoint(index, point) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* Returns specific point by index.
* @public
* @param {number} index - Point index.
* @return {*} Specific point
*/
getPoint(index) {
return this._points[index];
}
/**
* @todo
*/
removePoint(index) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
insertPoint(index, point) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* Each point iterator.
* @public
* @param {callback} callback
*/
each(callback) {
var i = this._points.length;
while (i--) {
callback && callback(this._points[i]);
}
}
draw() {
if (this.visibility && this._coordinatesData.length) {
this._update();
var rn = this._renderNode;
var r = rn.renderer;
var sh = r.handler.shaderPrograms.pointCloud;
var p = sh._program;
var gl = r.handler.gl,
sha = p.attributes,
shu = p.uniforms;
sh.activate();
gl.uniformMatrix4fv(shu.projectionViewMatrix._pName, false, r.activeCamera._projectionViewMatrix._m);
gl.uniform1f(shu.opacity._pName, this._handler._entityCollection._animatedOpacity);
gl.uniform1f(shu.pointSize._pName, this.pointSize);
gl.bindBuffer(gl.ARRAY_BUFFER, this._coordinatesBuffer);
gl.vertexAttribPointer(sha.coordinates._pName, this._coordinatesBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
gl.vertexAttribPointer(sha.colors._pName, this._colorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, this._coordinatesBuffer.numItems);
}
}
drawPicking() {
if (this.visibility && this._coordinatesData.length) {
var rn = this._renderNode;
var r = rn.renderer;
var sh = r.handler.shaderPrograms.pointCloud;
var p = sh._program;
var gl = r.handler.gl,
sha = p.attributes,
shu = p.uniforms;
sh.activate();
gl.uniformMatrix4fv(shu.projectionViewMatrix._pName, false, r.activeCamera._projectionViewMatrix._m);
gl.uniform1f(shu.opacity._pName, this._handler._entityCollection._animatedOpacity);
gl.uniform1f(shu.pointSize._pName, this.pointSize + this.pickingDistance);
gl.bindBuffer(gl.ARRAY_BUFFER, this._coordinatesBuffer);
gl.vertexAttribPointer(sha.coordinates._pName, this._coordinatesBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.colors._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, this._coordinatesBuffer.numItems);
}
}
/**
* Update gl buffers.
* @private
*/
_update() {
if (this._renderNode) {
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
}
}
/**
* Delete buffers
* @private
*/
_deleteBuffers() {
if (this._renderNode) {
var r = this._renderNode.renderer,
gl = r.handler.gl;
gl.deleteBuffer(this._coordinatesBuffer);
gl.deleteBuffer(this._colorBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
}
this._coordinatesBuffer = null;
this._colorBuffer = null;
this._pickingColorBuffer = null;
}
_createCoordinatesBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._coordinatesBuffer);
this._coordinatesBuffer = h.createArrayBuffer(new Float32Array(this._coordinatesData), 3, (this._coordinatesData.length) / 3);
}
_createColorBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._colorBuffer);
this._colorBuffer = h.createArrayBuffer(new Float32Array(this._colorData), 4, (this._colorData.length) / 4);
}
_createPickingColorBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._pickingColorBuffer);
this._pickingColorBuffer = h.createArrayBuffer(new Float32Array(this._pickingColorData), 4, (this._pickingColorData.length) / 4);
}
_setPickingColors() {
if (this._renderNode) {
for (var i = 0; i < this._points.length; i++) {
var p = this._points[i];
p._entity = this._entity;
p._entityCollection = this._entity._entityCollection;
this._renderNode.renderer.assignPickingColor(p);
this._pickingColorData.push(p._pickingColor.x / 255.0, p._pickingColor.y / 255.0, p._pickingColor.z / 255.0, 1.0);
}
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
}
};
export { PointCloud };

View File

@ -1,126 +0,0 @@
/**
* @module og/entity/PointCloudHandler
*/
'use strict';
import * as shaders from '../shaders/pointCloud.js';
class PointCloudHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
/**
* Parent collection
* @private
* @type {og.EntityCollection}
*/
this._entityCollection = entityCollection;
/**
* Renderer
* @private
* @type {og.Renderer}
*/
this._renderer = null;
/**
* Point cloud array
* @private
* @type {Array.<og.PointCloud>}
*/
this._pointClouds = [];
this.__staticId = PointCloudHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.pointCloud) {
this._renderer.handler.addShaderProgram(shaders.pointCloud());
}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._pointClouds.length; i++) {
this._pointClouds[i].setRenderNode(renderNode);
}
}
add(pointCloud) {
if (pointCloud._handlerIndex == -1) {
pointCloud._handler = this;
pointCloud._handlerIndex = this._pointClouds.length;
this._pointClouds.push(pointCloud);
this._entityCollection && this._entityCollection.renderNode &&
pointCloud.setRenderNode(this._entityCollection.renderNode);
}
}
remove(pointCloud) {
var index = pointCloud._handlerIndex;
if (index !== -1) {
pointCloud._deleteBuffers();
pointCloud._handlerIndex = -1;
pointCloud._handler = null;
this._pointClouds.splice(index, 1);
this.reindexPointCloudArray(index);
}
}
reindexPointCloudArray(startIndex) {
var pc = this._pointClouds;
for (var i = startIndex; i < pc.length; i++) {
pc[i]._handlerIndex = i;
}
}
draw() {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i].draw();
}
}
drawPicking() {
if (this.pickingEnabled) {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i].drawPicking();
}
}
}
clear() {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i]._deleteBuffers();
this._pointClouds[i]._handler = null;
this._pointClouds[i]._handlerIndex = -1;
}
this._pointClouds.length = 0;
this._pointClouds = [];
}
};
export { PointCloudHandler };

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
/**
* @module og/entity/PolylineHandler
*/
'use strict';
import * as shaders from '../shaders/polyline.js';
class PolylineHandler {
constructor(entityCollection) {
this._entityCollection = entityCollection;
this._renderer = null;
this._polylines = [];
this.__staticId = PolylineHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.polyline) {
this._renderer.handler.addShaderProgram(shaders.polyline(this._renderer.isMultiFramebufferCompatible()));
}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._polylines.length; i++) {
this._polylines[i].setRenderNode(renderNode);
}
}
add(polyline) {
if (polyline._handlerIndex == -1) {
polyline._handler = this;
polyline._handlerIndex = this._polylines.length;
this._polylines.push(polyline);
this._entityCollection && this._entityCollection.renderNode &&
polyline.setRenderNode(this._entityCollection.renderNode);
}
}
remove(polyline) {
var index = polyline._handlerIndex;
if (index !== -1) {
polyline._deleteBuffers();
polyline._handlerIndex = -1;
polyline._handler = null;
this._polylines.splice(index, 1);
this.reindexPolylineArray(index);
}
}
reindexPolylineArray(startIndex) {
var ls = this._polylines;
for (var i = startIndex; i < ls.length; i++) {
ls[i]._handlerIndex = i;
}
}
draw() {
var i = this._polylines.length;
while (i--) {
this._polylines[i].draw();
}
}
clear() {
var i = this._polylines.length;
while (i--) {
this._polylines[i]._deleteBuffers();
this._polylines[i]._handler = null;
this._polylines[i]._handlerIndex = -1;
}
this._polylines.length = 0;
this._polylines = [];
}
};
export { PolylineHandler };

View File

@ -1,90 +0,0 @@
/**
* @module og/entity/ShapeHandler
*/
'use strict';
import * as shaders from '../shaders/shape.js';
class ShapeHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
this._entityCollection = entityCollection;
this._renderer = null;
this._shapes = [];
this.__staticId = ShapeHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.shape_nl) {
this._renderer.handler.addShaderProgram(shaders.shape_nl());
}
if (!this._renderer.handler.shaderPrograms.shape_wl) {
this._renderer.handler.addShaderProgram(shaders.shape_wl());
}
//if (!this._renderer.handler.shaderPrograms.shapePicking) {
// this._renderer.handler.addShaderProgram(shaders.shapePicking());
//}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._shapes.length; i++) {
this._shapes[i].setRenderNode(renderNode);
}
}
add(shape) {
if (shape._handlerIndex == -1) {
shape._handler = this;
shape._handlerIndex = this._shapes.length;
this._shapes.push(shape);
this._entityCollection && this._entityCollection.renderNode && shape.setRenderNode(this._entityCollection.renderNode);
}
}
remove(shape) {
//TODO
}
draw() {
var i = this._shapes.length;
while (i--) {
this._shapes[i].draw();
}
}
drawPicking() {
//TODO
}
clear() {
//TODO
}
};
export { ShapeHandler };

View File

@ -1,352 +0,0 @@
/**
* @module og/entity/BaseBillboard
*/
'use strict';
import * as utils from '../utils/shared.js';
/**
* Base prototype for billboard and label classes.
* @class
* @param {Object} [options] - Options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
*/
class BaseBillboard {
constructor(options) {
options = options || {};
/**
* Object unic identifier.
* @public
* @readonly
* @type {number}
*/
this.id = BaseBillboard._staticCounter++;
/**
* Billboard center cartesian position.
* @protected
* @type {og.math.Vector3}
*/
this._position = utils.createVector3(options.position);
/**
* Screen space rotation angle.
* @protected
* @type {number}
*/
this._rotation = options.rotation || 0;
/**
* RGBA color.
* @protected
* @type {og.math.Vector4}
*/
this._color = utils.createColorRGBA(options.color);
/**
* Cartesian aligned axis vector.
* @protected
* @type {og.math.Vector3}
*/
this._alignedAxis = utils.createVector3(options.alignedAxis);
/**
* Billboard center screen space offset. Where x,y - screen space offset and z - depth offset.
* @protected
* @type {og.math.Vecto3}
*/
this._offset = utils.createVector3(options.offset);
/**
* Billboard visibility.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility != undefined ? options.visibility : true;
/**
* Billboard scale.
* @protected
* @type {number}
*/
this._scale = options.scale || 1.0;
/**
* Entity instance that holds this billboard.
* @protected
* @type {og.Entity}
*/
this._entity = null;
/**
* Handler that stores and renders this billboard object.
* @protected
* @type {og.BillboardHandler}
*/
this._handler = null;
/**
* Billboard handler array index.
* @protected
* @type {number}
*/
this._handlerIndex = -1;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Sets billboard position.
* @public
* @param {number} x - X coordinate.
* @param {number} y - Y coordinate.
* @param {number} z - Z coordinate.
*/
setPosition(x, y, z) {
this._position.x = x;
this._position.y = y;
this._position.z = z;
this._handler && this._handler.setPositionArr(this._handlerIndex, this._position);
}
/**
* Sets billboard position.
* @public
* @param {og.math.Vector3} position - Cartesian coordinates.
*/
setPosition3v(position) {
this._position.x = position.x;
this._position.y = position.y;
this._position.z = position.z;
this._handler && this._handler.setPositionArr(this._handlerIndex, position);
}
/**
* Returns billboard position.
* @public
* @returns {og.math.Vector3}
*/
getPosition() {
return this._position;
}
/**
* Sets screen space offset.
* @public
* @param {number} x - X offset.
* @param {number} y - Y offset.
* @param {number} [z] - Z offset.
*/
setOffset(x, y, z) {
this._offset.x = x;
this._offset.y = y;
(z != undefined) && (this._offset.z = z);
this._handler && this._handler.setOffsetArr(this._handlerIndex, this._offset);
}
/**
* Sets billboard scale.
* @public
* @param {number} scale - Scale.
*/
setScale(scale) {
this._scale = scale;
this._handler && this._handler.setScaleArr(this._handlerIndex, scale);
}
/**
* Gets billboard scale.
* @public
* @returns {number}
*/
getScale() {
return this._scale;
}
/**
* Sets screen space offset.
* @public
* @param {og.math.Vector2} offset - Offset size.
*/
setOffset3v(offset) {
this._offset.x = offset.x;
this._offset.y = offset.y;
(offset.z != undefined) && (this._offset.z = offset.z);
this._handler && this._handler.setOffsetArr(this._handlerIndex, offset);
}
/**
* Returns billboard screen space offset size.
* @public
* @returns {og.math.Vector3}
*/
getOffset() {
return this._offset;
}
/**
* Sets billboard screen space rotation in radians.
* @public
* @param {number} rotation - Screen space rotation in radians.
*/
setRotation(rotation) {
this._rotation = rotation;
this._handler && this._handler.setRotationArr(this._handlerIndex, rotation);
}
/**
* Gets screen space rotation.
* @public
* @returns {number}
*/
getRotation() {
return this._rotation;
}
/**
* Sets billboard opacity.
* @public
* @param {number} a - Billboard opacity.
*/
setOpacity(a) {
this._color.w = a;
this.setColor(this._color.x, this._color.y, this._color.z, a);
}
/**
* Sets RGBA color. Each channel from 0.0 to 1.0.
* @public
* @param {number} r - Red.
* @param {number} g - Green.
* @param {number} b - Blue.
* @param {number} a - Alpha.
*/
setColor(r, g, b, a) {
this._color.x = r;
this._color.y = g;
this._color.z = b;
(a != undefined) && (this._color.w = a);
this._handler && this._handler.setRgbaArr(this._handlerIndex, this._color);
}
/**
* Sets RGBA color. Each channel from 0.0 to 1.0.
* @public
* @param {og.math.Vector4} color - RGBA vector.
*/
setColor4v(color) {
this._color.x = color.x;
this._color.y = color.y;
this._color.z = color.z;
(color.w != undefined) && (this._color.w = color.w);
this._handler && this._handler.setRgbaArr(this._handlerIndex, color);
}
/**
* Sets billboard color.
* @public
* @param {string} color - HTML style color.
*/
setColorHTML(color) {
this.setColor4v(og.utils.htmlColorToRgba(color));
}
/**
* Returns RGBA color.
* @public
* @returns {og.math.Vector4}
*/
getColor() {
return this._color;
}
/**
* Sets billboard visibility.
* @public
* @param {boolean} visibility - Visibility flag.
*/
setVisibility(visibility) {
this._visibility = visibility;
this._handler && this._handler.setVisibility(this._handlerIndex, visibility);
}
/**
* Returns billboard visibility.
* @public
* @returns {boolean}
*/
getVisibility() {
return this._visibility;
}
/**
* Sets billboard cartesian aligned vector.
* @public
* @param {number} x - Aligned vector X coordinate.
* @param {number} y - Aligned vector Y coordinate.
* @param {number} z - Aligned vector Z coordinate.
*/
setAlignedAxis(x, y, z) {
this._alignedAxis.x = x;
this._alignedAxis.y = y;
this._alignedAxis.z = z;
this._handler && this._handler.setAlignedAxisArr(this._handlerIndex, this._alignedAxis);
}
/**
* Sets billboard aligned vector.
* @public
* @param {og.math.Vecto3} alignedAxis - Vector to align.
*/
setAlignedAxis3v(alignedAxis) {
this._alignedAxis.x = alignedAxis.x;
this._alignedAxis.y = alignedAxis.y;
this._alignedAxis.z = alignedAxis.z;
this._handler && this._handler.setAlignedAxisArr(this._handlerIndex, alignedAxis);
}
/**
* Returns aligned vector.
* @public
* @returns {og.math.Vector3}
*/
getAlignedAxis() {
return this._alignedAxis;
}
/**
* Removes billboard from hander.
* @public
*/
remove() {
this._entity = null;
this._handler && this._handler.remove(this);
}
/**
* Sets billboard picking color.
* @public
* @param {og.math.Vector3} color - Picking color.
*/
setPickingColor3v(color) {
this._handler && this._handler.setPickingColorArr(this._handlerIndex, color);
}
};
export { BaseBillboard };

View File

@ -1,160 +0,0 @@
/**
* @module og/entity/Billboard
*/
'use strict';
import { BaseBillboard } from './BaseBillboard.js';
/**
* Represents basic quad billboard image.
* @class
* @extends {og.BaseBillboard}
* @param {Object} [options] - Options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
* @param {string} [options.src] - Billboard image url source.
* @param {Image} [options.image] - Billboard image object.
* @param {number} [options.width] - Screen width.
* @param {number} [options.height] - Screen height.
* @param {number} [options.scale] - Billboard scale.
*/
class Billboard extends BaseBillboard {
constructor(options) {
super(options);
options = options || {};
/**
* Image src.
* @protected
* @type {string}
*/
this._src = options.src || null;
/**
* Image object.
* @protected
* @type {Object}
*/
this._image = options.image || null;
/**
* Billboard screen width.
* @protected
* @type {number}
*/
this._width = options.width || (options.size ? options.size[0] : 30);
/**
* Billboard screen height.
* @protected
* @type {number}
*/
this._height = options.height || (options.size ? options.size[1] : 30);
}
/**
* Sets billboard image url source.
* @public
* @param {string} src - Image url.
*/
setSrc(src) {
this._src = src;
var bh = this._handler;
if (bh && src) {
var rn = bh._entityCollection.renderNode;
if (rn) {
var ta = rn.billboardsTextureAtlas;
var that = this;
ta.loadImage(src, function (img) {
if (ta.nodes[img.__nodeIndex]) {
that._image = img;
bh.setTexCoordArr(that._handlerIndex, ta.nodes[that._image.__nodeIndex].texCoords);
} else {
ta.addImage(img);
ta.createTexture();
that._image = img;
rn.updateBillboardsTexCoords();
}
});
}
}
}
/**
* Sets image object.
* @public
* @param {Object} image - JavaScript image object.
*/
setImage(image) {
this.setSrc(image.src);
}
/**
* Sets billboard screen size in pixels.
* @public
* @param {number} width - Billboard width.
* @param {number} height - Billboard height.
*/
setSize(width, height) {
this._width = width;
this._height = height;
this._handler && this._handler.setSizeArr(this._handlerIndex, width * this._scale, height * this._scale);
}
/**
* Returns billboard screen size.
* @public
* @returns {Object}
*/
getSize() {
return {
"width": this._width,
"height": this._height
};
}
/**
* Sets billboard screen width.
* @public
* @param {number} width - Width.
*/
setWidth(width) {
this.setSize(width, this._height);
}
/**
* Gets billboard screen width.
* @public
* @returns {number}
*/
getWidth() {
return this._width;
}
/**
* Sets billboard screen heigh.
* @public
* @param {number} height - Height.
*/
setHeight(height) {
this.setSize(this._width, height);
}
/**
* Gets billboard screen height.
* @public
* @returns {number}
*/
getHeight() {
return this._height;
}
};
export { Billboard };

View File

@ -1,736 +0,0 @@
/**
* @module og/entity/BillboardHandler
*/
'use strict';
import * as shaders from '../shaders/billboard.js';
const PICKINGCOLOR_BUFFER = 0;
const POSITION_BUFFER = 1;
const SIZE_BUFFER = 2;
const OFFSET_BUFFER = 3;
const RGBA_BUFFER = 4;
const ROTATION_BUFFER = 5;
const TEXCOORD_BUFFER = 6;
const VERTEX_BUFFER = 7;
const ALIGNEDAXIS_BUFFER = 8;
/*
* og.BillboardHandler
*
*
*/
class BillboardHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
this._entityCollection = entityCollection;
this._renderer = null;
this._billboards = [];
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._texCoordBuffer = null;
this._vertexBuffer = null;
this._alignedAxisBuffer = null;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._pickingColorBuffer = null;
this._pickingColorArr = [];
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[PICKINGCOLOR_BUFFER] = this.createPickingColorBuffer;
this._buffersUpdateCallbacks[POSITION_BUFFER] = this.createPositionBuffer;
this._buffersUpdateCallbacks[SIZE_BUFFER] = this.createSizeBuffer;
this._buffersUpdateCallbacks[OFFSET_BUFFER] = this.createOffsetBuffer;
this._buffersUpdateCallbacks[RGBA_BUFFER] = this.createRgbaBuffer;
this._buffersUpdateCallbacks[ROTATION_BUFFER] = this.createRotationBuffer;
this._buffersUpdateCallbacks[TEXCOORD_BUFFER] = this.createTexCoordBuffer;
this._buffersUpdateCallbacks[VERTEX_BUFFER] = this.createVertexBuffer;
this._buffersUpdateCallbacks[ALIGNEDAXIS_BUFFER] = this.createAlignedAxisBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this.__staticId = BillboardHandler.staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static concArr(dest, curr) {
for (var i = 0; i < curr.length; i++) {
dest.push(curr[i]);
}
}
initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.billboard) {
var isSingleBuffer = !this._renderer.isMultiFramebufferCompatible();
this._renderer.handler.addShaderProgram(shaders.billboard(isSingleBuffer));
}
if (!this._renderer.handler.shaderPrograms.billboardPicking) {
this._renderer.handler.addShaderProgram(shaders.billboardPicking());
}
}
}
setRenderer(renderer) {
this._renderer = renderer;
this.initShaderProgram();
}
refresh() {
var i = this._changedBuffers.length;
while (i--) {
this._changedBuffers[i] = true;
}
}
_removeBillboards() {
var i = this._billboards.length;
while (i--) {
var bi = this._billboards[i];
bi._handlerIndex = -1;
bi._handler = null;
}
this._billboards.length = 0;
this._billboards = [];
}
clear() {
this._texCoordArr.length = 0;
this._vertexArr.length = 0;
this._positionArr.length = 0;
this._sizeArr.length = 0;
this._offsetArr.length = 0;
this._rgbaArr.length = 0;
this._rotationArr.length = 0;
this._alignedAxisArr.length = 0;
this._pickingColorArr.length = 0;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._pickingColorArr = [];
this._removeBillboards();
this._deleteBuffers();
this.refresh();
}
_deleteBuffers() {
var gl = this._renderer.handler.gl;
gl.deleteBuffer(this._positionBuffer);
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._offsetBuffer);
gl.deleteBuffer(this._rgbaBuffer);
gl.deleteBuffer(this._rotationBuffer);
gl.deleteBuffer(this._vertexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._alignedAxisBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._vertexBuffer = null;
this._texCoordBuffer = null;
this._alignedAxisBuffer = null;
this._pickingColorBuffer = null;
}
update() {
if (this._renderer) {
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
}
}
add(billboard) {
if (billboard._handlerIndex == -1) {
billboard._handler = this;
billboard._handlerIndex = this._billboards.length;
this._billboards.push(billboard);
this._addBillboardToArrays(billboard);
this.refresh();
billboard.setSrc(billboard._src || billboard._image && billboard._image.src);
}
}
_addBillboardToArrays(billboard) {
if (billboard._visibility) {
BillboardHandler.concArr(this._vertexArr, [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
} else {
BillboardHandler.concArr(this._vertexArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
BillboardHandler.concArr(this._texCoordArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
var x = billboard._position.x, y = billboard._position.y, z = billboard._position.z, w = billboard._scale;
BillboardHandler.concArr(this._positionArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = billboard._width; y = billboard._height;
BillboardHandler.concArr(this._sizeArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = billboard._offset.x; y = billboard._offset.y; z = billboard._offset.z;
BillboardHandler.concArr(this._offsetArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = billboard._color.x; y = billboard._color.y; z = billboard._color.z; w = billboard._color.w;
BillboardHandler.concArr(this._rgbaArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = billboard._rotation;
BillboardHandler.concArr(this._rotationArr, [x, x, x, x, x, x]);
x = billboard._alignedAxis.x, y = billboard._alignedAxis.y, z = billboard._alignedAxis.z;
BillboardHandler.concArr(this._alignedAxisArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = billboard._entity._pickingColor.x / 255, y = billboard._entity._pickingColor.y / 255, z = billboard._entity._pickingColor.z / 255;
BillboardHandler.concArr(this._pickingColorArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
}
_displayPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.billboard.activate();
var sh = h.shaderPrograms.billboard._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniform1i(shu.u_texture._pName, 0);
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rgbaBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._rgbaBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_pickingPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.billboardPicking.activate();
var sh = h.shaderPrograms.billboardPicking._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.a_pickingColor._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
};
draw() {
if (this._billboards.length) {
this.update();
this._displayPASS();
}
}
drawPicking() {
if (this._billboards.length && this.pickingEnabled) {
this._pickingPASS();
}
}
reindexBillbordsArray(startIndex) {
var b = this._billboards;
for (var i = startIndex; i < b.length; i++) {
b[i]._handlerIndex = i;
}
}
_removeBillboard(billboard) {
var bi = billboard._handlerIndex;
this._billboards.splice(bi, 1);
var i = bi * 24;
this._rgbaArr.splice(i, 24);
this._positionArr.splice(i, 24);
i = bi * 18;
this._offsetArr.splice(i, 18);
this._alignedAxisArr.splice(i, 18);
this._pickingColorArr.splice(i, 18);
i = bi * 12;
this._vertexArr.splice(i, 12);
this._sizeArr.splice(i, 12);
this._texCoordArr.splice(i, 12);
i = bi * 6;
this._rotationArr.splice(i, 6);
this.reindexBillbordsArray(bi);
this.refresh();
billboard._handlerIndex = -1;
billboard._handler = null;
}
remove(billboard) {
if (billboard._handler && this.__staticId == billboard._handler.__staticId) {
this._removeBillboard(billboard);
}
}
setPositionArr(index, position) {
var i = index * 24;
var a = this._positionArr, x = position.x, y = position.y, z = position.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = z;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 16] = x;
a[i + 17] = y;
a[i + 18] = z;
a[i + 20] = x;
a[i + 21] = y;
a[i + 22] = z;
this._changedBuffers[POSITION_BUFFER] = true;
}
setScaleArr(index, scale) {
var i = index * 24;
var a = this._positionArr;
a[i + 3] = scale;
a[i + 7] = scale;
a[i + 11] = scale;
a[i + 15] = scale;
a[i + 19] = scale;
a[i + 23] = scale;
this._changedBuffers[POSITION_BUFFER] = true;
}
setPickingColorArr(index, color) {
var i = index * 18;
var a = this._pickingColorArr, x = color.x / 255, y = color.y / 255, z = color.z / 255;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[PICKINGCOLOR_BUFFER] = true;
}
setSizeArr(index, width, height) {
var i = index * 12;
var a = this._sizeArr, x = width, y = height;
a[i] = x;
a[i + 1] = y;
a[i + 2] = x;
a[i + 3] = y;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = x;
a[i + 11] = y;
this._changedBuffers[SIZE_BUFFER] = true;
}
setOffsetArr(index, offset) {
var i = index * 18;
var a = this._offsetArr, x = offset.x, y = offset.y, z = offset.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[OFFSET_BUFFER] = true;
}
setRgbaArr(index, rgba) {
var i = index * 24;
var a = this._rgbaArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = w;
a[i + 4] = x;
a[i + 5] = y;
a[i + 6] = z;
a[i + 7] = w;
a[i + 8] = x;
a[i + 9] = y;
a[i + 10] = z;
a[i + 11] = w;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = w;
a[i + 16] = x;
a[i + 17] = y;
a[i + 18] = z;
a[i + 19] = w;
a[i + 20] = x;
a[i + 21] = y;
a[i + 22] = z;
a[i + 23] = w;
this._changedBuffers[RGBA_BUFFER] = true;
}
setRotationArr(index, rotation) {
var i = index * 6;
var a = this._rotationArr;
a[i] = rotation;
a[i + 1] = rotation;
a[i + 2] = rotation;
a[i + 3] = rotation;
a[i + 4] = rotation;
a[i + 5] = rotation;
this._changedBuffers[ROTATION_BUFFER] = true
}
setTexCoordArr(index, tcoordArr) {
var i = index * 12;
var a = this._texCoordArr;
a[i] = tcoordArr[0];
a[i + 1] = tcoordArr[1];
a[i + 2] = tcoordArr[2];
a[i + 3] = tcoordArr[3];
a[i + 4] = tcoordArr[4];
a[i + 5] = tcoordArr[5];
a[i + 6] = tcoordArr[6];
a[i + 7] = tcoordArr[7];
a[i + 8] = tcoordArr[8];
a[i + 9] = tcoordArr[9];
a[i + 10] = tcoordArr[10];
a[i + 11] = tcoordArr[11];
this._changedBuffers[TEXCOORD_BUFFER] = true;
}
setVisibility(index, visibility) {
var vArr;
if (visibility) {
vArr = [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5];
} else {
vArr = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
}
this.setVertexArr(index, vArr);
}
setVertexArr(index, vertexArr) {
var i = index * 12;
var a = this._vertexArr;
a[i] = vertexArr[0];
a[i + 1] = vertexArr[1];
a[i + 2] = vertexArr[2];
a[i + 3] = vertexArr[3];
a[i + 4] = vertexArr[4];
a[i + 5] = vertexArr[5];
a[i + 6] = vertexArr[6];
a[i + 7] = vertexArr[7];
a[i + 8] = vertexArr[8];
a[i + 9] = vertexArr[9];
a[i + 10] = vertexArr[10];
a[i + 11] = vertexArr[11];
this._changedBuffers[VERTEX_BUFFER] = true;
}
setAlignedAxisArr(index, alignedAxis) {
var i = index * 18;
var a = this._alignedAxisArr, x = alignedAxis.x, y = alignedAxis.y, z = alignedAxis.z;
a[i] = x;
a[i + 1] = y;
a[i + 2] = z;
a[i + 3] = x;
a[i + 4] = y;
a[i + 5] = z;
a[i + 6] = x;
a[i + 7] = y;
a[i + 8] = z;
a[i + 9] = x;
a[i + 10] = y;
a[i + 11] = z;
a[i + 12] = x;
a[i + 13] = y;
a[i + 14] = z;
a[i + 15] = x;
a[i + 16] = y;
a[i + 17] = z;
this._changedBuffers[ALIGNEDAXIS_BUFFER] = true;
}
createPositionBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._positionBuffer);
this._positionBuffer = h.createArrayBuffer(new Float32Array(this._positionArr), 4, this._positionArr.length / 4, h.gl.DYNAMIC_DRAW);
}
createSizeBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._sizeBuffer);
this._sizeBuffer = h.createArrayBuffer(new Float32Array(this._sizeArr), 2, this._sizeArr.length / 2);
}
createOffsetBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._offsetBuffer);
this._offsetBuffer = h.createArrayBuffer(new Float32Array(this._offsetArr), 3, this._offsetArr.length / 3);
}
createRgbaBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._rgbaBuffer);
this._rgbaBuffer = h.createArrayBuffer(new Float32Array(this._rgbaArr), 4, this._rgbaArr.length / 4);
}
createRotationBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._rotationBuffer);
this._rotationBuffer = h.createArrayBuffer(new Float32Array(this._rotationArr), 1, this._rotationArr.length, h.gl.DYNAMIC_DRAW);
}
createVertexBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._vertexBuffer);
this._vertexBuffer = h.createArrayBuffer(new Float32Array(this._vertexArr), 2, this._vertexArr.length / 2, h.gl.DYNAMIC_DRAW);
}
createTexCoordBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._texCoordBuffer);
this._texCoordBuffer = h.createArrayBuffer(new Float32Array(this._texCoordArr), 2, this._texCoordArr.length / 2, h.gl.DYNAMIC_DRAW);
}
createAlignedAxisBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._alignedAxisBuffer);
this._alignedAxisBuffer = h.createArrayBuffer(new Float32Array(this._alignedAxisArr), 3, this._alignedAxisArr.length / 3);
}
createPickingColorBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._pickingColorBuffer);
this._pickingColorBuffer = h.createArrayBuffer(new Float32Array(this._pickingColorArr), 3, this._pickingColorArr.length / 3);
}
refreshTexCoordsArr() {
var bc = this._entityCollection;
if (bc && bc.renderNode) {
var ta = bc.renderNode.billboardsTextureAtlas;
for (var i = 0; i < this._billboards.length; i++) {
var bi = this._billboards[i];
var img = bi._image;
if (img) {
var imageNode = ta.nodes[bi._image.__nodeIndex];
if (imageNode) {
this.setTexCoordArr(bi._handlerIndex, imageNode.texCoords);
}
}
}
}
}
};
export { BillboardHandler };

View File

@ -1,607 +0,0 @@
/**
* @module og/entity/Entity
*/
'use strict';
import * as mercator from '../mercator.js';
import * as utils from '../utils/shared.js';
import { Billboard } from './Billboard.js';
//import { Box } from '../shapes/Box.js';
import { Extent } from '../Extent.js';
import { Geometry } from './Geometry.js';
import { Label } from './Label.js';
import { LonLat } from '../LonLat.js';
import { Polyline } from './Polyline.js';
import { PointCloud } from './PointCloud.js';
//import { Sphere } from '../shapes/Sphere.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Entity instances aggregate multiple forms of visualization into a single high-level object.
* They can be created manually and added to entity collection.
*
* @class
* @param {Object} [options] - Entity options:
* @param {string} [options.name] - A human readable name to display to users. It does not have to be unique.
* @param {og.math.Vector3|Array.<number>} [options.cartesian] - Spatial entities like billboard, label, sphere etc. cartesian position.
* @param {og.LonLat} [options.lonlat] - Geodetic coordiantes for an entities like billboard, label, sphere etc.
* @param {boolean} [options.aground] - True for entities that have to be placed on the relief.
* @param {boolean} [options.visibility] - Entity visibility.
* @param {*} [options.billboard] - Billboard options(see {@link og.Billboard}).
* @param {*} [options.label] - Label options(see {@link og.Label}).
* @param {*} [options.sphere] - Sphere options(see {@link og.shape.Sphere}).
* @param {*} [options.box] - Sphere options(see {@link og.shape.Box}).
* @param {*} [options.Polyline] - Polyline options(see {@link og.Polyline}).
* @param {*} [options.pointCloud] - Point cloud options(see {@link og.PointCloud}).
* @param {*} [options.geometry] - Geometry options (see {@link og.Geometry}), available for vector layer only.
* @param {*} [options.properties] - Entity custom properties.
*/
class Entity {
constructor(options) {
options = options || {};
options.properties = options.properties || {};
/**
* Unic identifier.
* @public
* @readonly
*/
this.id = Entity.__staticCounter++;
/**
* Entity user defined properties.
* @public
* @type {Object}
*/
this.properties = options.properties || {};
/**
* Entity name.
* @public
* @type {string}
*/
this.properties.name = this.properties.name || "noname";
/**
* Children entities.
* @public
* @type {Array.<og.Entity>}
*/
this.childrenNodes = [];
/**
* Parent entity.
* @public
* @type {og.Entity}
*/
this.parent = null;
/**
* Entity cartesian position.
* @protected
* @type {og.math.Vector3}
*/
this._cartesian = utils.createVector3(options.cartesian);
/**
* Geodetic entity coordiantes.
* @protected
* @type {og.LonLat}
*/
this._lonlat = utils.createLonLat(options.lonlat);
/**
* World Mercator entity coordinates.
* @protected
* @type {og.LonLat}
*/
this._lonlatMerc = null;
/**
* Entity visible terrain altitude.
* @protected
* @type {number}
*/
this._altitude = options.altitude || 0.0;
/**
* Visibility flag.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility != undefined ? options.visibility : true;
/**
* Entity collection that this entity belongs to.
* @protected
* @type {og.EntityCollection}
*/
this._entityCollection = null;
/**
* Entity collection array store index.
* @protected
* @type {number}
*/
this._entityCollectionIndex = -1;
/**
* Assigned vector layer pointer.
* @protected
* @type {og.layer.Vector}
*/
this._layer = null;
/**
* Assigned vector layer entity array index.
* @protected
* @type {number}
*/
this._layerIndex = -1;
/**
* Picking color.
* @protected
* @type {og.math.Vector3}
*/
this._pickingColor = new Vec3(0, 0, 0);
this._featureConstructorArray = {
"billboard": [Billboard, this.setBillboard],
"label": [Label, this.setLabel],
"sphere": [Sphere, this.setShape],
"box": [Box, this.setShape],
"polyline": [Polyline, this.setPolyline],
"pointCloud": [PointCloud, this.setPointCloud],
"geometry": [Geometry, this.setGeometry],
};
/**
* Billboard entity.
* @public
* @type {og.Billboard}
*/
this.billboard = this._createOptionFeature('billboard', options.billboard);
/**
* Text label entity.
* @public
* @type {og.Label}
*/
this.label = this._createOptionFeature('label', options.label);
/**
* Shape entity.
* @public
* @type {og.shape.BaseShape}
*/
this.shape = this._createOptionFeature('sphere', options.sphere || options.box);
/**
* Polyline entity.
* @public
* @type {og.Polyline}
*/
this.polyline = this._createOptionFeature('polyline', options.polyline);
/**
* PointCloud entity.
* @public
* @type {og.PointCloud}
*/
this.pointCloud = this._createOptionFeature('pointCloud', options.pointCloud);
/**
* Geometry entity(available only for vector layer).
* @public
* @type {og.Geometry}
*/
this.geometry = this._createOptionFeature('geometry', options.geometry);
//this.model = null;
//...
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_createOptionFeature(featureName, options) {
if (options) {
var c = this._featureConstructorArray[featureName];
return c[1].call(this, new c[0](options));
}
return null;
}
/**
* Adds current entity into the specified entity collection.
* @public
* @param {og.EntityCollection|og.layer.Vector} collection - Specified entity collection or vector layer.
* @param {Boolean} [rightNow=false] - Entity insertion option for vector layer.
* @returns {og.Entity} - This object.
*/
addTo(collection, rightNow) {
collection.add(this, rightNow);
return this;
}
/**
* Removes current entity from collection and layer.
* @public
*/
remove() {
this._layer && this._layer.removeEntity(this);
this._entityCollection && this._entityCollection.removeEntity(this);
}
/**
* Sets the entity visibility.
* @public
* @param {boolean} visibility - Entity visibility.
*/
setVisibility(visibility) {
this._visibility = visibility;
//billboards
this.billboard && this.billboard.setVisibility(visibility);
//labels
this.label && this.label.setVisibility(visibility);
//shape
this.shape && this.shape.setVisibility(visibility);
//polyline
this.polyline && this.polyline.setVisibility(visibility);
//geometry
this.geometry && this.geometry.setVisibility(visibility);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setVisibility(visibility);
}
}
/**
* Returns entity visibility.
* @public
* @returns {boolean} -
*/
getVisibility() {
return this._visibility;
}
/**
* Sets entity cartesian position.
* @public
* @param {og.math.Vector3} cartesian - Cartesian position in 3d space.
*/
setCartesian3v(cartesian) {
this.setCartesian(cartesian.x, cartesian.y, cartesian.z);
}
/**
* Sets entity cartesian position.
* @public
* @param {number} x - 3d space X - position.
* @param {number} y - 3d space Y - position.
* @param {number} z - 3d space Z - position.
*/
setCartesian(x, y, z) {
var p = this._cartesian;
p.x = x;
p.y = y;
p.z = z;
//billboards
this.billboard && this.billboard.setPosition3v(p);
//labels
this.label && this.label.setPosition3v(p);
//shape
this.shape && this.shape.setPosition3v(p);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setCartesian(x, y, z);
}
var ec = this._entityCollection;
if (ec && ec.renderNode && ec.renderNode.ellipsoid) {
this._lonlat = ec.renderNode.ellipsoid.cartesianToLonLat(p);
if (Math.abs(this._lonlat.lat) < mercator.MAX_LAT) {
this._lonlatMerc = this._lonlat.forwardMercator();
} else {
this._lonlatMerc = null;
}
}
ec && ec.events.dispatch(ec.events.entitymove, this);
}
/**
* Sets entity cartesian position without moveentity event dispatching.
* @protected
* @param {og.math.Vector3} cartesian - Cartesian position in 3d space.
*/
_setCartesian3vSilent(cartesian) {
var p = this._cartesian;
p.x = cartesian.x;
p.y = cartesian.y;
p.z = cartesian.z;
//billboards
this.billboard && this.billboard.setPosition3v(p);
//labels
this.label && this.label.setPosition3v(p);
//shape
this.shape && this.shape.setPosition3v(p);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setCartesian(x, y, z);
}
}
/**
* Gets entity geodetic coordinates.
* @public
* @returns {og.LonLat} -
*/
getLonLat() {
return this._lonlat.clone();
}
/**
* Sets geodetic coordinates of the entity point object.
* @public
* @param {og.LonLat} lonlat - WGS84 coordinates.
*/
setLonLat(lonlat) {
var l = this._lonlat;
l.lon = lonlat.lon;
l.lat = lonlat.lat;
l.height = lonlat.height;
var ec = this._entityCollection;
if (ec && ec.renderNode && ec.renderNode.ellipsoid) {
if (Math.abs(lonlat.lat) < mercator.MAX_LAT) {
this._lonlatMerc = lonlat.forwardMercator();
} else {
this._lonlatMerc = null;
}
this._cartesian = ec.renderNode.ellipsoid.lonLatToCartesian(lonlat);
this.setCartesian3v(this._cartesian);
}
}
/**
* Sets entity altitude over the planet.
* @public
* @param {number} altitude - Altitude.
*/
setAltitude(altitude) {
this._altitude = altitude;
}
/**
* Returns carteain position.
* @public
* @returns {og.math.Vector3} -
*/
getCartesian() {
return this._cartesian;
}
/**
* Sets entity billboard.
* @public
* @param {og.Billboard} billboard - Billboard object.
* @returns {og.Billboard} -
*/
setBillboard(billboard) {
if (this.billboard) {
this.billboard.remove();
}
this.billboard = billboard;
this.billboard._entity = this;
this.billboard.setPosition3v(this._cartesian);
this.billboard.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._billboardHandler.add(billboard);
return billboard;
}
/**
* Sets entity label.
* @public
* @param {og.Label} label - Text label.
* @returns {og.Label} -
*/
setLabel(label) {
if (this.label) {
this.label.remove();
}
this.label = label;
this.label._entity = this;
this.label.setPosition3v(this._cartesian);
this.label.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._labelHandler.add(label);
return label;
}
/**
* Sets entity shape.
* @public
* @param {og.BaseShape} shape - Shape object.
* @returns {og.Polyline} -
*/
setShape(shape) {
if (this.shape) {
this.shape.remove();
}
this.shape = shape;
this.shape._entity = this;
this.shape.setPosition3v(this._cartesian);
this.shape.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._shapeHandler.add(shape);
return shape;
}
/**
* Sets entity polyline.
* @public
* @param {og.Polyline} polyline - Polyline object.
* @returns {og.Polyline} -
*/
setPolyline(polyline) {
if (this.polyline) {
this.polyline.remove();
}
this.polyline = polyline;
this.polyline._entity = this;
this.polyline.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._polylineHandler.add(polyline);
return polyline;
}
/**
* Sets entity pointCloud.
* @public
* @param {og.PointCloud} pointCloud - PointCloud object.
* @returns {og.PointCloud} -
*/
setPointCloud(pointCloud) {
if (this.pointCloud) {
this.pointCloud.remove();
}
this.pointCloud = pointCloud;
this.pointCloud._entity = this;
this.pointCloud.setVisibility(this._visibility);
this._entityCollection && this._entityCollection._pointCloudHandler.add(pointCloud);
return pointCloud;
}
/**
* Sets entity geometry.
* @public
* @param {og.Geometry} geometry - Geometry object.
* @returns {og.Geometry} -
*/
setGeometry(geometry) {
if (this.geometry) {
this.geometry.remove();
}
this.geometry = geometry;
this.geometry._entity = this;
this.geometry.setVisibility(this._visibility);
this._layer && this._layer.add(this);
return geometry;
}
/**
* Append child entity.
* @public
* @param {og.Entity} entity - Child entity.
*/
appendChild(entity) {
entity._entityCollection = this._entityCollection;
entity._pickingColor = this._pickingColor;
entity.parent = this;
this.childrenNodes.push(entity);
this._entityCollection && this._entityCollection._addRecursively(entity);
}
/**
* Appends entity items(billboard, label etc.) picking color.
* @public
*/
setPickingColor() {
var c = this._pickingColor;
//billboard
this.billboard && this.billboard.setPickingColor3v(c);
//label
this.label && this.label.setPickingColor3v(c);
//shape
this.shape && this.shape.setPickingColor3v(c);
//polyline
this.polyline && this.polyline.setPickingColor3v(c);
for (var i = 0; i < this.childrenNodes.length; i++) {
this.childrenNodes[i].setPickingColor();
}
}
/**
* Return geodethic extent.
* @returns {og.Extent} -
*/
getExtent() {
var res;
var c = this._lonlat;
if (this.billboard || this.label) {
res = new Extent(new LonLat(c.lon, c.lat), new LonLat(c.lon, c.lat));
} else {
res = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
}
var sw = res.southWest,
ne = res.northEast;
if (this.polyline) {
var e = this.polyline.getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
if (this.geometry) {
var e = this.geometry.getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
for (var i = 0; i < this.childrenNodes.length; i++) {
var e = this.childrenNodes[i].getExtent();
if (e.southWest.lon < sw.lon) sw.lon = e.southWest.lon;
if (e.southWest.lat < sw.lat) sw.lat = e.southWest.lat;
if (e.northEast.lon > ne.lon) ne.lon = e.northEast.lon;
if (e.northEast.lat > ne.lat) ne.lat = e.northEast.lat;
}
return res;
}
};
export { Entity };

View File

@ -1,774 +0,0 @@
/**
* @module og/entity/EntityCollection
*/
'use strict';
import * as math from '../math.js';
import { BillboardHandler } from './BillboardHandler.js';
import { Events } from '../Events.js';
import { LabelHandler } from './LabelHandler.js';
import { PolylineHandler } from './PolylineHandler.js';
import { PointCloudHandler } from './PointCloudHandler.js';
import { ShapeHandler } from './ShapeHandler.js';
/**
* An observable collection of og.Entity instances where each entity has a unique id.
* Entity collection provide handlers for an each type of entity like billboard, label or 3ds object.
* @constructor
* @param {Object} [options] - Entity options:
* @param {Array.<og.Entity>} [options.entities] - Entities array.
* @param {boolean} [options.visibility=true] - Entity visibility.
* @param {Array.<number,number,number>} [options.scaleByDistance] - Entity scale by distance parameters.
* First index - near distance to the entity, after entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @param {number} [options.opacity] - Entity global opacity.
* @param {boolean} [options.pickingEnabled=true] - Entity picking enable.
* @fires og.EntityCollection#entitymove
* @fires og.EntityCollection#draw
* @fires og.EntityCollection#drawend
* @fires og.EntityCollection#add
* @fires og.EntityCollection#remove
* @fires og.EntityCollection#entityadd
* @fires og.EntityCollection#entityremove
* @fires og.EntityCollection#visibilitychange
* @fires og.EntityCollection#mousemove
* @fires og.EntityCollection#mouseenter
* @fires og.EntityCollection#mouseleave
* @fires og.EntityCollection#lclick
* @fires og.EntityCollection#rclick
* @fires og.EntityCollection#mclick
* @fires og.EntityCollection#ldblclick
* @fires og.EntityCollection#rdblclick
* @fires og.EntityCollection#mdblclick
* @fires og.EntityCollection#lup
* @fires og.EntityCollection#rup
* @fires og.EntityCollection#mup
* @fires og.EntityCollection#ldown
* @fires og.EntityCollection#rdown
* @fires og.EntityCollection#mdown
* @fires og.EntityCollection#lhold
* @fires og.EntityCollection#rhold
* @fires og.EntityCollection#mhold
* @fires og.EntityCollection#mousewheel
* @fires og.EntityCollection#touchmove
* @fires og.EntityCollection#touchstart
* @fires og.EntityCollection#touchend
* @fires og.EntityCollection#doubletouch
* @fires og.EntityCollection#touchleave
* @fires og.EntityCollection#touchenter
*/
class EntityCollection {
constructor(options) {
options = options || {};
/**
* Unic identifier.
* @public
* @readonly
*/
this.id = EntityCollection.__staticCounter++;
/**
* Render node collections array index.
* @protected
* @type {number}
*/
this._renderNodeIndex = -1;
/**
* Render node context.
* @public
* @type {og.scene.RenderNode}
*/
this.renderNode = null;
/**
* Visibility option.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility == undefined ? true : options.visibility;
/**
* Billboards handler
* @public
* @type {og.BillboardHandler}
*/
this.billboardHandler = new BillboardHandler(this);
/**
* Labels handler
* @public
* @type {og.LabelHandler}
*/
this.labelHandler = new LabelHandler(this);
/**
* Shape handler
* @public
* @type {og.ShapeHandler}
*/
this.shapeHandler = new ShapeHandler(this);
/**
* Polyline handler
* @public
* @type {og.PolylineHandler}
*/
this.polylineHandler = new PolylineHandler(this);
/**
* PointCloud handler
* @public
* @type {og.PointCloudHandler}
*/
this.pointCloudHandler = new PointCloudHandler(this);
//
//...
if (options.pickingEnabled != undefined) {
this.setPickingEnabled(options.pickingEnabled);
}
/**
* Entities array.
* @protected
* @type {Array.<og.Entity>}
*/
this._entities = options.entities || [];
/**
* First index - near distance to the entity, after entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @public
* @type {Array.<number,number,number>}
*/
this.scaleByDistance = options.scaleByDistance || [math.MAX32, math.MAX32, math.MAX32];
/**
* Global opacity.
* @protected
* @type {number}
*/
this._opacity = options.opacity == undefined ? 1.0 : options.opacity;
/**
* Opacity state during the animated opacity.
* @protected
* @type {number}
*/
this._animatedOpacity = this._opacity;
/**
* Entity collection events handler.
* @public
* @type {og.Events}
*/
this.events = new Events(EVENT_NAMES);
//initialize current entities
this.addEntities(this._entities);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Sets collection visibility.
* @public
* @param {boolean} visibility - Visibility flag.
*/
setVisibility(visibility) {
this._visibility = visibility;
this._animatedOpacity = this._opacity * (visibility ? 1 : 0);
this.events.dispatch(this.events.visibilitychange, this);
}
/**
* Returns collection visibility.
* @public
* @returns {boolean}
*/
getVisibility() {
return this._visibility;
}
/**
* Sets collection opacity.
* @public
* @param {number} opacity - Opacity.
*/
setOpacity(opacity) {
this._opacity = opacity;
}
/**
* Sets collection picking ability.
* @public
* @param {boolean} enable - Picking enable flag.
*/
setPickingEnabled(enable) {
this.billboardHandler.pickingEnabled = enable;
this.labelHandler.pickingEnabled = enable;
this.polylineHandler.pickingEnabled = enable;
this.shapeHandler.pickingEnabled = enable;
this.pointCloudHandler.pickingEnabled = enable;
}
/**
* Gets collection opacity.
* @public
* @param {number} opacity - Opacity.
*/
getOpacity() {
return this._opacity;
}
/**
* Sets scale by distance parameters.
* @public
* @param {number} near - Full scale entity distance.
* @param {number} far - Zerol scale entity distance.
* @param {number} [farInvisible] - Entity visibility distance.
*/
setScaleByDistance(near, far, farInvisible) {
this.scaleByDistance[0] = near;
this.scaleByDistance[1] = far;
this.scaleByDistance[2] = farInvisible || math.MAX32;
}
_addRecursively(entity) {
//billboard
entity.billboard && this.billboardHandler.add(entity.billboard);
//label
entity.label && this.labelHandler.add(entity.label);
//shape
entity.shape && this.shapeHandler.add(entity.shape);
//polyline
entity.polyline && this.polylineHandler.add(entity.polyline);
//pointCloud
entity.pointCloud && this.pointCloudHandler.add(entity.pointCloud);
this.events.dispatch(this.events.entityadd, entity);
for (var i = 0; i < entity.childrenNodes.length; i++) {
entity.childrenNodes[i]._entityCollection = this;
entity.childrenNodes[i]._entityCollectionIndex = entity._entityCollectionIndex;
entity.childrenNodes[i]._pickingColor = entity._pickingColor;
this._addRecursively(entity.childrenNodes[i]);
}
}
/**
* Adds entity to the collection and returns collection.
* @public
* @param {og.Entity} entity - Entity.
* @returns {og.EntityCollection}
*/
add(entity) {
if (!entity._entityCollection) {
entity._entityCollection = this;
entity._entityCollectionIndex = this._entities.length;
this._entities.push(entity);
var rn = this.renderNode;
if (rn) {
rn.renderer && rn.renderer.assignPickingColor(entity);
rn.ellipsoid && entity._lonlat && entity.setCartesian3v(rn.ellipsoid.lonLatToCartesian(entity._lonlat));
}
this._addRecursively(entity);
}
return this;
}
/**
* Adds entities array to the collection and returns collection.
* @public
* @param {Array.<og.Entity>} entities - Entities array.
* @returns {og.EntityCollection}
*/
addEntities(entities) {
var i = entities.length;
while (i--) {
this.add(entities[i]);
}
return this;
}
/**
* Returns true if the entity belongs this collection, otherwise returns false.
* @public
* @param {og.Entity} entity - Entity.
* @returns {boolean}
*/
belongs(entity) {
return (entity._entityCollection && this._renderNodeIndex == entity._entityCollection._renderNodeIndex);
}
_removeRecursively(entity) {
entity._entityCollection = null;
entity._entityCollectionIndex = -1;
//billboard
entity.billboard && this.billboardHandler.remove(entity.billboard);
//label
entity.label && this.labelHandler.remove(entity.label);
//shape
entity.shape && this.shapeHandler.remove(entity.shape);
//polyline
entity.polyline && this.polylineHandler.remove(entity.polyline);
//pointCloud
entity.pointCloud && this.pointCloudHandler.remove(entity.pointCloud);
for (var i = 0; i < entity.childrenNodes.length; i++) {
this._removeRecursively(entity.childrenNodes[i]);
}
}
/**
* Removes entity from this collection.
* @public
* @param {og.Entity} entity - Entity to remove.
*/
removeEntity(entity) {
this._entities.splice(entity._entityCollectionIndex, 1);
this.reindexEntitiesArray(entity._entityCollectionIndex);
//clear picking color
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(entity);
entity._pickingColor.clear();
}
if (this.belongs(entity)) {
this._removeRecursively(entity);
}
this.events.dispatch(this.events.entityremove, entity);
}
_removeEntitySilent(entity) {
this._entities.splice(entity._entityCollectionIndex, 1);
this.reindexEntitiesArray(entity._entityCollectionIndex);
//clear picking color
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(entity);
entity._pickingColor.clear();
}
if (this.belongs(entity)) {
this._removeRecursively(entity);
}
}
/**
* Creates or refresh collected entities picking color.
* @public
*/
createPickingColors() {
var e = this._entities;
for (var i = 0; i < e.length; i++) {
if (!e[i].parent) {
this.renderNode.renderer.assignPickingColor(e[i]);
e[i].setPickingColor();
}
}
}
/**
* Refresh collected entities indexes from startIndex entitytes collection array position.
* @public
* @param {number} startIndex - Entities collection array index.
*/
reindexEntitiesArray(startIndex) {
var e = this._entities;
for (var i = startIndex; i < e.length; i++) {
e[i]._entityCollectionIndex = i;
}
}
/**
* Adds this collection to render node.
* @public
* @param {og.scene.RenderNode} renderNode - Render node.
* @param {boolean} [isHidden] - Uses in vector layers that render in planet render specific function.
* @returns {og.EntityCollection}
*/
addTo(renderNode, isHidden) {
if (!this.renderNode) {
this.renderNode = renderNode;
if (!isHidden) {
this._renderNodeIndex = renderNode.entityCollections.length;
renderNode.entityCollections.push(this);
}
renderNode.ellipsoid && this._updateGeodeticCoordinates(renderNode.ellipsoid);
this.setRenderer(renderNode.renderer);
this.shapeHandler.setRenderNode(renderNode);
this.polylineHandler.setRenderNode(renderNode);
this.pointCloudHandler.setRenderNode(renderNode);
this.events.dispatch(this.events.add, this);
}
return this;
}
/**
* Updates coordiantes all lonLat entities in collection after collecction attached to the planet node.
* @private
* @param {og.Ellipsoid} ellipsoid - Globe ellipsoid.
*/
_updateGeodeticCoordinates(ellipsoid) {
var e = this._entities;
var i = e.length;
while (i--) {
var ei = e[i];
ei._lonlat && ei.setCartesian3v(ellipsoid.lonLatToCartesian(ei._lonlat));
}
}
/**
* Sets renderer. Used in renderer initialization, when entity collection starts before renderer has initialized.
* @public
* @param {og.Renderer} renderer - Renderer.
*/
setRenderer(renderer) {
//todo: better to replace to setRenderNode function
if (renderer) {
this.billboardHandler.setRenderer(renderer);
this.labelHandler.setRenderer(renderer);
this.updateBillboardsTextureAtlas();
this.updateLabelsFontAtlas();
this.createPickingColors();
}
}
/**
* Updates billboard texture atlas.
* @public
*/
updateBillboardsTextureAtlas() {
var b = this.billboardHandler._billboards;
for (var i = 0; i < b.length; i++) {
b[i].setSrc(b[i]._src);
}
}
/**
* Updates labels font atlas.
* @public
*/
updateLabelsFontAtlas() {
if (this.renderNode) {
var l = this.labelHandler._billboards;
for (var i = 0; i < l.length; i++) {
l[i].assignFontAtlas(this.renderNode.fontAtlas);
}
}
}
/**
* Removes collection from render node.
* @public
*/
remove() {
if (this.renderNode) {
if (this._renderNodeIndex != -1) {
this.renderNode.entityCollections.splice(this._renderNodeIndex, 1);
//reindex in the renderNode
for (var i = this._renderNodeIndex; i < this.renderNode.entityCollections.length; i++) {
this.renderNode.entityCollections._renderNodeIndex = i;
}
}
this.renderNode = null;
this._renderNodeIndex = -1;
this.events.dispatch(this.events.remove, this);
}
}
/**
* Gets entities.
* @public
* @returns {Array.<og.Entity>}
*/
getEntities() {
return [].concat(this._entities);
}
/**
* Safety entities loop.
* @public
* @param {function} callback - Entity callback.
*/
each(callback) {
var i = this._entities.length;
while (i--) {
var ei = this._entities[i];
ei && callback(ei);
}
}
/**
* Removes all entities from colection and clear handlers.
* @public
*/
clear() {
//TODO: Optimize by replace delete
//code to the clearEntity function.
this.billboardHandler.clear();
this.labelHandler.clear();
this.shapeHandler.clear();
this.polylineHandler.clear();
this.pointCloudHandler.clear();
var i = this._entities.length;
while (i--) {
var ei = this._entities[i];
if (this.renderNode && this.renderNode.renderer) {
this.renderNode.renderer.clearPickingColor(ei);
ei._pickingColor.clear();
}
this._clearEntity(ei);
}
this._entities.length = 0;
this._entities = [];
}
/**
* Clears entity recursevely.
* @private
* @param {og.Entity} entity - Entity to clear.
*/
_clearEntity(entity) {
entity._entityCollection = null;
entity._entityCollectionIndex = -1;
for (var i = 0; i < entity.childrenNodes.length; i++) {
this._clearEntity(entity.childrenNodes[i]);
}
}
};
const EVENT_NAMES = [
/**
* Triggered when entity has moved.
* @event og.EntityCollection#entitymove
*/
"entitymove",
/**
* Triggered when collection entities begin draw.
* @event og.EntityCollection#draw
*/
"draw",
/**
* Triggered after collection has drawn.
* @event og.EntityCollection#drawend
*/
"drawend",
/**
* Triggered when added to the render node.
* @event og.EntityCollection#add
*/
"add",
/**
* Triggered when removed from the render node.
* @event og.EntityCollection#remove
*/
"remove",
/**
* Triggered when new entity added to the collection.
* @event og.EntityCollection#entityadd
*/
"entityadd",
/**
* Triggered when entity removes from the collection.
* @event og.EntityCollection#entityremove
*/
"entityremove",
/**
* Triggered when visibility changes.
* @event og.EntityCollection#visibilitychange
*/
"visibilitychange",
/**
* Triggered when mouse moves over the entity.
* @event og.EntityCollection#mousemove
*/
"mousemove",
/**
* Triggered when mouse has entered over the entity.
* @event og.EntityCollection#mouseenter
*/
"mouseenter",
/**
* Triggered when mouse leaves the entity.
* @event og.EntityCollection#mouseleave
*/
"mouseleave",
/**
* Mouse left button clicked.
* @event og.EntityCollection#lclick
*/
"lclick",
/**
* Mouse right button clicked.
* @event og.EntityCollection#rclick
*/
"rclick",
/**
* Mouse right button clicked.
* @event og.EntityCollection#mclick
*/
"mclick",
/**
* Mouse left button double click.
* @event og.EntityCollection#ldblclick
*/
"ldblclick",
/**
* Mouse right button double click.
* @event og.EntityCollection#rdblclick
*/
"rdblclick",
/**
* Mouse middle button double click.
* @event og.EntityCollection#mdblclick
*/
"mdblclick",
/**
* Mouse left button up(stop pressing).
* @event og.EntityCollection#lup
*/
"lup",
/**
* Mouse right button up(stop pressing).
* @event og.EntityCollection#rup
*/
"rup",
/**
* Mouse middle button up(stop pressing).
* @event og.EntityCollection#mup
*/
"mup",
/**
* Mouse left button is just pressed down(start pressing).
* @event og.EntityCollection#ldown
*/
"ldown",
/**
* Mouse right button is just pressed down(start pressing).
* @event og.EntityCollection#rdown
*/
"rdown",
/**
* Mouse middle button is just pressed down(start pressing).
* @event og.EntityCollection#mdown
*/
"mdown",
/**
* Mouse left button is pressing.
* @event og.EntityCollection#lhold
*/
"lhold",
/**
* Mouse right button is pressing.
* @event og.EntityCollection#rhold
*/
"rhold",
/**
* Mouse middle button is pressing.
* @event og.EntityCollection#mhold
*/
"mhold",
/**
* Mouse wheel is rotated.
* @event og.EntityCollection#mousewheel
*/
"mousewheel",
/**
* Triggered when touch moves over the entity.
* @event og.EntityCollection#touchmove
*/
"touchmove",
/**
* Triggered when entity begins to touch.
* @event og.EntityCollection#touchstart
*/
"touchstart",
/**
* Triggered when entity ends touching.
* @event og.EntityCollection#touchend
*/
"touchend",
/**
* Triggered entity double touch.
* @event og.EntityCollection#doubletouch
*/
"doubletouch",
/**
* Triggered when touching leaves entity.
* @event og.EntityCollection#touchleave
*/
"touchleave",
/**
* Triggered when touch enters over the entity.
* @event og.EntityCollection#touchenter
*/
"touchenter"
];
export { EntityCollection };

View File

@ -1,317 +0,0 @@
/**
* @module og/entity/Geometry
*/
'use strict';
import * as utils from '../utils/shared.js';
import { Extent } from '../Extent.js';
import { Vec4 } from '../math/Vec4.js';
import { LonLat } from '../LonLat.js';
const GeometryType = {
POINT: 1,
LINESTRING: 2,
POLYGON: 3,
MULTIPOLYGON: 4,
MULTILINESTRING: 5
};
class Geometry {
constructor(options) {
this._id = Geometry._staticCounter++;
options = options || {};
options.style = options.style || {};
/**
* Entity instance that holds this geometry.
* @protected
* @type {og.Entity}
*/
this._entity = null;
this._handler = null;
this._handlerIndex = -1;
//Polygon
this._polyVerticesMerc = [];
this._polyVerticesLength = -1;
this._polyIndexesLength = -1;
this._polyVerticesHandlerIndex = -1;
this._polyIndexesHandlerIndex = -1;
//Line(Linestring and polygon's stroke(s)
this._lineVerticesMerc = [];
this._lineVerticesLength = -1;
this._lineOrdersLength = -1;
this._lineIndexesLength = -1;
this._lineColorsLength = -1;
this._lineThicknessLength = -1;
this._lineVerticesHandlerIndex = -1;
this._lineOrdersHandlerIndex = -1;
this._lineIndexesHandlerIndex = -1;
this._lineThicknessHandlerIndex = -1;
this._lineColorsHandlerIndex = -1;
this._type = options.type && Geometry.getType(options.type) || GeometryType.POINT;
this._coordinates = [];
this._extent = Geometry.getExtent({
'type': options.type || "Point",
'coordinates': options.coordinates || []
}, this._coordinates);
this._style = options.style || {};
this._style.fillColor = utils.createColorRGBA(options.style.fillColor, new Vec4(0.19, 0.62, 0.85, 0.4));
this._style.lineColor = utils.createColorRGBA(options.style.lineColor, new Vec4(0.19, 0.62, 0.85, 1));
this._style.strokeColor = utils.createColorRGBA(options.style.strokeColor, new Vec4(1, 1, 1, 0.95));
this._style.lineWidth = options.style.lineWidth || 3;
this._style.strokeWidth = options.style.strokeWidth || 0;
this._visibility = options.visibility || true;
//optimization flag for picking mask rendering pass
this._pickingReady = false;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static getType(typeStr) {
return GeometryType[typeStr.toUpperCase()];
}
/**
* Returns geometry feature extent.
@static
@param {Object} geometryObj - GeoJSON style geometry feature.
@param {Array} outoordinates - Geometry feature coordinates clone.
@returns {og.Extent}
*/
static getExtent(geometryObj, outCoordinates) {
var res = new Extent(new LonLat(180.0, 90.0), new LonLat(-180.0, -90.0));
var t = Geometry.getType(geometryObj.type);
if (t === GeometryType.POINT) {
var lon = res.coordinates[0],
lat = res.coordinates[1];
res.southWest.lon = lon;
res.southWest.lat = lat;
res.northEast.lon = lon;
res.northEast.lat = lat;
outCoordinates && (outCoordinates[0] = lon) && (outCoordinates[1] = lat);
} else if (t === GeometryType.LINESTRING) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var lon = c[i][0],
lat = c[i][1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i] = [lon, lat]);
}
} else if (t === GeometryType.POLYGON) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var ci = c[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < ci.length; j++) {
var cij = ci[j];
var lon = cij[0],
lat = cij[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j] = [lon, lat]);
}
}
} else if (t === GeometryType.MULTIPOLYGON) {
var p = geometryObj.coordinates;
for (var i = 0; i < p.length; i++) {
var pi = p[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < pi.length; j++) {
var pij = pi[j];
outCoordinates && (outCoordinates[i][j] = []);
for (var k = 0; k < pij.length; k++) {
var pijk = pij[k];
var lon = pijk[0],
lat = pijk[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j][k] = [lon, lat]);
}
}
}
} else if (t === GeometryType.MULTILINESTRING) {
var c = geometryObj.coordinates;
for (var i = 0; i < c.length; i++) {
var ci = c[i];
outCoordinates && (outCoordinates[i] = []);
for (var j = 0; j < ci.length; j++) {
var cij = ci[j];
var lon = cij[0],
lat = cij[1];
if (lon < res.southWest.lon) res.southWest.lon = lon;
if (lat < res.southWest.lat) res.southWest.lat = lat;
if (lon > res.northEast.lon) res.northEast.lon = lon;
if (lat > res.northEast.lat) res.northEast.lat = lat;
outCoordinates && (outCoordinates[i][j] = [lon, lat]);
}
}
} else {
res.southWest.lon = res.southWest.lat = res.northEast.lon = res.northEast.lat = 0.0;
outCoordinates && (outCoordinates[0] = lon) && (outCoordinates[1] = lat);
}
return res;
}
/**
*/
setGeometry(geoJson) {
var h = this._handler;
this.remove();
this._type = Geometry.getType(geoJson.type || "Point");
this._extent = Geometry.getExtent(geoJson, this._coordinates);
h.add(this);
return this;
}
setFillColor(r, g, b, a) {
var c = this._style.fillColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setPolyColorArr(this, c);
return this;
}
setFillColor4v(rgba) {
return this.setFillColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setStrokeColor(r, g, b, a) {
var c = this._style.strokeColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setStrokeColorArr(this, c);
return this;
}
setLineColor(r, g, b, a) {
var c = this._style.lineColor;
if (c.w === 0.0 && a !== 0.0 || c.w !== 0.0 && a === 0.0) {
this._pickingReady = false;
}
c.x = r;
c.y = g;
c.z = b;
c.w = a;
this._handler && this._handler.setLineColorArr(this, c);
return this;
}
setStrokeColor4v(rgba) {
return this.setStrokeColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setLineColor4v(rgba) {
return this.setLineColor(rgba.x, rgba.y, rgba.z, rgba.w);
}
setStrokeOpacity(opacity) {
var c = this._style.strokeColor;
c.w = opacity;
return this.setStrokeColor(c.x, c.y, c.z, opacity);
}
setLineOpacity(opacity) {
var c = this._style.lineColor;
c.w = opacity;
return this.setLineColor(c.x, c.y, c.z, opacity);
}
setStrokeWidth(width) {
this._style.strokeWidth = width;
this._pickingReady = false;
this._handler && this._handler.setLineStrokeArr(this, width);
return this;
}
bringToFront() {
this._handler && this._handler.bringToFront(this);
return this;
}
setLineWidth(width) {
this._style.lineWidth = width;
this._pickingReady = false;
this._handler && this._handler.setLineThicknessArr(this, width);
return this;
}
setFillOpacity(opacity) {
var c = this._style.fillColor;
if (c.w === 0.0 && opacity !== 0.0 || c.w !== 0.0 && opacity === 0.0) {
this._pickingReady = false;
}
c.w = opacity;
this._handler && this._handler.setPolyColorArr(this, c);
return this;
}
setVisibility(visibility) {
this._visibility = visibility;
this._handler && this._handler.setGeometryVisibility(this);
return this;
}
getVisibility() {
return this._visibility;
}
remove() {
this._handler && this._handler.remove(this);
}
etExtent() {
return this._extent.clone();
}
getType() {
return this._type;
}
};
export { Geometry, GeometryType };

View File

@ -1,747 +0,0 @@
/**
* @module og/entity/GeometryHandler
*/
'use strict';
import * as mercator from '../mercator.js';
import * as quadTree from '../quadTree/quadTree.js';
import { earcut, flatten } from '../utils/earcut.js';
import { GeometryType } from './Geometry.js';
const POLYVERTICES_BUFFER = 0;
const POLYINDEXES_BUFFER = 1;
const POLYCOLORS_BUFFER = 2;
const LINEVERTICES_BUFFER = 3;
const LINEINDEXES_BUFFER = 4;
const LINEORDERS_BUFFER = 5;
const LINECOLORS_BUFFER = 6;
const LINETHICKNESS_BUFFER = 7;
const LINESTROKES_BUFFER = 8;
const LINESTROKECOLORS_BUFFER = 9;
const POLYPICKINGCOLORS_BUFFER = 10;
const LINEPICKINGCOLORS_BUFFER = 11;
class GeometryHandler {
constructor(layer) {
this.__staticId = GeometryHandler._staticCounter++;
this._layer = layer;
this._handler = null;
this._geometries = [];
this._updatedGeometryArr = [];
this._updatedGeometry = {};
this._removeGeometryExtentArr = [];
this._removeGeometryExtents = {};
//Polygon arrays
this._polyVerticesMerc = [];
this._polyColors = [];
this._polyPickingColors = [];
this._polyIndexes = [];
//Line arrays
this._lineVerticesMerc = [];
this._lineOrders = [];
this._lineIndexes = [];
this._lineColors = [];
this._linePickingColors = [];
this._lineThickness = [];
this._lineStrokes = [];
this._lineStrokeColors = [];
//Buffers
this._polyVerticesBufferMerc = null;
this._polyColorsBuffer = null;
this._polyPickingColorsBuffer = null;
this._polyIndexesBuffer = null;
this._lineVerticesBufferMerc = null;
this._lineColorsBuffer = null;
this._linePickingColorsBuffer = null;
this._lineThicknessBuffer = null;
this._lineStrokesBuffer = null;
this._lineStrokeColorsBuffer = null;
this._lineOrdersBuffer = null;
this._lineIndexesBuffer = null;
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[POLYVERTICES_BUFFER] = this.createPolyVerticesBuffer;
this._buffersUpdateCallbacks[POLYINDEXES_BUFFER] = this.createPolyIndexesBuffer;
this._buffersUpdateCallbacks[POLYCOLORS_BUFFER] = this.createPolyColorsBuffer;
this._buffersUpdateCallbacks[LINEVERTICES_BUFFER] = this.createLineVerticesBuffer;
this._buffersUpdateCallbacks[LINEINDEXES_BUFFER] = this.createLineIndexesBuffer;
this._buffersUpdateCallbacks[LINEORDERS_BUFFER] = this.createLineOrdersBuffer;
this._buffersUpdateCallbacks[LINECOLORS_BUFFER] = this.createLineColorsBuffer;
this._buffersUpdateCallbacks[LINETHICKNESS_BUFFER] = this.createLineThicknessBuffer;
this._buffersUpdateCallbacks[LINESTROKES_BUFFER] = this.createLineStrokesBuffer;
this._buffersUpdateCallbacks[LINESTROKECOLORS_BUFFER] = this.createLineStrokeColorsBuffer;
this._buffersUpdateCallbacks[POLYPICKINGCOLORS_BUFFER] = this.createPolyPickingColorsBuffer;
this._buffersUpdateCallbacks[LINEPICKINGCOLORS_BUFFER] = this.createLinePickingColorsBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
static appendLineData(pathArr, isClosed, color, pickingColor, thickness, strokeColor, strokeSize,
outVertices, outOrders, outIndexes, outColors, outPickingColors, outThickness, outStrokeColors, outStrokes,
outVertices2) {
var index = 0;
if (outIndexes.length > 0) {
index = outIndexes[outIndexes.length - 5] + 9;
outIndexes.push(index, index);
} else {
outIndexes.push(0, 0);
}
var t = thickness,
c = [color.x, color.y, color.z, color.w],
s = strokeSize,
sc = [strokeColor.x, strokeColor.y, strokeColor.z, strokeColor.w],
p = [pickingColor.x, pickingColor.y, pickingColor.z, 1.0];
for (var j = 0; j < pathArr.length; j++) {
var path = pathArr[j];
var startIndex = index;
var last;
if (isClosed) {
last = path[path.length - 1];
} else {
var p0 = path[0],
p1 = path[1];
last = [p0[0] + p0[0] - p1[0], p0[1] + p0[1] - p1[1]];
}
outVertices.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
outVertices2.push(last[0], last[1], last[0], last[1], last[0], last[1], last[0], last[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
for (var i = 0; i < path.length; i++) {
var cur = path[i];
outVertices.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
outVertices2.push(cur[0], cur[1], cur[0], cur[1], cur[0], cur[1], cur[0], cur[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
outIndexes.push(index++, index++, index++, index++);
}
var first;
if (isClosed) {
first = path[0];
outIndexes.push(startIndex, startIndex + 1, startIndex + 1, startIndex + 1);
} else {
var p0 = path[path.length - 1],
p1 = path[path.length - 2];
first = [p0[0] + p0[0] - p1[0], p0[1] + p0[1] - p1[1]];
outIndexes.push(index - 1, index - 1, index - 1, index - 1);
}
outVertices.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
outVertices2.push(first[0], first[1], first[0], first[1], first[0], first[1], first[0], first[1]);
outOrders.push(1, -1, 2, -2);
outThickness.push(t, t, t, t);
outStrokes.push(s, s, s, s);
outColors.push(c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3], c[0], c[1], c[2], c[3]);
outStrokeColors.push(sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3], sc[0], sc[1], sc[2], sc[3]);
outPickingColors.push(p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3], p[0], p[1], p[2], p[3]);
if (j < pathArr.length - 1) {
index += 8;
outIndexes.push(index, index);
}
}
}
assignHandler(handler) {
this._handler = handler;
this.refresh();
}
/**
* @public
* @param {og.Geometry} geometry - Geometry object.
*/
add(geometry) {
//
// Triangulates polygon and sets geometry data.
if (geometry._handlerIndex === -1) {
geometry._handler = this;
geometry._handlerIndex = this._geometries.length;
this._geometries.push(geometry);
var pickingColor = geometry._entity._pickingColor.scaleTo(1 / 255);
geometry._polyVerticesMerc = [];
geometry._lineVerticesMerc = [];
if (geometry._type === GeometryType.POLYGON) {
var coordinates = geometry._coordinates;
var ci = [];
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[j].length; k++) {
ci[j][k] = [mercator.forward_lon(coordinates[j][k][0]), mercator.forward_lat(coordinates[j][k][1])];
}
}
var data = earcut.flatten(ci);
var indexes = earcut(data.vertices, data.holes, 2);
geometry._polyVerticesMerc = data.vertices;
geometry._polyVerticesHandlerIndex = this._polyVerticesMerc.length;
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
this._polyVerticesMerc.push.apply(this._polyVerticesMerc, data.vertices);
for (var i = 0; i < indexes.length; i++) {
this._polyIndexes.push(indexes[i] + geometry._polyVerticesHandlerIndex * 0.5);
}
var color = geometry._style.fillColor;
for (var i = 0; i < data.vertices.length * 0.5; i++) {
this._polyColors.push(color.x, color.y, color.z, color.w);
this._polyPickingColors.push(pickingColor.x, pickingColor.y, pickingColor.z, 1.0);
}
geometry._polyVerticesLength = data.vertices.length;
geometry._polyIndexesLength = indexes.length;
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData(ci, true,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.MULTIPOLYGON) {
var coordinates = geometry._coordinates;
var vertices = [],
indexes = [],
colors = [];
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
for (var i = 0; i < coordinates.length; i++) {
var cci = coordinates[i];
var ci = [];
for (var j = 0; j < cci.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[i][j].length; k++) {
ci[j][k] = [mercator.forward_lon(cci[j][k][0]), mercator.forward_lat(cci[j][k][1])];
}
}
var data = flatten(ci);
var dataIndexes = earcut(data.vertices, data.holes, 2);
for (var j = 0; j < dataIndexes.length; j++) {
indexes.push(dataIndexes[j] + vertices.length * 0.5);
}
vertices.push.apply(vertices, data.vertices);
GeometryHandler.appendLineData(ci, true,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
}
geometry._polyVerticesMerc = vertices;
geometry._polyVerticesHandlerIndex = this._polyVerticesMerc.length;
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
this._polyVerticesMerc.push.apply(this._polyVerticesMerc, vertices);
for (var i = 0; i < indexes.length; i++) {
this._polyIndexes.push(indexes[i] + geometry._polyVerticesHandlerIndex * 0.5);
}
var color = geometry._style.fillColor;
for (var i = 0; i < vertices.length * 0.5; i++) {
this._polyColors.push(color.x, color.y, color.z, color.w);
this._polyPickingColors.push(pickingColor.x, pickingColor.y, pickingColor.z, 1.0);
}
geometry._polyVerticesLength = vertices.length;
geometry._polyIndexesLength = indexes.length;
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.LINESTRING) {
var coordinates = geometry._coordinates;
var ci = new Array(coordinates.length);
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [mercator.forward_lon(coordinates[j][0]), mercator.forward_lat(coordinates[j][1])];
}
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData([ci], false,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
} else if (geometry._type === GeometryType.MULTILINESTRING) {
var coordinates = geometry._coordinates;
var ci = [];
for (var j = 0; j < coordinates.length; j++) {
ci[j] = [];
for (var k = 0; k < coordinates[j].length; k++) {
ci[j][k] = [mercator.forward_lon(coordinates[j][k][0]), mercator.forward_lat(coordinates[j][k][1])];
}
}
//Creates polygon stroke data
geometry._lineVerticesHandlerIndex = this._lineVerticesMerc.length;
geometry._lineOrdersHandlerIndex = this._lineOrders.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._lineColorsHandlerIndex = this._lineColors.length;
geometry._lineThicknessHandlerIndex = this._lineThickness.length;
GeometryHandler.appendLineData(ci, false,
geometry._style.lineColor, pickingColor, geometry._style.lineWidth,
geometry._style.strokeColor, geometry._style.strokeWidth,
this._lineVerticesMerc, this._lineOrders, this._lineIndexes, this._lineColors, this._linePickingColors,
this._lineThickness, this._lineStrokeColors, this._lineStrokes, geometry._lineVerticesMerc);
geometry._lineVerticesLength = this._lineVerticesMerc.length - geometry._lineVerticesHandlerIndex;
geometry._lineOrdersLength = this._lineOrders.length - geometry._lineOrdersHandlerIndex;
geometry._lineIndexesLength = this._lineIndexes.length - geometry._lineIndexesHandlerIndex;
geometry._lineColorsLength = this._lineColors.length - geometry._lineColorsHandlerIndex;
geometry._lineThicknessLength = this._lineThickness.length - geometry._lineThicknessHandlerIndex;
}
//Refresh visibility
this.setGeometryVisibility(geometry);
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
this.refresh();
}
}
remove(geometry) {
var index = geometry._handlerIndex;
if (index !== -1) {
this._geometries.splice(index, 1);
//polygon
//this._polyVerticesLonLat.splice(geometry._polyVerticesHandlerIndex, geometry._polyVerticesLength);
this._polyVerticesMerc.splice(geometry._polyVerticesHandlerIndex, geometry._polyVerticesLength);
this._polyColors.splice(geometry._polyVerticesHandlerIndex * 2, geometry._polyVerticesLength * 2);
this._polyPickingColors.splice(geometry._polyVerticesHandlerIndex * 2, geometry._polyVerticesLength * 2);
this._polyIndexes.splice(geometry._polyIndexesHandlerIndex, geometry._polyIndexesLength);
var di = geometry._polyVerticesLength * 0.5;
for (var i = geometry._polyIndexesHandlerIndex; i < this._polyIndexes.length; i++) {
this._polyIndexes[i] -= di;
}
//line
//this._lineVerticesLonLat.splice(geometry._lineVerticesHandlerIndex, geometry._lineVerticesLength);
this._lineVerticesMerc.splice(geometry._lineVerticesHandlerIndex, geometry._lineVerticesLength);
this._lineOrders.splice(geometry._lineOrdersHandlerIndex, geometry._lineOrdersLength);
this._lineColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._linePickingColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._lineStrokeColors.splice(geometry._lineColorsHandlerIndex, geometry._lineColorsLength);
this._lineThickness.splice(geometry._lineThicknessHandlerIndex, geometry._lineThicknessLength);
this._lineStrokes.splice(geometry._lineThicknessHandlerIndex, geometry._lineThicknessLength);
this._lineIndexes.splice(geometry._lineIndexesHandlerIndex, geometry._lineIndexesLength);
di = geometry._lineVerticesLength * 0.5;
for (var i = geometry._lineIndexesHandlerIndex; i < this._lineIndexes.length; i++) {
this._lineIndexes[i] -= di;
}
//reindex
var g = this._geometries;
for (i = index; i < g.length; i++) {
var gi = g[i];
gi._handlerIndex = i;
gi._polyVerticesHandlerIndex -= geometry._polyVerticesLength;
gi._polyIndexesHandlerIndex -= geometry._polyIndexesLength;
gi._lineVerticesHandlerIndex -= geometry._lineVerticesLength;
gi._lineOrdersHandlerIndex -= geometry._lineOrdersLength;
gi._lineColorsHandlerIndex -= geometry._lineColorsLength;
gi._lineThicknessHandlerIndex -= geometry._lineThicknessLength;
gi._lineIndexesHandlerIndex -= geometry._lineIndexesLength;
}
geometry._pickingReady = false;
geometry._handler = null;
geometry._handlerIndex = -1;
geometry._polyVerticesMerc = [];
geometry._polyVerticesLength = -1;
geometry._polyIndexesLength = -1;
geometry._polyVerticesHandlerIndex = -1;
geometry._polyIndexesHandlerIndex = -1;
geometry._lineVerticesMerc = [];
geometry._lineVerticesLength = -1;
geometry._lineOrdersLength = -1;
geometry._lineIndexesLength = -1;
geometry._lineColorsLength = -1;
geometry._lineThicknessLength = -1;
geometry._lineVerticesHandlerIndex = -1;
geometry._lineOrdersHandlerIndex = -1;
geometry._lineIndexesHandlerIndex = -1;
geometry._lineThicknessHandlerIndex = -1;
geometry._lineColorsHandlerIndex = -1;
!this._removeGeometryExtents[geometry._id] && this._removeGeometryExtentArr.push(geometry.getExtent());
this._removeGeometryExtents[geometry._id] = true;
this.refresh();
}
}
_refreshRecursevely(geometry, treeNode) {
var lid = this._layer._id;
for (var i = 0; i < treeNode.nodes.length; i++) {
var ni = treeNode.nodes[i];
if (geometry._extent.overlaps(ni.segment.getExtentLonLat())) {
this._refreshRecursevely(geometry, ni);
var m = ni.segment.materials[lid];
if (m && m.isReady) {
if (m.segment.node.getState() !== quadTree.RENDERING) {
m.layer.clearMaterial(m);
} else {
m.pickingReady = m.pickingReady && geometry._pickingReady;
m.isReady = false;
m._updateTexture = m.texture;
m._updatePickingMask = m.pickingMask;
}
geometry._pickingReady = true;
}
}
}
}
_refreshRecursevelyExt(extent, treeNode) {
var lid = this._layer._id;
for (var i = 0; i < treeNode.nodes.length; i++) {
var ni = treeNode.nodes[i];
if (extent.overlaps(ni.segment.getExtentLonLat())) {
this._refreshRecursevelyExt(extent, ni);
var m = ni.segment.materials[lid];
if (m && m.isReady) {
m.layer.clearMaterial(m);
// m.pickingReady = false;
// m.isReady = false;
// m._updateTexture = m.texture;
// m._updatePickingMask = m.pickingMask;
}
}
}
}
_refreshPlanetNode(treeNode) {
var i = 0;
var e = this._removeGeometryExtentArr;
for (i = 0; i < e.length; i++) {
this._refreshRecursevelyExt(e[i], treeNode);
}
var g = this._updatedGeometryArr;
for (i = 0; i < g.length; i++) {
this._refreshRecursevely(g[i], treeNode);
}
}
_updatePlanet() {
var p = this._layer._planet;
if (p) {
this._refreshPlanetNode(p._quadTree);
this._refreshPlanetNode(p._quadTreeNorth);
this._refreshPlanetNode(p._quadTreeSouth);
}
this._updatedGeometryArr.length = 0;
this._updatedGeometryArr = [];
this._updatedGeometry = {};
this._removeGeometryExtentArr.length = 0;
this._removeGeometryExtentArr = [];
this._removeGeometryExtents = {};
}
refresh() {
var i = this._changedBuffers.length;
while (i--) {
this._changedBuffers[i] = true;
}
}
update() {
if (this._handler) {
var needUpdate = false;
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
needUpdate = true;
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
needUpdate && this._updatePlanet();
}
}
setGeometryVisibility(geometry) {
var v = geometry._visibility ? 1.0 : 0.0;
var a = this._polyVerticesMerc;
var l = geometry._polyVerticesLength;
var ind = geometry._polyVerticesHandlerIndex;
for (var i = 0; i < l; i++) {
a[ind + i] = geometry._polyVerticesMerc[i] * v;
}
a = this._lineVerticesMerc;
l = geometry._lineVerticesLength;
ind = geometry._lineVerticesHandlerIndex;
for (i = 0; i < l; i++) {
a[ind + i] = geometry._lineVerticesMerc[i] * v;
}
this._changedBuffers[POLYVERTICES_BUFFER] = true;
this._changedBuffers[LINEVERTICES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setPolyColorArr(geometry, color) {
var index = geometry._polyVerticesHandlerIndex * 2, // ... / 2 * 4
size = index + geometry._polyVerticesLength * 2; // ... / 2 * 4
var a = this._polyColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[POLYCOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineStrokeColorArr(geometry, color) {
var index = geometry._lineColorsHandlerIndex,
size = index + geometry._lineColorsLength;
var a = this._lineStrokeColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[LINESTROKECOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineColorArr(geometry, color) {
var index = geometry._lineColorsHandlerIndex,
size = index + geometry._lineColorsLength;
var a = this._lineColors;
for (var i = index; i < size; i += 4) {
a[i] = color.x;
a[i + 1] = color.y;
a[i + 2] = color.z;
a[i + 3] = color.w;
}
this._changedBuffers[LINECOLORS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineStrokeArr(geometry, width) {
var index = geometry._lineStrokesHandlerIndex,
size = index + geometry._lineStrokesLength;
var a = this._lineStrokes;
for (var i = index; i < size; i++) {
a[i] = width;
}
this._changedBuffers[LINESTROKES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
setLineThicknessArr(geometry, width) {
var index = geometry._lineThicknessHandlerIndex,
size = index + geometry._lineThicknessLength;
var a = this._lineThickness;
for (var i = index; i < size; i++) {
a[i] = width;
}
this._changedBuffers[LINETHICKNESS_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
bringToFront(geometry) {
var polyIndexes = this._polyIndexes.splice(geometry._polyIndexesHandlerIndex, geometry._polyIndexesLength);
var lineIndexes = this._lineIndexes.splice(geometry._lineIndexesHandlerIndex, geometry._lineIndexesLength);
this._geometries.splice(geometry._handlerIndex, 1);
var g = this._geometries;
for (var i = geometry._handlerIndex; i < g.length; i++) {
var gi = g[i];
gi._handlerIndex = i;
gi._polyIndexesHandlerIndex -= geometry._polyIndexesLength;
gi._lineIndexesHandlerIndex -= geometry._lineIndexesLength;
}
geometry._polyIndexesHandlerIndex = this._polyIndexes.length;
geometry._lineIndexesHandlerIndex = this._lineIndexes.length;
geometry._handlerIndex = this._geometries.length;
this._geometries.push(geometry);
this._polyIndexes.push.apply(this._polyIndexes, polyIndexes);
this._lineIndexes.push.apply(this._lineIndexes, lineIndexes);
this._changedBuffers[POLYINDEXES_BUFFER] = true;
this._changedBuffers[LINEINDEXES_BUFFER] = true;
!this._updatedGeometry[geometry._id] && this._updatedGeometryArr.push(geometry);
this._updatedGeometry[geometry._id] = true;
}
createPolyVerticesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyVerticesBufferMerc);
this._polyVerticesBufferMerc = h.createArrayBuffer(new Float32Array(this._polyVerticesMerc), 2, this._polyVerticesMerc.length / 2);
}
createPolyIndexesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyIndexesBuffer);
this._polyIndexesBuffer = h.createElementArrayBuffer(new Uint32Array(this._polyIndexes), 1, this._polyIndexes.length);
}
createPolyColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyColorsBuffer);
this._polyColorsBuffer = h.createArrayBuffer(new Float32Array(this._polyColors), 4, this._polyColors.length / 4);
}
createPolyPickingColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._polyPickingColorsBuffer);
this._polyPickingColorsBuffer = h.createArrayBuffer(new Float32Array(this._polyPickingColors), 4, this._polyPickingColors.length / 4);
}
createLineVerticesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineVerticesBufferMerc);
this._lineVerticesBufferMerc = h.createArrayBuffer(new Float32Array(this._lineVerticesMerc), 2, this._lineVerticesMerc.length / 2);
}
createLineIndexesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineIndexesBuffer);
this._lineIndexesBuffer = h.createElementArrayBuffer(new Uint32Array(this._lineIndexes), 1, this._lineIndexes.length);
}
createLineOrdersBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineOrdersBuffer);
this._lineOrdersBuffer = h.createArrayBuffer(new Float32Array(this._lineOrders), 1, this._lineOrders.length / 2);
}
createLineColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineColorsBuffer);
this._lineColorsBuffer = h.createArrayBuffer(new Float32Array(this._lineColors), 4, this._lineColors.length / 4);
}
createLinePickingColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._linePickingColorsBuffer);
this._linePickingColorsBuffer = h.createArrayBuffer(new Float32Array(this._linePickingColors), 4, this._linePickingColors.length / 4);
}
createLineThicknessBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineThicknessBuffer);
this._lineThicknessBuffer = h.createArrayBuffer(new Float32Array(this._lineThickness), 1, this._lineThickness.length);
}
createLineStrokesBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineStrokesBuffer);
this._lineStrokesBuffer = h.createArrayBuffer(new Float32Array(this._lineStrokes), 1, this._lineStrokes.length);
}
createLineStrokeColorsBuffer() {
var h = this._handler;
h.gl.deleteBuffer(this._lineStrokeColorsBuffer);
this._lineStrokeColorsBuffer = h.createArrayBuffer(new Float32Array(this._lineStrokeColors), 4, this._lineStrokeColors.length / 4);
}
};
export { GeometryHandler };

View File

@ -1,372 +0,0 @@
/**
* @module og/entity/Label
*/
'use strict';
import * as utils from '../utils/shared.js';
import { BaseBillboard } from './BaseBillboard.js';
import { Vec4 } from '../math/Vec4.js';
const ALIGN = {
RIGHT: 0,
LEFT: 1,
CENTER: 2
};
/**
* Text align options.
* @readonly
* @enum {number}
*/
const STR2ALIGN = {
"left": ALIGN.LEFT,
"right": ALIGN.RIGHT,
"center": ALIGN.CENTER
};
/**
* Billboard text label.
* @class
* @extends {og.BaseBillboard}
* @param {Object} [options] - Label options:
* @param {og.math.Vector3|Array.<number>} [options.position] - Billboard spatial position.
* @param {number} [options.rotation] - Screen angle rotaion.
* @param {og.math.Vector4|string|Array.<number>} [options.color] - Billboard color.
* @param {og.math.Vector3|Array.<number>} [options.alignedAxis] - Billboard aligned vector.
* @param {og.math.Vector3|Array.<number>} [options.offset] - Billboard center screen offset.
* @param {boolean} [options.visibility] - Visibility.
* @param {string} [options.text] - Text string.
* @param {string} [options.face] - HTML5 font face.
* @param {number} [options.size] - Font size in pixels.
* @param {string} [options.style] - HTML5 font style. Example 'normal', 'italic'.
* @param {string} [options.weight] - HTML5 font weight. Example 'normal', 'bold'.
* @param {number} [options.outline] - Text outline size. 0 - no outline, 1 - maximum outline. Default 0.58.
* @param {og.math.Vector4|string|Array.<number>} [options.outlineColor] - Outline color.
* @param {og.Label.ALIGN} [options.align] - Text horizontal align: "left", "right" and "center".
*/
class Label extends BaseBillboard {
constructor(options) {
super(options);
options = options || {};
/**
* Label text string.
* @private
* @type {string}
*/
this._text = options.text;
/**
* HTML5 font face.
* @private
* @type {string}
*/
this._face = utils.defaultString(options.face, null);
/**
* Font size in pixels.
* @private
* @type {number}
*/
this._size = options.size || 33;
/**
* HTML5 font style. Example 'normal', 'italic'.
* @private
* @type {string}
*/
this._style = utils.defaultString(options.style, null);
/**
* HTML5 font weight style. Example 'normal', 'bold'.
* @private
* @type {string}
*/
this._weight = utils.defaultString(options.weight, null);
/**
* Label outline.
* @private
* @type {number}
*/
this._outline = options.outline != undefined ? options.outline : 0.5;
/**
* Label outline color.
* @private
* @type {og.math.Vector4}
*/
this._outlineColor = utils.createColorRGBA(options.outlineColor, new Vec4(0.0, 0.0, 0.0, 1.0));
/**
* Text horizontal align: "left", "right" and "center".
* @private
* @type {og.Label.ALIGN}
*/
this._align = options.align ? STR2ALIGN[options.align.trim().toLowerCase()] || ALIGN.RIGHT : ALIGN.RIGHT;
/**
* Label font atlas index.
* @private
* @type {number}
*/
this._fontIndex = 0;
/**
* Font atlas pointer.
* @private
* @type {og.utils.FontAtlas}
*/
this._fontAtlas = null;
}
/**
* Sets lablel text.
* @public
* @param {string} text - Text string.
* It can't be bigger than maximum labelHandler _maxLetters value.
*/
setText(text) {
this._text = text;
this._handler && this._handler.setText(this._handlerIndex, text, this._fontIndex, this._align);
}
/**
* Gets current text string.
* @public
* @returns {string}
*/
getText() {
return this._text;
}
/**
* Sets label text align. Could be center, left or right. Left is default.
* @public
* @param {og.Label.ALIGN} align - Text align.
*/
setAlign(align) {
this._align = STR2ALIGN[align.trim().toLowerCase()];
this._handler && this._handler.setText(this._handlerIndex, this._text, this._fontIndex, this._align);
};
/**
* Gets label text current alignment.
* @public
* @returns {og.Label.ALIGN}
*/
getAlign() {
return this._align;
}
/**
* Sets font face family.
* @public
* @param {string} face - Font face family.
*/
setFace(face) {
this._face = face.trim().toLowerCase();
this.update();
}
/**
* Gets current font face.
* @public
* @returns {string}
*/
getFace() {
return this._face;
}
/**
* Sets label font size in pixels.
* @public
* @param {number} size - Label size in pixels.
*/
setSize(size) {
this._size = size;
this._handler && this._handler.setSizeArr(this._handlerIndex, size);
}
/**
* Gets label size in pixels.
* @public
* @returns {number}
*/
getSize() {
return this._size;
}
/**
* Sets font HTML5 style. It's can be Italic or Normal values.
* @public
* @param {string} style - HTML5 font style.
*/
setStyle(style) {
this._style = style.trim().toLowerCase();
this.update();
}
/**
* Gets label font style.
* @public
* @returns {string}
*/
getStyle() {
return this._style;
}
/**
* Sets label font HTML5 weight style. It's can be bold or normal.
* @public
* @param {string} weight - HTML5 font weight style.
*/
setWeight(weight) {
this._weight = weight.trim().toLowerCase();
this.update();
}
/**
* Gets label font weight.
* @public
* @returns {string}
*/
getWeight() {
return this._wight;
}
/**
* Sets text outline border size. Where 0 - is no outline and 1 - is the maximum outline size.
* @public
* @param {number} outline - Text outline size.
*/
setOutline(outline) {
this._outline = outline;
this._handler && this._handler.setOutlineArr(this._handlerIndex, 1.0 - outline);
}
/**
* Gets text current outline size.
* @public
* @returns {number}
*/
getOutline() {
return this._outline;
}
/**
* Sets label opacity.
* @public
* @param {number} a - Label opacity.
*/
setOpacity(a) {
this._color.w = a;
this.setColor4v(this._color);
this._outlineColor.w = a;
this.setOutlineColor4v(this._outlineColor);
}
/**
* Sets text outline color.
* @public
* @param {number} r - Red.
* @param {number} g - Green.
* @param {number} b - Blue.
* @param {number} a - Alpha.
*/
setOutlineColor(r, g, b, a) {
this._outlineColor.x = r;
this._outlineColor.y = g;
this._outlineColor.z = b;
this._outlineColor.w = a;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, this._outlineColor);
}
/**
* Sets text outline color.
* @public
* @param {og.math.Vector4} rgba - Color vector.
*/
setOutlineColor4v(rgba) {
this._outlineColor.x = rgba.x;
this._outlineColor.y = rgba.y;
this._outlineColor.z = rgba.z;
this._outlineColor.w = rgba.w;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, rgba);
}
/**
* Sets text outline color HTML string.
* @public
* @param {string} color - HTML string color.
*/
setOutlineColorHTML(color) {
this.setOutlineColor4v(utils.htmlColorToRgba(color));
};
/**
* Gets outline color vector.
* @public
* @returns {og.math.Vector4}
*/
getOutlineColor() {
return this._outlineColor;
}
/**
* Sets outline opacity. Actually outline color alpha value.
* @public
* @param {number} opacity - Outline opacity.
*/
setOutlineOpacity(opacity) {
this._outlineColor.w = opacity;
this._handler && this._handler.setOutlineColorArr(this._handlerIndex, this._outlineColor);
}
/**
* Gets outline opacity value.
* @public
* @returns {number}
*/
getOutlineOpacity() {
return this._outlineColor.w;
}
/**
* Updates label parameters.
* @public
*/
update() {
if (this._fontAtlas) {
var fontIndex = this._fontAtlas.getFontIndex(this._face, this._style, this._weight);
if (fontIndex == undefined) {
this._fontAtlas.createFontAsync(this._face, this._style, this._weight, this._applyFontIndex.bind(this));
} else {
this._applyFontIndex(fontIndex);
}
}
}
_applyFontIndex(fontIndex) {
this._fontIndex = fontIndex;
if (this._handler) {
this._handler.setFontIndexArr(this._handlerIndex, this._fontIndex);
this._handler.setText(this._handlerIndex, this._text, this._fontIndex, this._align);
}
}
/**
* Assigns font atlas and update.
* @public
* @param {og.utils.FontAtlas} fontAtlas - Font atlas.
*/
assignFontAtlas(fontAtlas) {
!this._fontAtlas && (this._fontAtlas = fontAtlas);
this.update();
}
};
export { Label, ALIGN };

View File

@ -1,818 +0,0 @@
/**
* @module og/entity/LabelHandler
*/
'use strict';
import * as shaders from '../shaders/label.js';
import { ALIGN } from './Label.js';
import { BillboardHandler } from './BillboardHandler.js';
const FONTINDEX_BUFFER = 9;
const OUTLINE_BUFFER = 10;
const OUTLINECOLOR_BUFFER = 11;
/*
* og.LabelHandler
*
*
*/
class LabelHandler extends BillboardHandler {
constructor(entityCollection) {
super(entityCollection);
this._fontIndexBuffer = null;
this._noOutlineBuffer = null;
this._outlineBuffer = null;
this._outlineColorBuffer = null;
this._fontIndexArr = [];
this._noOutlineArr = [];
this._outlineArr = [];
this._outlineColorArr = [];
this._buffersUpdateCallbacks[FONTINDEX_BUFFER] = this.createFontIndexBuffer;
this._buffersUpdateCallbacks[OUTLINE_BUFFER] = this.createOutlineBuffer;
this._buffersUpdateCallbacks[OUTLINECOLOR_BUFFER] = this.createOutlineColorBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this._maxLetters = 25;
}
initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.label) {
var isSingleBuffer = !this._renderer.isMultiFramebufferCompatible();
this._renderer.handler.addShaderProgram(shaders.label(isSingleBuffer));
}
if (!this._renderer.handler.shaderPrograms.labelPicking) {
this._renderer.handler.addShaderProgram(shaders.labelPicking());
}
}
}
add(label) {
if (label._handlerIndex == -1) {
label._handler = this;
label._handlerIndex = this._billboards.length;
this._billboards.push(label);
this._addBillboardToArrays(label);
this.refresh();
this.assignFontAtlas(label);
}
}
assignFontAtlas(label) {
if (this._entityCollection && this._entityCollection.renderNode) {
label.assignFontAtlas(this._entityCollection.renderNode.fontAtlas);
}
}
clear() {
this._texCoordArr.length = 0;
this._vertexArr.length = 0;
this._positionArr.length = 0;
this._sizeArr.length = 0;
this._offsetArr.length = 0;
this._rgbaArr.length = 0;
this._rotationArr.length = 0;
this._alignedAxisArr.length = 0;
this._fontIndexArr.length = 0;
this._noOutlineArr.length = 0;
this._outlineArr.length = 0;
this._outlineColorArr.length = 0;
this._texCoordArr = [];
this._vertexArr = [];
this._positionArr = [];
this._sizeArr = [];
this._offsetArr = [];
this._rgbaArr = [];
this._rotationArr = [];
this._alignedAxisArr = [];
this._fontIndexArr = [];
this._noOutlineArr = [];
this._outlineArr = [];
this._outlineColorArr = [];
this._removeBillboards();
this._deleteBuffers();
this.refresh();
}
_deleteBuffers() {
var gl = this._renderer.handler.gl;
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._fontIndexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._outlineBuffer);
gl.deleteBuffer(this._noOutlineBuffer);
gl.deleteBuffer(this._outlineColorBuffer);
gl.deleteBuffer(this._positionBuffer);
gl.deleteBuffer(this._sizeBuffer);
gl.deleteBuffer(this._offsetBuffer);
gl.deleteBuffer(this._rgbaBuffer);
gl.deleteBuffer(this._rotationBuffer);
gl.deleteBuffer(this._vertexBuffer);
gl.deleteBuffer(this._texCoordBuffer);
gl.deleteBuffer(this._alignedAxisBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
this._sizeBuffer = null;
this._fontIndexBuffer = null;
this._texCoordBuffer = null;
this._outlineBuffer = null;
this._outlineColorBuffer = null;
this._positionBuffer = null;
this._sizeBuffer = null;
this._offsetBuffer = null;
this._rgbaBuffer = null;
this._rotationBuffer = null;
this._vertexBuffer = null;
this._texCoordBuffer = null;
this._alignedAxisBuffer = null;
this._pickingColorBuffer = null;
}
_addBillboardToArrays(label) {
for (var i = 0; i < this._maxLetters; i++) {
if (label._visibility) {
BillboardHandler.concArr(this._vertexArr, [-0.5, 0.5, -0.5, -0.5, 0.5, -0.5, 0.5, -0.5, 0.5, 0.5, -0.5, 0.5]);
} else {
BillboardHandler.concArr(this._vertexArr, [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]);
}
BillboardHandler.concArr(this._texCoordArr, [0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0, 0, 0, -1, 0]);
var x = label._position.x, y = label._position.y, z = label._position.z, w = label._scale;
BillboardHandler.concArr(this._positionArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._size;
BillboardHandler.concArr(this._sizeArr, [x, x, x, x, x, x]);
x = label._offset.x; y = label._offset.y; z = label._offset.z - 0.05;
BillboardHandler.concArr(this._offsetArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = label._color.x; y = label._color.y; z = label._color.z; w = label._color.w;
BillboardHandler.concArr(this._rgbaArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._rotation;
BillboardHandler.concArr(this._rotationArr, [x, x, x, x, x, x]);
x = label._alignedAxis.x, y = label._alignedAxis.y, z = label._alignedAxis.z;
BillboardHandler.concArr(this._alignedAxisArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
x = label._fontIndex;
BillboardHandler.concArr(this._fontIndexArr, [0, 0, 0, 0, 0, 0]);
x = 1.0 - label._outline, y = 0.0;
BillboardHandler.concArr(this._outlineArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = 0.75, y = 0.7;
BillboardHandler.concArr(this._noOutlineArr, [x, y, x, y, x, y, x, y, x, y, x, y]);
x = label._outlineColor.x; y = label._outlineColor.y; z = label._outlineColor.z; w = label._outlineColor.w;
BillboardHandler.concArr(this._outlineColorArr, [x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w, x, y, z, w]);
x = label._entity._pickingColor.x / 255, y = label._entity._pickingColor.y / 255, z = label._entity._pickingColor.z / 255;
BillboardHandler.concArr(this._pickingColorArr, [x, y, z, x, y, z, x, y, z, x, y, z, x, y, z, x, y, z]);
}
};
_displayPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.label.activate();
var sh = h.shaderPrograms.label._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
var ec = this._entityCollection;
var rn = ec.renderNode;
gl.uniform1iv(shu.u_fontTextureArr._pName, rn.fontAtlas.samplerArr);
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, ec.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, ec._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [rn._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._fontIndexBuffer);
gl.vertexAttribPointer(sha.a_fontIndex._pName, this._fontIndexBuffer.itemSize, gl.FLOAT, false, 0, 0);
//buffer
gl.bindBuffer(gl.ARRAY_BUFFER, this._outlineColorBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._outlineColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._outlineBuffer);
gl.vertexAttribPointer(sha.a_bufferAA._pName, this._outlineBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform1f(shu.uZ._pName, -2.0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
//nobuffer
gl.bindBuffer(gl.ARRAY_BUFFER, this._rgbaBuffer);
gl.vertexAttribPointer(sha.a_rgba._pName, this._rgbaBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._noOutlineBuffer);
gl.vertexAttribPointer(sha.a_bufferAA._pName, this._noOutlineBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform1f(shu.uZ._pName, -10.0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_pickingPASS() {
var r = this._renderer;
var h = r.handler;
h.shaderPrograms.labelPicking.activate();
var sh = h.shaderPrograms.labelPicking._program;
var sha = sh.attributes,
shu = sh.uniforms;
var gl = h.gl;
gl.uniformMatrix4fv(shu.viewMatrix._pName, false, r.activeCamera._viewMatrix._m);
gl.uniformMatrix4fv(shu.projectionMatrix._pName, false, r.activeCamera._projectionMatrix._m);
gl.uniform3fv(shu.uCamPos._pName, r.activeCamera.eye.toVec());
gl.uniform3fv(shu.uScaleByDistance._pName, this._entityCollection.scaleByDistance);
gl.uniform1f(shu.uOpacity._pName, this._entityCollection._animatedOpacity);
gl.uniform2fv(shu.uFloatParams._pName, [this._entityCollection.renderNode._planetRadius2 || 0, r.activeCamera._tanViewAngle_hradOneByHeight]);
gl.bindBuffer(gl.ARRAY_BUFFER, this._vertexBuffer);
gl.vertexAttribPointer(sha.a_vertices._pName, this._vertexBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._texCoordBuffer);
gl.vertexAttribPointer(sha.a_texCoord._pName, this._texCoordBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._positionBuffer);
gl.vertexAttribPointer(sha.a_positions._pName, this._positionBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._sizeBuffer);
gl.vertexAttribPointer(sha.a_size._pName, this._sizeBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._offsetBuffer);
gl.vertexAttribPointer(sha.a_offset._pName, this._offsetBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._rotationBuffer);
gl.vertexAttribPointer(sha.a_rotation._pName, this._rotationBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._alignedAxisBuffer);
gl.vertexAttribPointer(sha.a_alignedAxis._pName, this._alignedAxisBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.a_pickingColor._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.TRIANGLES, 0, this._vertexBuffer.numItems);
}
_removeBillboard(label) {
var li = label._handlerIndex;
this._billboards.splice(li, 1);
var ml = 24 * this._maxLetters;
var i = li * ml;
this._rgbaArr.splice(i, ml);
this._outlineColorArr.splice(i, ml);
this._texCoordArr.splice(i, ml);
this._positionArr.splice(i, ml);
ml = 18 * this._maxLetters;
i = li * ml;
this._offsetArr.splice(i, ml);
this._alignedAxisArr.splice(i, ml);
this._pickingColorArr.splice(i, ml);
ml = 12 * this._maxLetters;
i = li * ml;
this._vertexArr.splice(i, ml);
this._outlineArr.splice(i, ml);
this._noOutlineArr.splice(i, ml);
ml = 6 * this._maxLetters;
i = li * ml;
this._sizeArr.splice(i, ml);
this._rotationArr.splice(i, ml);
this._fontIndexArr.splice(i, ml);
this.reindexBillbordsArray(li);
this.refresh();
label._handlerIndex = -1;
label._handler = null;
//label._fontIndex = 0;
//label._fontAtlas = null;
};
setText(index, text, fontIndex, align) {
var fa = this._entityCollection.renderNode.fontAtlas.atlasesArr[fontIndex];
if (!fa) return;
var i = index * 24 * this._maxLetters;
var a = this._texCoordArr;
var c = 0;
var j = i + c * 24;
var n = fa.nodes[text[c]];
var f = n ? n.emptySize : 0.0;
var offset = f;
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
var n = fa.nodes[text[c]] || fa.nodes[" "];
var tc = n.texCoords;
a[j] = tc[0];
a[j + 1] = tc[1];
a[j + 2] = offset;
a[j + 3] = 0.0;
a[j + 4] = tc[2];
a[j + 5] = tc[3];
a[j + 6] = offset;
a[j + 7] = 0.0;
a[j + 8] = tc[4];
a[j + 9] = tc[5];
a[j + 10] = offset;
a[j + 11] = 0.0;
a[j + 12] = tc[6];
a[j + 13] = tc[7];
a[j + 14] = offset;
a[j + 15] = 0.0;
a[j + 16] = tc[8];
a[j + 17] = tc[9];
a[j + 18] = offset;
a[j + 19] = 0.0;
a[j + 20] = tc[10];
a[j + 21] = tc[11];
a[j + 22] = offset;
a[j + 23] = 0.0;
offset += n.emptySize;
}
//49/512 - font atlas left border letter offset
if (align == ALIGN.CENTER) {
offset = (f + 49 / 512 - offset) * 0.5;
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
a[j + 3] = offset;
a[j + 7] = offset;
a[j + 11] = offset;
a[j + 15] = offset;
a[j + 19] = offset;
a[j + 23] = offset;
}
} else if (align == ALIGN.LEFT) {
offset = (f + 49 / 512 - offset);
for (c = 0; c < text.length; c++) {
var j = i + c * 24;
a[j + 3] = offset;
a[j + 7] = offset;
a[j + 11] = offset;
a[j + 15] = offset;
a[j + 19] = offset;
a[j + 23] = offset;
}
}
for (var c = c; c < this._maxLetters; c++) {
var j = i + c * 24;
a[j + 2] = -1.0;
a[j + 6] = -1.0;
a[j + 10] = -1.0;
a[j + 14] = -1.0;
a[j + 18] = -1.0;
a[j + 17] = -1.0;
}
this._changedBuffers[TEXCOORD_BUFFER] = true;
}
setPositionArr(index, position) {
var i = index * 24 * this._maxLetters;
var a = this._positionArr, x = position.x, y = position.y, z = position.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
}
this._changedBuffers[POSITION_BUFFER] = true;
}
setScaleArr(index, scale) {
var i = index * 24 * this._maxLetters;
var a = this._positionArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j + 3] = scale;
a[j + 7] = scale;
a[j + 11] = scale;
a[j + 15] = scale;
a[j + 19] = scale;
a[j + 23] = scale;
}
this._changedBuffers[POSITION_BUFFER] = true;
}
setPickingColorArr(index, color) {
var i = index * 18 * this._maxLetters;
var a = this._pickingColorArr, x = color.x / 255, y = color.y / 255, z = color.z / 255;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[PICKINGCOLOR_BUFFER] = true;
}
setSizeArr(index, size) {
var i = index * 6 * this._maxLetters;
var a = this._sizeArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = size;
a[j + 1] = size;
a[j + 2] = size;
a[j + 3] = size;
a[j + 4] = size;
a[j + 5] = size;
}
this._changedBuffers[SIZE_BUFFER] = true;
}
setOffsetArr(index, offset) {
var i = index * 18 * this._maxLetters;
var a = this._offsetArr, x = offset.x, y = offset.y, z = offset.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[OFFSET_BUFFER] = true;
}
setRgbaArr(index, rgba) {
var i = index * 24 * this._maxLetters;
var a = this._rgbaArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = w;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 7] = w;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 11] = w;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = w;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 19] = w;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
a[j + 23] = w;
}
this._changedBuffers[RGBA_BUFFER] = true;
}
setOutlineColorArr(index, rgba) {
var i = index * 24 * this._maxLetters;
var a = this._outlineColorArr, x = rgba.x, y = rgba.y, z = rgba.z, w = rgba.w;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 24;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = w;
a[j + 4] = x;
a[j + 5] = y;
a[j + 6] = z;
a[j + 7] = w;
a[j + 8] = x;
a[j + 9] = y;
a[j + 10] = z;
a[j + 11] = w;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = w;
a[j + 16] = x;
a[j + 17] = y;
a[j + 18] = z;
a[j + 19] = w;
a[j + 20] = x;
a[j + 21] = y;
a[j + 22] = z;
a[j + 23] = w;
}
this._changedBuffers[OUTLINECOLOR_BUFFER] = true;
}
setOutlineArr(index, outline) {
var i = index * 12 * this._maxLetters;
var a = this._outlineArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 12;
a[j] = outline;
a[j + 2] = outline;
a[j + 4] = outline;
a[j + 6] = outline;
a[j + 8] = outline;
a[j + 10] = outline;
}
this._changedBuffers[OUTLINE_BUFFER] = true;
}
setRotationArr(index, rotation) {
var i = index * 6 * this._maxLetters;
var a = this._rotationArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = rotation;
a[j + 1] = rotation;
a[j + 2] = rotation;
a[j + 3] = rotation;
a[j + 4] = rotation;
a[j + 5] = rotation;
}
this._changedBuffers[ROTATION_BUFFER] = true
}
setVertexArr(index, vertexArr) {
var i = index * 12 * this._maxLetters;
var a = this._vertexArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 12;
a[j] = vertexArr[0];
a[j + 1] = vertexArr[1];
a[j + 2] = vertexArr[2];
a[j + 3] = vertexArr[3];
a[j + 4] = vertexArr[4];
a[j + 5] = vertexArr[5];
a[j + 6] = vertexArr[6];
a[j + 7] = vertexArr[7];
a[j + 8] = vertexArr[8];
a[j + 9] = vertexArr[9];
a[j + 10] = vertexArr[10];
a[j + 11] = vertexArr[11];
}
this._changedBuffers[VERTEX_BUFFER] = true;
}
setAlignedAxisArr(index, alignedAxis) {
var i = index * 18 * this._maxLetters;
var a = this._alignedAxisArr, x = alignedAxis.x, y = alignedAxis.y, z = alignedAxis.z;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 18;
a[j] = x;
a[j + 1] = y;
a[j + 2] = z;
a[j + 3] = x;
a[j + 4] = y;
a[j + 5] = z;
a[j + 6] = x;
a[j + 7] = y;
a[j + 8] = z;
a[j + 9] = x;
a[j + 10] = y;
a[j + 11] = z;
a[j + 12] = x;
a[j + 13] = y;
a[j + 14] = z;
a[j + 15] = x;
a[j + 16] = y;
a[j + 17] = z;
}
this._changedBuffers[ALIGNEDAXIS_BUFFER] = true;
}
setFontIndexArr(index, fontIndex) {
var i = index * 6 * this._maxLetters;
var a = this._fontIndexArr;
for (var q = 0; q < this._maxLetters; q++) {
var j = i + q * 6;
a[j] = fontIndex;
a[j + 1] = fontIndex;
a[j + 2] = fontIndex;
a[j + 3] = fontIndex;
a[j + 4] = fontIndex;
a[j + 5] = fontIndex;
}
this._changedBuffers[FONTINDEX_BUFFER] = true;
}
createSizeBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._sizeBuffer);
this._sizeBuffer = h.createArrayBuffer(new Float32Array(this._sizeArr), 1, this._sizeArr.length);
}
createFontIndexBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._fontIndexBuffer);
this._fontIndexBuffer = h.createArrayBuffer(new Float32Array(this._fontIndexArr), 1, this._fontIndexArr.length);
}
createTexCoordBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._texCoordBuffer);
this._texCoordBuffer = h.createArrayBuffer(new Float32Array(this._texCoordArr), 4, this._texCoordArr.length / 4);
}
createOutlineBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._outlineBuffer);
this._outlineBuffer = h.createArrayBuffer(new Float32Array(this._outlineArr), 2, this._outlineArr.length / 2);
h.gl.deleteBuffer(this._noOutlineBuffer);
this._noOutlineBuffer = h.createArrayBuffer(new Float32Array(this._noOutlineArr), 2, this._noOutlineArr.length / 2);
}
createOutlineColorBuffer() {
var h = this._renderer.handler;
h.gl.deleteBuffer(this._outlineColorBuffer);
this._outlineColorBuffer = h.createArrayBuffer(new Float32Array(this._outlineColorArr), 4, this._outlineColorArr.length / 4);
}
setMaxLetters(c) {
this._maxLetters = c;
//...
}
refreshTexCoordsArr() {
//it is empty
return null;
}
};
export { LabelHandler };

View File

@ -1,461 +0,0 @@
/**
* @module og/entity/PointCloud
*/
'use strict';
import { Vec3 } from '../math/Vec3.js';
import { Vec4 } from '../math/Vec4.js';
const COORDINATES_BUFFER = 0;
const COLOR_BUFFER = 1;
const PICKING_COLOR_BUFFER = 2;
/**
* PointCloud object.
* @class
* @param {*} [options] - Point cloud options:
* @param {Array.<Array.<number,number,number,number,number,number,number,*>>} [options.points] - Points cartesian coordinates array,
* where first three is cartesian coordinates, next fourth is a RGBA color, and last is an point properties.
* @param {number} [options.pointSize] - Point screen size in pixels.
* @param {number} [options.pickingDistance] - Point border picking size in screen pixels.
* @parar {boolean} [options.visibility] - Point cloud visibility.
* @example <caption>Creates point cloud with two ten pixel size points</caption>
* new og.Entity({
* pointCloud: {
* pointSize: 10,
* points: [
* [0, 0, 0, 255, 255, 255, 255, { 'name': 'White point' }],
* [100, 100, 0, 255, 0, 0, 255, { 'name': 'Red point' }]
* ]
* }
* });
*/
class PointCloud {
constructor(options) {
options = options || {};
/**
* Object unic identifier.
* @public
* @readonly
* @type {number}
*/
this.id = PointCloud._staticCounter++;
/**
* Cloud visibility.
* @public
* @type {boolean}
*/
this.visibility = (options.visibility != undefined ? options.visibility : true);
/**
* Point screen size in pixels.
* @public
* @type {number}
*/
this.pointSize = options.pointSize || 3;
/**
* Point picking border size in pixels.
* @public
* @type {number}
*/
this.pickingDistance = options.pickingDistance || 0;
/**
* Parent collection render node.
* @private
* @type {og.scene.RenderNode}
*/
this._renderNode = null;
/**
* Entity instance that holds this point cloud.
* @private
* @type {og.Entity}
*/
this._entity = null;
/**
* Points properties.
* @private
* @type {Array.<*>}
*/
this._points = [];
/**
* Coordinates array.
* @private
* @type {Array.<number>}
*/
this._coordinatesData = [];
/**
* Color array.
* @private
* @type {Array.<number>}
*/
this._colorData = [];
/**
* Picking color array.
* @private
* @type {Array.<number>}
*/
this._pickingColorData = [];
this._coordinatesBuffer = null;
this._colorBuffer = null;
this._pickingColorBuffer = null;
/**
* Handler that stores and renders this object.
* @private
* @type {og.PointCloudHandler}
*/
this._handler = null;
this._handlerIndex = -1;
this._buffersUpdateCallbacks = [];
this._buffersUpdateCallbacks[COORDINATES_BUFFER] = this._createCoordinatesBuffer;
this._buffersUpdateCallbacks[COLOR_BUFFER] = this._createColorBuffer;
this._buffersUpdateCallbacks[PICKING_COLOR_BUFFER] = this._createPickingColorBuffer;
this._changedBuffers = new Array(this._buffersUpdateCallbacks.length);
this.setPoints(options.points);
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
/**
* Clears point cloud data
* @public
*/
clear() {
this._points.length = 0;
this._points = [];
this._coordinatesData.length = 0;
this._coordinatesData = [];
this._colorData.length = 0;
this._colorData = [];
this._pickingColorData.length = 0;
this._pickingColorData = [];
this._deleteBuffers();
}
/**
* Set point cloud opacity.
* @public
* @param {number} opacity - Cloud opacity.
*/
setOpacity(opacity) {
this.opacity = opacity;
}
/**
* Sets cloud visibility.
* @public
* @param {number} visibility - Visibility flag.
*/
setVisibility(visibility) {
this.visibility = visibility;
}
/**
* @return {boolean} Point cloud visibily.
*/
getVisibility() {
return this.visibility;
}
/**
* Assign rendering scene node.
* @public
* @param {og.scene.RenderNode} renderNode - Assigned render node.
*/
setRenderNode(renderNode) {
this._renderNode = renderNode;
this._setPickingColors();
}
/**
* Removes from entity.
* @public
*/
remove() {
this._entity = null;
this._handler && this._handler.remove(this);
}
/**
* Adds points to render.
* @public
* @param {Array.<Array<number,number,number,number,number,number,number,*>>} points - Point cloud array.
* @example
* var points = [[0, 0, 0, 255, 255, 255, 255, { 'name': 'White point' }], [100, 100, 0, 255, 0, 0, 255, { 'name': 'Red point' }]];
*/
setPoints(points) {
this.clear();
for (var i = 0; i < points.length; i++) {
var pi = points[i];
var pos = new Vec3(pi[0], pi[1], pi[2]),
col = new Vec4(pi[3], pi[4], pi[5], (pi[6] == undefined ? 255.0 : pi[6]));
this._coordinatesData.push(pos.x, pos.y, pos.z);
this._colorData.push(col.x / 255.0, col.y / 255.0, col.z / 255.0, col.w / 255.0);
var p = {
'_pickingColor': new Vec3(),
'_entityCollection': this._entity && this._entity._entityCollection,
'index': i,
'position': pos,
'color': col,
'pointCloud': this,
'properties': pi[7] || {}
};
this._points.push(p);
if (this._renderNode) {
this._renderNode.renderer.assignPickingColor(p);
this._pickingColorData.push(p._pickingColor.x / 255.0, p._pickingColor.y / 255.0, p._pickingColor.z / 255.0, 1.0);
}
}
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
setPointPosition(index, x, y, z) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
}
/**
* @todo
*/
setPointColor(index, r, g, b, a) {
//...
this._changedBuffers[COLOR_BUFFER] = true;
}
/**
* @todo
*/
addPoints(points) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
addPoint(index, point) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* Returns specific point by index.
* @public
* @param {number} index - Point index.
* @return {*} Specific point
*/
getPoint(index) {
return this._points[index];
}
/**
* @todo
*/
removePoint(index) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* @todo
*/
insertPoint(index, point) {
//...
this._changedBuffers[COORDINATES_BUFFER] = true;
this._changedBuffers[COLOR_BUFFER] = true;
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
/**
* Each point iterator.
* @public
* @param {callback} callback
*/
each(callback) {
var i = this._points.length;
while (i--) {
callback && callback(this._points[i]);
}
}
draw() {
if (this.visibility && this._coordinatesData.length) {
this._update();
var rn = this._renderNode;
var r = rn.renderer;
var sh = r.handler.shaderPrograms.pointCloud;
var p = sh._program;
var gl = r.handler.gl,
sha = p.attributes,
shu = p.uniforms;
sh.activate();
gl.uniformMatrix4fv(shu.projectionViewMatrix._pName, false, r.activeCamera._projectionViewMatrix._m);
gl.uniform1f(shu.opacity._pName, this._handler._entityCollection._animatedOpacity);
gl.uniform1f(shu.pointSize._pName, this.pointSize);
gl.bindBuffer(gl.ARRAY_BUFFER, this._coordinatesBuffer);
gl.vertexAttribPointer(sha.coordinates._pName, this._coordinatesBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._colorBuffer);
gl.vertexAttribPointer(sha.colors._pName, this._colorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, this._coordinatesBuffer.numItems);
}
}
drawPicking() {
if (this.visibility && this._coordinatesData.length) {
var rn = this._renderNode;
var r = rn.renderer;
var sh = r.handler.shaderPrograms.pointCloud;
var p = sh._program;
var gl = r.handler.gl,
sha = p.attributes,
shu = p.uniforms;
sh.activate();
gl.uniformMatrix4fv(shu.projectionViewMatrix._pName, false, r.activeCamera._projectionViewMatrix._m);
gl.uniform1f(shu.opacity._pName, this._handler._entityCollection._animatedOpacity);
gl.uniform1f(shu.pointSize._pName, this.pointSize + this.pickingDistance);
gl.bindBuffer(gl.ARRAY_BUFFER, this._coordinatesBuffer);
gl.vertexAttribPointer(sha.coordinates._pName, this._coordinatesBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._pickingColorBuffer);
gl.vertexAttribPointer(sha.colors._pName, this._pickingColorBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.drawArrays(gl.POINTS, 0, this._coordinatesBuffer.numItems);
}
}
/**
* Update gl buffers.
* @private
*/
_update() {
if (this._renderNode) {
var i = this._changedBuffers.length;
while (i--) {
if (this._changedBuffers[i]) {
this._buffersUpdateCallbacks[i].call(this);
this._changedBuffers[i] = false;
}
}
}
}
/**
* Delete buffers
* @private
*/
_deleteBuffers() {
if (this._renderNode) {
var r = this._renderNode.renderer,
gl = r.handler.gl;
gl.deleteBuffer(this._coordinatesBuffer);
gl.deleteBuffer(this._colorBuffer);
gl.deleteBuffer(this._pickingColorBuffer);
}
this._coordinatesBuffer = null;
this._colorBuffer = null;
this._pickingColorBuffer = null;
}
_createCoordinatesBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._coordinatesBuffer);
this._coordinatesBuffer = h.createArrayBuffer(new Float32Array(this._coordinatesData), 3, (this._coordinatesData.length) / 3);
}
_createColorBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._colorBuffer);
this._colorBuffer = h.createArrayBuffer(new Float32Array(this._colorData), 4, (this._colorData.length) / 4);
}
_createPickingColorBuffer() {
var h = this._renderNode.renderer.handler;
h.gl.deleteBuffer(this._pickingColorBuffer);
this._pickingColorBuffer = h.createArrayBuffer(new Float32Array(this._pickingColorData), 4, (this._pickingColorData.length) / 4);
}
_setPickingColors() {
if (this._renderNode) {
for (var i = 0; i < this._points.length; i++) {
var p = this._points[i];
p._entity = this._entity;
p._entityCollection = this._entity._entityCollection;
this._renderNode.renderer.assignPickingColor(p);
this._pickingColorData.push(p._pickingColor.x / 255.0, p._pickingColor.y / 255.0, p._pickingColor.z / 255.0, 1.0);
}
this._changedBuffers[PICKING_COLOR_BUFFER] = true;
}
}
};
export { PointCloud };

View File

@ -1,126 +0,0 @@
/**
* @module og/entity/PointCloudHandler
*/
'use strict';
import * as shaders from '../shaders/pointCloud.js';
class PointCloudHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
/**
* Parent collection
* @private
* @type {og.EntityCollection}
*/
this._entityCollection = entityCollection;
/**
* Renderer
* @private
* @type {og.Renderer}
*/
this._renderer = null;
/**
* Point cloud array
* @private
* @type {Array.<og.PointCloud>}
*/
this._pointClouds = [];
this.__staticId = PointCloudHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.pointCloud) {
this._renderer.handler.addShaderProgram(shaders.pointCloud());
}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._pointClouds.length; i++) {
this._pointClouds[i].setRenderNode(renderNode);
}
}
add(pointCloud) {
if (pointCloud._handlerIndex == -1) {
pointCloud._handler = this;
pointCloud._handlerIndex = this._pointClouds.length;
this._pointClouds.push(pointCloud);
this._entityCollection && this._entityCollection.renderNode &&
pointCloud.setRenderNode(this._entityCollection.renderNode);
}
}
remove(pointCloud) {
var index = pointCloud._handlerIndex;
if (index !== -1) {
pointCloud._deleteBuffers();
pointCloud._handlerIndex = -1;
pointCloud._handler = null;
this._pointClouds.splice(index, 1);
this.reindexPointCloudArray(index);
}
}
reindexPointCloudArray(startIndex) {
var pc = this._pointClouds;
for (var i = startIndex; i < pc.length; i++) {
pc[i]._handlerIndex = i;
}
}
draw() {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i].draw();
}
}
drawPicking() {
if (this.pickingEnabled) {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i].drawPicking();
}
}
}
clear() {
var i = this._pointClouds.length;
while (i--) {
this._pointClouds[i]._deleteBuffers();
this._pointClouds[i]._handler = null;
this._pointClouds[i]._handlerIndex = -1;
}
this._pointClouds.length = 0;
this._pointClouds = [];
}
};
export { PointCloudHandler };

File diff suppressed because it is too large Load Diff

View File

@ -1,95 +0,0 @@
/**
* @module og/entity/PolylineHandler
*/
'use strict';
import * as shaders from '../shaders/polyline.js';
class PolylineHandler {
constructor(entityCollection) {
this._entityCollection = entityCollection;
this._renderer = null;
this._polylines = [];
this.__staticId = PolylineHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.polyline) {
this._renderer.handler.addShaderProgram(shaders.polyline(this._renderer.isMultiFramebufferCompatible()));
}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._polylines.length; i++) {
this._polylines[i].setRenderNode(renderNode);
}
}
add(polyline) {
if (polyline._handlerIndex == -1) {
polyline._handler = this;
polyline._handlerIndex = this._polylines.length;
this._polylines.push(polyline);
this._entityCollection && this._entityCollection.renderNode &&
polyline.setRenderNode(this._entityCollection.renderNode);
}
}
remove(polyline) {
var index = polyline._handlerIndex;
if (index !== -1) {
polyline._deleteBuffers();
polyline._handlerIndex = -1;
polyline._handler = null;
this._polylines.splice(index, 1);
this.reindexPolylineArray(index);
}
}
reindexPolylineArray(startIndex) {
var ls = this._polylines;
for (var i = startIndex; i < ls.length; i++) {
ls[i]._handlerIndex = i;
}
}
draw() {
var i = this._polylines.length;
while (i--) {
this._polylines[i].draw();
}
}
clear() {
var i = this._polylines.length;
while (i--) {
this._polylines[i]._deleteBuffers();
this._polylines[i]._handler = null;
this._polylines[i]._handlerIndex = -1;
}
this._polylines.length = 0;
this._polylines = [];
}
};
export { PolylineHandler };

View File

@ -1,90 +0,0 @@
/**
* @module og/entity/ShapeHandler
*/
'use strict';
import * as shaders from '../shaders/shape.js';
class ShapeHandler {
constructor(entityCollection) {
/**
* Picking rendering option.
* @public
* @type {boolean}
*/
this.pickingEnabled = true;
this._entityCollection = entityCollection;
this._renderer = null;
this._shapes = [];
this.__staticId = ShapeHandler._staticCounter++;
}
static get _staticCounter() {
if (!this._counter && this._counter !== 0) {
this._counter = 0;
}
return this._counter;
}
static set _staticCounter(n) {
this._counter = n;
}
_initShaderProgram() {
if (this._renderer.handler) {
if (!this._renderer.handler.shaderPrograms.shape_nl) {
this._renderer.handler.addShaderProgram(shaders.shape_nl());
}
if (!this._renderer.handler.shaderPrograms.shape_wl) {
this._renderer.handler.addShaderProgram(shaders.shape_wl());
}
//if (!this._renderer.handler.shaderPrograms.shapePicking) {
// this._renderer.handler.addShaderProgram(shaders.shapePicking());
//}
}
}
setRenderNode(renderNode) {
this._renderer = renderNode.renderer;
this._initShaderProgram()
for (var i = 0; i < this._shapes.length; i++) {
this._shapes[i].setRenderNode(renderNode);
}
}
add(shape) {
if (shape._handlerIndex == -1) {
shape._handler = this;
shape._handlerIndex = this._shapes.length;
this._shapes.push(shape);
this._entityCollection && this._entityCollection.renderNode && shape.setRenderNode(this._entityCollection.renderNode);
}
}
remove(shape) {
//TODO
}
draw() {
var i = this._shapes.length;
while (i--) {
this._shapes[i].draw();
}
}
drawPicking() {
//TODO
}
clear() {
//TODO
}
};
export { ShapeHandler };

View File

@ -1,144 +0,0 @@
/**
* @module og/Frustum
*/
'use strict';
/**
* Frustum object, part of the camera object.
* @class
*/
class Frustum {
constructor() {
/**
* Frustum planes.
* @private
* @type {Array.<Array.<number>>}
*/
this._f = new Array(6);
for (var i = 0; i < 6; i++)
this._f[i] = new Array(4);
}
/**
* Normalize frustum plane.
* @static
* @param {Array.<number>} plane - Frustum plane coordinates.
*/
static planeNormalize(plane) {
var t = Math.sqrt(plane[0] * plane[0] + plane[1] * plane[1] + plane[2] * plane[2]);
plane[0] /= t;
plane[1] /= t;
plane[2] /= t;
plane[3] /= t;
}
/**
* Camera's projection matrix values.
* @public
* @param {Array.<number>} clip - Projection matrix parameters.
*/
setFrustum(clip) {
/* Right */
this._f[0][0] = clip[3] - clip[0];
this._f[0][1] = clip[7] - clip[4];
this._f[0][2] = clip[11] - clip[8];
this._f[0][3] = clip[15] - clip[12];
Frustum.planeNormalize(this._f[0]);
/* Left */
this._f[1][0] = clip[3] + clip[0];
this._f[1][1] = clip[7] + clip[4];
this._f[1][2] = clip[11] + clip[8];
this._f[1][3] = clip[15] + clip[12];
Frustum.planeNormalize(this._f[1]);
/* Bottom */
this._f[2][0] = clip[3] + clip[1];
this._f[2][1] = clip[7] + clip[5];
this._f[2][2] = clip[11] + clip[9];
this._f[2][3] = clip[15] + clip[13];
Frustum.planeNormalize(this._f[2]);
/* Top */
this._f[3][0] = clip[3] - clip[1];
this._f[3][1] = clip[7] - clip[5];
this._f[3][2] = clip[11] - clip[9];
this._f[3][3] = clip[15] - clip[13];
Frustum.planeNormalize(this._f[3]);
/* Backward */
this._f[4][0] = clip[3] - clip[2];
this._f[4][1] = clip[7] - clip[6];
this._f[4][2] = clip[11] - clip[10];
this._f[4][3] = clip[15] - clip[14];
Frustum.planeNormalize(this._f[4]);
/* Forward */
this._f[5][0] = clip[3] + clip[2];
this._f[5][1] = clip[7] + clip[6];
this._f[5][2] = clip[11] + clip[10];
this._f[5][3] = clip[15] + clip[14];
Frustum.planeNormalize(this._f[5]);
}
/**
* Returns true if a point in the frustum.
* @public
* @param {og.math.Vec3} point - Cartesian point.
* @returns {boolean}
*/
containsPoint(point) {
var d;
for (var p = 0; p < 6; p++) {
d = point.dotArr(this._f[p]) + this._f[p][3];
if (d <= 0)
return false;
}
return true;
}
/**
* Returns true if the frustum contains a bonding sphere.
* @public
* @param {og.bv.Sphere} sphere - Bounding sphere.
* @returns {boolean}
*/
containsSphere(sphere) {
var r = -sphere.radius;
if (sphere.center.dotArr(this._f[0]) + this._f[0][3] <= r) return false;
if (sphere.center.dotArr(this._f[1]) + this._f[1][3] <= r) return false;
if (sphere.center.dotArr(this._f[2]) + this._f[2][3] <= r) return false;
if (sphere.center.dotArr(this._f[3]) + this._f[3][3] <= r) return false;
if (sphere.center.dotArr(this._f[4]) + this._f[4][3] <= r) return false;
if (sphere.center.dotArr(this._f[5]) + this._f[5][3] <= r) return false;
return true;
}
/**
* Returns true if the frustum contains a bounding box.
* @public
* @param {og.bv.Box} box - Bounding box.
* @returns {boolean}
*/
containsBox(box) {
var result = true, cout, cin;
for (var i = 0; i < 6; i++) {
cout = 0; cin = 0;
for (var k = 0; k < 8 && (cin == 0 || cout == 0); k++) {
var d = box.vertices[k].dotArr(this._f[i]) + this._f[i][3];
if (d < 0)
cout++;
else
cin++;
}
if (cin == 0)
return false;
else if (cout > 0)
result = true;
}
return (result);
}
};
export { Frustum };

View File

@ -1,164 +0,0 @@
'use strict';
import * as jd from './astro/jd.js';
import * as math from './math.js';
import * as mercator from './mercator.js';
import * as utils from './utils/shared.js';
import { Globe } from './Globe.js';
import { CanvasTiles } from './layer/CanvasTiles.js';
import { GeoImage } from './layer/GeoImage.js';
import { GeoTexture2d } from './layer/GeoTexture2d.js';
import { GeoVideo } from './layer/GeoVideo.js';
import { Layer } from './layer/Layer.js';
import { Vector } from './layer/Vector.js';
import { WMS } from './layer/WMS.js';
import { XYZ } from './layer/XYZ.js';
const layer = {
'CanvasTiles': CanvasTiles,
'GeoImage': GeoImage,
'GeoTexture2d': GeoTexture2d,
'GeoVideo': GeoVideo,
'Layer': Layer,
'Vector': Vector,
'WMS': WMS,
'XYZ': XYZ,
};
import { BaseControl } from './control/BaseControl.js';
import { EarthCoordinates } from './control/EarthCoordinates.js';
import { GeoImageDragControl } from './control/GeoImageDragControl.js';
import { KeyboardNavigation } from './control/KeyboardNavigation.js';
import { LayerSwitcher } from './control/LayerSwitcher.js';
import { MouseNavigation } from './control/MouseNavigation.js';
import { ToggleWireframe } from './control/ToggleWireframe.js';
import { TouchNavigation } from './control/TouchNavigation.js';
import { SimpleNavigation } from './control/SimpleNavigation.js';
import { ShowFps } from './control/ShowFps.js';
import { Sun } from './control/Sun.js';
import { ZoomControl } from './control/ZoomControl.js';
const control = {
'BaseControl': BaseControl,
'EarthCoordinates': EarthCoordinates,
'GeoImageDragControl': GeoImageDragControl,
'KeyboardNavigation': KeyboardNavigation,
'LayerSwitcher': LayerSwitcher,
'MouseNavigation': MouseNavigation,
'ToggleWireframe': ToggleWireframe,
'TouchNavigation': TouchNavigation,
'SimpleNavigation': SimpleNavigation,
'ShowFps': ShowFps,
'Sun': Sun,
'ZoomControl': ZoomControl
};
import { Entity } from './entity/Entity.js';
import { EntityCollection } from './entity/EntityCollection.js';
import { Billboard } from './entity/Billboard.js';
import { Geometry } from './entity/Geometry.js';
import { Label } from './entity/Label.js';
import { PointCloud } from './entity/PointCloud.js';
import { Polyline } from './entity/Polyline.js';
const entity = {
'Entity': Entity,
'Billboard': Billboard,
'Geometry': Geometry,
'Label': Label,
'PointCloud': PointCloud,
'Polyline': Polyline
};
import { input } from './input/input.js';
import { Ellipsoid } from './ellipsoid/Ellipsoid.js';
import { wgs84 } from './ellipsoid/wgs84.js';
import { EmptyTerrain } from './terrain/EmptyTerrain.js';
import { GlobusTerrain } from './terrain/GlobusTerrain.js';
const terrain = {
'EmptyTerrain': EmptyTerrain,
'GlobusTerrain': GlobusTerrain
};
import { Camera } from './camera/Camera.js';
import { PlanetCamera } from './camera/PlanetCamera.js';
import { Line2 } from './math/Line2.js';
import { Line3 } from './math/Line3.js';
import { Mat3 } from './math/Mat3.js';
import { Mat4 } from './math/Mat4.js';
import { Plane } from './math/Plane.js';
import { Quat } from './math/Quat.js';
import { Ray } from './math/Ray.js';
import { Vec2 } from './math/Vec2.js';
import { Vec3 } from './math/Vec3.js';
import { Vec4 } from './math/Vec4.js';
import { Framebuffer } from './webgl/Framebuffer.js';
import { Handler } from './webgl/Handler.js';
import { MultiFramebuffer } from './webgl/MultiFramebuffer.js';
import { types } from './webgl/types.js';
import { ShaderProgram } from './webgl/ShaderProgram.js';
const webgl = {
'Framebuffer': Framebuffer,
'Handler': Handler,
'MultiFramebuffer': MultiFramebuffer,
'types': types,
'ShaderProgram': ShaderProgram
};
import { Renderer } from './renderer/Renderer.js';
import { LightSource } from './light/LightSource.js';
import { Clock } from './Clock.js';
import { Events } from './Events.js';
import { Extent } from './Extent.js';
import { LonLat } from './LonLat.js';
import { Planet } from './scene/Planet.js';
import { RenderNode } from './scene/RenderNode.js';
export {
jd,
math,
mercator,
utils,
input,
layer,
terrain,
control,
entity,
webgl,
wgs84,
Camera,
Ellipsoid,
PlanetCamera,
Globe,
LightSource,
EntityCollection,
Handler,
Renderer,
Clock,
Events,
Extent,
LonLat,
Planet,
RenderNode,
Line2,
Line3,
Mat3,
Mat4,
Plane,
Quat,
Ray,
Vec2,
Vec3,
Vec4
};

View File

@ -1,8 +0,0 @@
/**
* @module og/inherits
*/
export function inherits(childCtor, parentCtor) {
childCtor.prototype = Object.create(parentCtor.prototype);
childCtor.prototype.constructor = childCtor;
};

View File

@ -1,87 +0,0 @@
/**
* @module og/input/KeyboardHandler
*/
'use strict';
const KeyboardHandler = function () {
var _currentlyPressedKeys = {};
var _pressedKeysCallbacks = {};
var _charkeysCallbacks = {};
var _that = this;
var _anykeyCallback = null;
var _event = null;
if (KeyboardHandler.prototype._instance) {
return KeyboardHandler.prototype._instance;
} else {
KeyboardHandler.prototype._instance = this;
document.onkeydown = function (event) { _event = event; _that.handleKeyDown.call(_that) };
document.onkeyup = function (event) { _event = event; _that.handleKeyUp.call(_that) };
}
var _sortByPriority = function (a, b) {
return a.priority < b.priority;
};
this.addEvent = function (event, sender, callback, keyCode, priority) {
if (priority === undefined) {
priority = 1600;
}
switch (event) {
case "keypress": {
if (keyCode == null) {
_anykeyCallback = { "callback": callback, "sender": sender || _that };
} else {
if (!_pressedKeysCallbacks[keyCode]) {
_pressedKeysCallbacks[keyCode] = [];
}
_pressedKeysCallbacks[keyCode].push({ callback: callback, sender: sender, priority: priority });
_pressedKeysCallbacks[keyCode].sort(_sortByPriority);
}
} break;
case "charkeypress": {
if (!_charkeysCallbacks[keyCode]) {
_charkeysCallbacks[keyCode] = [];
}
_charkeysCallbacks[keyCode].push({ callback: callback, sender: sender, priority: priority });
_charkeysCallbacks[keyCode].sort(_sortByPriority);
} break;
}
};
this.isKeyPressed = function (keyCode) {
return _currentlyPressedKeys[keyCode];
};
this.handleKeyDown = function () {
_anykeyCallback && _anykeyCallback.callback.call(_anykeyCallback.sender, _event);
_currentlyPressedKeys[_event.keyCode] = true;
for (var ch in _charkeysCallbacks) {
if (String.fromCharCode(_event.keyCode) == String.fromCharCode(ch)) {
var ccl = _charkeysCallbacks[ch];
for (var i = 0; i < ccl.length; i++) {
ccl[i].callback.call(ccl[i].sender, _event);
}
}
}
};
this.handleKeyUp = function () {
_currentlyPressedKeys[_event.keyCode] = false;
};
this.handleEvents = function () {
for (var pk in _pressedKeysCallbacks) {
if (_currentlyPressedKeys[pk]) {
var cpk = _pressedKeysCallbacks[pk];
for (var i = 0; i < cpk.length; i++) {
cpk[i].callback.call(cpk[i].sender, _event);
}
}
}
};
};
export { KeyboardHandler };

View File

@ -1,58 +0,0 @@
/**
* @module og/input/MouseHandler
*/
'use strict';
const MouseHandler = function (htmlObject) {
this._htmlObject = htmlObject;
};
MouseHandler.prototype.setEvent = function (event, sender, callback) {
switch (event) {
case "mousewheel": {
this._htmlObject.addEventListener('mousewheel', function (evt) {
var delta = evt.deltaY || evt.detail || evt.wheelDelta;
if (evt.wheelDelta == undefined) {
evt.wheelDelta = delta * (-120);
}
callback.call(sender, evt);
evt.preventDefault();
}, false);
this._htmlObject.addEventListener('wheel', function (evt) {
var delta = evt.deltaY || evt.detail || evt.wheelDelta;
if (evt.wheelDelta == undefined) {
evt.wheelDelta = delta * (-120);
}
callback.call(sender, evt);
evt.preventDefault();
}, false);
} break;
case "mousedown": {
this._htmlObject.addEventListener('mousedown', function (event) {
callback.call(sender, event);
});
this._htmlObject.addEventListener('contextmenu', function (event) {
event.preventDefault();
return false;
});
} break;
case "mouseup": {
this._htmlObject.addEventListener('mouseup', function (event) {
callback.call(sender, event);
});
} break;
case "mousemove": {
this._htmlObject.addEventListener('mousemove', function (event) {
var rect = this.getBoundingClientRect();
callback.call(sender, {
'clientX': event.clientX - rect.left,
'clientY': event.clientY - rect.top
});
});
} break;
}
};
export { MouseHandler };

View File

@ -1,57 +0,0 @@
/**
* @module og/input/TouchHandler
*/
'use strict';
const TouchHandler = function (htmlObject) {
this._htmlObject = htmlObject;
};
TouchHandler.prototype.setEvent = function (event, sender, callback) {
switch (event) {
case "touchcancel": {
this._htmlObject.addEventListener('touchcancel', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
}
break;
case "touchstart": {
this._htmlObject.addEventListener('touchstart', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
case "touchend": {
this._htmlObject.addEventListener('touchend', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
case "touchmove": {
this._htmlObject.addEventListener('touchmove', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
}
};
export { TouchHandler };

View File

@ -1,31 +0,0 @@
/**
* @module og/input/input
*/
'use strict';
export const input = {
KEY_SHIFT: 16,
KEY_SPACE: 32,
KEY_LEFT: 37,
KEY_UP: 38,
KEY_RIGHT: 39,
KEY_DOWN: 40,
KEY_A: 65,
KEY_C: 67,
KEY_D: 68,
KEY_E: 69,
KEY_F: 70,
KEY_H: 72,
KEY_L: 76,
KEY_Q: 81,
KEY_S: 83,
KEY_V: 86,
KEY_W: 87,
KEY_X: 88,
KEY_F1: 112,
KEY_APOSTROPHE: 192,
MB_LEFT: 0,
MB_RIGHT: 2,
MB_MIDDLE: 1
};

View File

@ -1,87 +0,0 @@
/**
* @module og/input/KeyboardHandler
*/
'use strict';
const KeyboardHandler = function () {
var _currentlyPressedKeys = {};
var _pressedKeysCallbacks = {};
var _charkeysCallbacks = {};
var _that = this;
var _anykeyCallback = null;
var _event = null;
if (KeyboardHandler.prototype._instance) {
return KeyboardHandler.prototype._instance;
} else {
KeyboardHandler.prototype._instance = this;
document.onkeydown = function (event) { _event = event; _that.handleKeyDown.call(_that) };
document.onkeyup = function (event) { _event = event; _that.handleKeyUp.call(_that) };
}
var _sortByPriority = function (a, b) {
return a.priority < b.priority;
};
this.addEvent = function (event, sender, callback, keyCode, priority) {
if (priority === undefined) {
priority = 1600;
}
switch (event) {
case "keypress": {
if (keyCode == null) {
_anykeyCallback = { "callback": callback, "sender": sender || _that };
} else {
if (!_pressedKeysCallbacks[keyCode]) {
_pressedKeysCallbacks[keyCode] = [];
}
_pressedKeysCallbacks[keyCode].push({ callback: callback, sender: sender, priority: priority });
_pressedKeysCallbacks[keyCode].sort(_sortByPriority);
}
} break;
case "charkeypress": {
if (!_charkeysCallbacks[keyCode]) {
_charkeysCallbacks[keyCode] = [];
}
_charkeysCallbacks[keyCode].push({ callback: callback, sender: sender, priority: priority });
_charkeysCallbacks[keyCode].sort(_sortByPriority);
} break;
}
};
this.isKeyPressed = function (keyCode) {
return _currentlyPressedKeys[keyCode];
};
this.handleKeyDown = function () {
_anykeyCallback && _anykeyCallback.callback.call(_anykeyCallback.sender, _event);
_currentlyPressedKeys[_event.keyCode] = true;
for (var ch in _charkeysCallbacks) {
if (String.fromCharCode(_event.keyCode) == String.fromCharCode(ch)) {
var ccl = _charkeysCallbacks[ch];
for (var i = 0; i < ccl.length; i++) {
ccl[i].callback.call(ccl[i].sender, _event);
}
}
}
};
this.handleKeyUp = function () {
_currentlyPressedKeys[_event.keyCode] = false;
};
this.handleEvents = function () {
for (var pk in _pressedKeysCallbacks) {
if (_currentlyPressedKeys[pk]) {
var cpk = _pressedKeysCallbacks[pk];
for (var i = 0; i < cpk.length; i++) {
cpk[i].callback.call(cpk[i].sender, _event);
}
}
}
};
};
export { KeyboardHandler };

View File

@ -1,58 +0,0 @@
/**
* @module og/input/MouseHandler
*/
'use strict';
const MouseHandler = function (htmlObject) {
this._htmlObject = htmlObject;
};
MouseHandler.prototype.setEvent = function (event, sender, callback) {
switch (event) {
case "mousewheel": {
this._htmlObject.addEventListener('mousewheel', function (evt) {
var delta = evt.deltaY || evt.detail || evt.wheelDelta;
if (evt.wheelDelta == undefined) {
evt.wheelDelta = delta * (-120);
}
callback.call(sender, evt);
evt.preventDefault();
}, false);
this._htmlObject.addEventListener('wheel', function (evt) {
var delta = evt.deltaY || evt.detail || evt.wheelDelta;
if (evt.wheelDelta == undefined) {
evt.wheelDelta = delta * (-120);
}
callback.call(sender, evt);
evt.preventDefault();
}, false);
} break;
case "mousedown": {
this._htmlObject.addEventListener('mousedown', function (event) {
callback.call(sender, event);
});
this._htmlObject.addEventListener('contextmenu', function (event) {
event.preventDefault();
return false;
});
} break;
case "mouseup": {
this._htmlObject.addEventListener('mouseup', function (event) {
callback.call(sender, event);
});
} break;
case "mousemove": {
this._htmlObject.addEventListener('mousemove', function (event) {
var rect = this.getBoundingClientRect();
callback.call(sender, {
'clientX': event.clientX - rect.left,
'clientY': event.clientY - rect.top
});
});
} break;
}
};
export { MouseHandler };

View File

@ -1,57 +0,0 @@
/**
* @module og/input/TouchHandler
*/
'use strict';
const TouchHandler = function (htmlObject) {
this._htmlObject = htmlObject;
};
TouchHandler.prototype.setEvent = function (event, sender, callback) {
switch (event) {
case "touchcancel": {
this._htmlObject.addEventListener('touchcancel', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
}
break;
case "touchstart": {
this._htmlObject.addEventListener('touchstart', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
case "touchend": {
this._htmlObject.addEventListener('touchend', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
case "touchmove": {
this._htmlObject.addEventListener('touchmove', function (event) {
event.preventDefault();
var rect = this.getBoundingClientRect();
event.offsetLeft = rect.left;
event.offsetTop = rect.top;
callback.call(sender, event);
event.preventDefault();
});
} break;
}
};
export { TouchHandler };

View File

@ -1,275 +0,0 @@
/**
* @module og/layer/BaseGeoImage
*/
'use sctrict';
import * as mercator from '../mercator.js';
import { Extent } from '../Extent.js';
import { Layer } from './Layer.js';
import { LonLat } from '../LonLat.js';
/**
* BaseGeoImage layer represents square imagery layer that could be an static image, or animated video or webgl buffer object displayed on the globe.
* @class
* @extends {og.layer.Layer}
*/
class BaseGeoImage extends Layer {
constructor(name, options) {
super(name, options);
this._projType = 0;
this._frameWidth = 256;
this._frameHeight = 256;
this._sourceReady = false;
this._sourceTexture = null;
this._materialTexture = null;
this._gridBuffer = null;
this._extentWgs84Params = null;
this._refreshFrame = true;
this._frameCreated = false;
this._sourceCreated = false;
this._animate = false;
this._ready = false;
this._creationProceeding = false;
this._isRendering = false;
this._extentWgs84 = new Extent();
this._cornersWgs84 = null;
this.rendering = null;
options.corners && this.setCorners(options.corners);
}
/**
* Gets corners coordinates.
* @public
* @return {Array.<og.LonLat,og.LonLat,og.LonLat,og.LonLat>}
*/
getCornersLonLat() {
var c = this._cornersWgs84;
return [new LonLat(c[0].lon, c[0].lat), new LonLat(c[1].lon, c[1].lat),
new LonLat(c[2].lon, c[2].lat), new LonLat(c[3].lon, c[3].lat)];
}
/**
* Gets corners coordinates.
* @public
* @return {Array.<Array<number,number,number>>}
*/
getCorners() {
var c = this._cornersWgs84;
return [[c[0].lon, c[0].lat], [c[1].lon, c[1].lat], [c[2].lon, c[2].lat], [c[3].lon, c[3].lat]];
}
/**
* Sets geoImage geographical corners coordinates.
* @public
* @param {Array.<Array.<number,number,number>>} corners - GeoImage corners coordinates. Where first coordinate
* coincedents to the left top image corner, secont to the right top image corner, third to the right bottom
* and fourth - left bottom image corner.
*/
setCorners(corners) {
this.setCornersLonLat(LonLat.join(corners));
}
/**
* Sets geoImage geographical corners coordinates.
* @public
* @param {Array.<og.LonLat, og.LonLat, og.LonLat, og.LonLat>} corners - GeoImage corners coordinates. Where first coordinate
* coincedents to the left top image corner, secont to the right top image corner, third to the right bottom
* and fourth - left bottom image corner.
*/
setCornersLonLat(corners) {
this._refreshFrame = true;
this._cornersWgs84 = [corners[0].clone(), corners[1].clone(), corners[2].clone(), corners[3].clone()] || [0, 0, 0, 0];
for (var i = 0; i < this._cornersWgs84.length; i++) {
if (this._cornersWgs84[i].lat >= 89.9)
this._cornersWgs84[i].lat = 89.9;
if (this._cornersWgs84[i].lat <= -89.9)
this._cornersWgs84[i].lat = -89.9;
}
this._extent.setByCoordinates(this._cornersWgs84);
var me = this._extent;
if (me.southWest.lat > mercator.MAX_LAT ||
me.northEast.lat < mercator.MIN_LAT) {
this._projType = 0;
this.rendering = this._renderingProjType0;
} else {
this._projType = 1;
this.rendering = this._renderingProjType1;
}
if (this._ready && !this._creationProceeding) {
this._planet._geoImageCreator.add(this);
}
}
/**
* Creates geoImage frame.
* @protected
*/
_createFrame() {
this._extentWgs84 = this._extent.clone();
this._cornersMerc = [this._cornersWgs84[0].forwardMercatorEPS01(), this._cornersWgs84[1].forwardMercatorEPS01(),
this._cornersWgs84[2].forwardMercatorEPS01(), this._cornersWgs84[3].forwardMercatorEPS01()];
this._extentMerc = new Extent(this._extentWgs84.southWest.forwardMercatorEPS01(), this._extentWgs84.northEast.forwardMercatorEPS01());
if (this._projType == 0) {
this._extentWgs84Params = [this._extentWgs84.southWest.lon, this._extentWgs84.southWest.lat, 2.0 / this._extentWgs84.getWidth(), 2.0 / this._extentWgs84.getHeight()];
} else {
this._extentMercParams = [this._extentMerc.southWest.lon, this._extentMerc.southWest.lat, 2.0 / this._extentMerc.getWidth(), 2.0 / this._extentMerc.getHeight()];
}
//creates material frame textures
if (this._planet) {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl;
gl.deleteTexture(this._materialTexture);
this._materialTexture = h.createEmptyTexture_l(this._frameWidth, this._frameHeight);
this._gridBuffer = this._planet._geoImageCreator.createGridBuffer(this._cornersWgs84, this._projType);
this._refreshFrame = false;
}
}
/**
* @virtual
* @param {og.planetSegment.Material} material - GeoImage material.
*/
abortMaterialLoading(material) {
this._creationProceeding = false;
material.isLoading = false;
material.isReady = false;
}
/**
* Clear layer material.
* @virtual
*/
clear() {
var p = this._planet;
if (p) {
var gl = p.renderer.handler.gl;
this._creationProceeding && p._geoImageCreator.remove(this);
p._clearLayerMaterial(this);
gl.deleteBuffer(this._gridBuffer);
gl.deleteTexture(this._sourceTexture);
!this._materialTexture.default && gl.deleteTexture(this._materialTexture);
}
this._sourceTexture = null;
this._materialTexture = null;
this._gridBuffer = null;
this._refreshFrame = true;
this._sourceCreated = false;
this._ready = false;
this._creationProceeding = false;
}
/**
* Sets layer visibility.
* @public
* @virtual
* @param {boolean} visibility - GeoImage visibility.
*/
setVisibility(visibility) {
if (visibility != this._visibility) {
this._visibility = visibility;
if (this._isBaseLayer && visibility) {
this._planet.setBaseLayer(this);
}
this._planet.updateVisibleLayers();
this.events.dispatch(this.events.visibilitychange, this);
//remove from creator
if (visibility)
this._sourceReady && this._planet._geoImageCreator.add(this);
else
this._sourceReady && this._planet._geoImageCreator.remove(this);
}
}
/**
* @virtual
* @protected
* @param {og.planetSegment.Material} material - GeoImage material.
*/
clearMaterial(material) {
//just clear material pointer not geoimage
material.image = null;
material.texture = null;
material.isLoading = false;
material.isReady = false;
}
/**
* @virtual
* @protected
* @param {og.planetSegment.Material} material - GeoImage material.
*/
applyMaterial(material) {
var segment = material.segment;
if (this._ready) {
material.applyTexture(this._materialTexture);
} else {
material.texture = this._planet.transparentTexture;
!this._creationProceeding && this.loadMaterial(material);
}
if (this._projType === 0) {
var v0s = this._extentWgs84;
var v0t = segment._extent;
} else {
var v0s = this._extentMerc;
var v0t = segment.getExtentMerc();
}
var sSize_x = v0s.northEast.lon - v0s.southWest.lon;
var sSize_y = v0s.northEast.lat - v0s.southWest.lat;
var dV0s_x = (v0t.southWest.lon - v0s.southWest.lon) / sSize_x;
var dV0s_y = (v0s.northEast.lat - v0t.northEast.lat) / sSize_y;
var dSize_x = (v0t.northEast.lon - v0t.southWest.lon) / sSize_x;
var dSize_y = (v0t.northEast.lat - v0t.southWest.lat) / sSize_y;
return [dV0s_x, dV0s_y, dSize_x, dSize_y];
}
/**
* Gets frame width size in pixels.
* @public
*/
getFrameWidth() {
return this._frameWidth;
}
/**
* Gets frame height size in pixels.
* @public
*/
getFrameHeight() {
return this._frameHeight;
}
};
export { BaseGeoImage };

View File

@ -1,285 +0,0 @@
/**
* @module og/layer/CanvasTiles
*/
'use strict';
import * as quadTree from '../quadTree/quadTree.js';
import { ImageCanvas } from '../ImageCanvas.js';
import { Layer } from './Layer.js';
/**
* Maximum tiles per frame.
* @const
* @type {number}
*/
const MAX_REQUESTS = 7;
const EVENT_NAMES = [
/**
* Triggered when current tile image has loaded before rendereing.
* @event og.layer.CanvasTiles#load
*/
"load",
/**
* Triggered when all tiles have loaded or loading has stopped.
* @event og.layer.CanvasTiles#loadend
*/
"loadend"
];
/**
* Layer used to rendering each tile as a separate canvas object.
* @class
* @extends {og.layer.Layer}
* //TODO: make asynchronous handler.
* @param {String} [name="noname"] - Layer name.
* @param {Object} options:
* @param {number} [options.opacity=1.0] - Layer opacity.
* @param {Array.<number,number,number>} [options.transparentColor=[-1,-1,-1]] - RGB color that defines transparent color.
* @param {number} [options.minZoom=0] - Minimal visibility zoom level.
* @param {number} [options.maxZoom=0] - Maximal visibility zoom level.
* @param {string} [options.attribution] - Layer attribution that displayed in the attribution area on the screen.
* @param {boolean} [options.isBaseLayer=false] - Base layer flag.
* @param {boolean} [options.visibility=true] - Layer visibility.
* @param {og.layer.CanvasTiles~drawTileCallback} [options.drawTile] - Draw tile callback.
* @fires og.layer.CanvasTiles#load
* @fires og.layer.CanvasTiles#loadend
*/
class CanvasTiles extends Layer {
constructor(name, options) {
options = options || {};
super(name, options);
this.events.registerNames(EVENT_NAMES);
/**
* Current creating tiles couter.
* @protected
* @type {number}
*/
this._counter = 0;
/**
* Tile pending queue that waiting for create.
* @protected
* @type {Array.<og.planetSegment.Material>}
*/
this._pendingsQueue = []; //new og.QueueArray();
/**
* Draw tile callback.
* @type {og.layer.CanvasTiles~drawTileCallback}
* @public
*/
this.drawTile = options.drawTile || null;
}
/**
* Abort loading tiles.
* @public
*/
abortLoading() {
var q = this._pendingsQueue;
for (var i = q._shiftIndex + 1; i < q._popIndex + 1; i++) {
if (q._array[i]) {
this.abortMaterialLoading(q._array[i]);
}
}
this._pendingsQueue = [];
//this._pendingsQueue.clear();
};
/**
* Sets layer visibility.
* @public
* @param {boolean} visibility - Layer visibility.
*/
setVisibility(visibility) {
if (visibility != this._visibility) {
this._visibility = visibility;
if (this._isBaseLayer && visibility) {
this._planet.setBaseLayer(this);
} else if (!visibility) {
this.abortLoading();
}
this._planet.updateVisibleLayers();
this.events.dispatch(this.events.visibilitychange, this);
}
}
/**
* Start to load tile material.
* @public
* @virtual
* @param {og.planetSegment.Material} mateial
*/
loadMaterial(material) {
var seg = material.segment;
if (this._isBaseLayer) {
material.texture = seg._isNorth ? seg.planet.solidTextureOne : seg.planet.solidTextureTwo;
} else {
material.texture = seg.planet.transparentTexture;
}
if (this._planet.layerLock.isFree()) {
material.isReady = false;
material.isLoading = true;
if (CanvasTiles.__requestsCounter >= MAX_REQUESTS && this._counter) {
this._pendingsQueue.push(material);
} else {
this._exec(material);
}
}
}
/**
* Loads material image and apply it to the planet segment.
* @protected
* @param {og.planetSegment.Material} material - Loads material image.
*/
_exec(material) {
CanvasTiles.__requestsCounter++;
this._counter++;
var that = this;
if (this.drawTile) {
/**
* Tile custom draw function.
* @callback og.layer.CanvasTiles~drawTileCallback
* @param {og.planetSegment.Material} material
* @param {applyCanvasCallback} applyCanvasCallback
*/
setTimeout(function () {
var e = that.events.load;
if (e.handlers.length) {
that.events.dispatch(e, material);
}
that.drawTile(material,
/**
* Apply canvas.
* @callback applyCanvasCallback
* @param {Object} canvas
*/
function (canvas) {
that._counter--;
og.layer.CanvasTiles.__requestsCounter--;
if (material.isLoading) {
material.applyImage(canvas);
}
that._dequeueRequest();
});
}, 50);
} else {
material.textureNotExists();
}
}
/**
* Abort exact material loading.
* @public
* @param {og.planetSegment.Material} material - Segment material.
*/
abortMaterialLoading(material) {
if (material.isLoading && material.image) {
material.image.src = "";
this._counter--;
og.layer.CanvasTiles.__requestsCounter--;
this._dequeueRequest();
}
material.isLoading = false;
material.isReady = false;
}
_dequeueRequest() {
if (this._pendingsQueue.length) {
if (CanvasTiles.__requestsCounter < MAX_REQUESTS) {
var pmat;
if (pmat = this._whilePendings())
this._exec.call(this, pmat);
}
} else if (this._counter === 0) {
this.events.dispatch(this.events.loadend);
}
}
_whilePendings() {
while (this._pendingsQueue.length) {
var pmat = this._pendingsQueue.pop();
if (pmat.segment.node) {
if (pmat.segment.ready && pmat.segment.node.getState() === quadTree.RENDERING) {
return pmat;
}
pmat.isLoading = false;
}
}
return null;
}
applyMaterial(material) {
if (material.isReady) {
return [0, 0, 1, 1];
} else {
!material.isLoading && this.loadMaterial(material);
var segment = material.segment;
var pn = segment.node,
notEmpty = false;
var mId = this._id;
var psegm = material;
while (pn.parentNode) {
if (psegm && psegm.isReady) {
notEmpty = true;
break;
}
pn = pn.parentNode;
psegm = pn.segment.materials[mId];
}
if (notEmpty) {
material.appliedNodeId = pn.nodeId;
material.texture = psegm.texture;
var dZ2 = 1.0 / (2 << (segment.tileZoom - pn.segment.tileZoom - 1));
return [
segment.tileX * dZ2 - pn.segment.tileX,
segment.tileY * dZ2 - pn.segment.tileY,
dZ2,
dZ2
];
} else {
material.texture = segment.planet.transparentTexture;
return [0, 0, 1, 1];
}
}
}
clearMaterial(material) {
if (material.isReady) {
material.isReady = false;
!material.texture.default &&
material.segment.handler.gl.deleteTexture(material.texture);
material.texture = null;
}
this.abortMaterialLoading(material);
material.isLoading = false;
material.textureExists = false;
if (material.image) {
material.image.src = '';
material.image = null;
}
}
};
export { CanvasTiles };

View File

@ -1,214 +0,0 @@
/**
* @module og/layer/GeoImage
*/
'use sctrict';
import { BaseGeoImage } from './BaseGeoImage.js';
/**
* Used to load and display a single image over specific corner coordinates on the globe, implements og.layer.BaseGeoImage interface.
* @class
* @extends {og.layer.BaseGeoImage}
*/
class GeoImage extends BaseGeoImage {
constructor(name, options) {
super(name, options);
/**
* Image object.
* @private
* @type {Image}
*/
this._image = options.image || null;
/**
* Image source url path.
* @private
* @type {String}
*/
this._src = options.src || null;
}
/**
* Sets image source url path.
* @public
* @param {String} srs - Image url path.
*/
setSrc(src) {
this._planet && this._planet._geoImageCreator.remove(this);
this._src = src;
this._sourceReady = false;
}
/**
* Sets image object.
* @public
* @param {Image} image - Image object.
*/
setImage(image) {
this._planet && this._planet._geoImageCreator.remove(this);
this._image = image;
this._src = image.src;
this._sourceReady = false;
}
/**
* Creates source gl texture.
* @virtual
* @protected
*/
_createSourceTexture() {
if (!this._sourceCreated) {
this._sourceTexture = this._planet.renderer.handler.createTexture_n(this._image);
this._sourceCreated = true;
}
}
/**
* @private
* @param {Image} img
*/
_onLoad(img) {
this._frameWidth = img.width;
this._frameHeight = img.height;
this._sourceReady = true;
this._planet._geoImageCreator.add(this);
}
/**
* Loads planet segment material. In this case - GeoImage source image.
* @virtual
* @public
* @param {og.planetSegment.Material} material - GeoImage planet material.
*/
loadMaterial(material) {
material.isLoading = true;
this._creationProceeding = true;
if (!this._sourceReady && this._src) {
if (this._image) {
if (this._image.complete) {
this._onLoad(this._image);
} else if (this._image.src) {
var that = this;
this._image.addEventListener('load', function (e) {
that._onLoad(this);
});
}
} else {
var that = this;
this._image = new Image();
this._image.addEventListener('load', function (e) {
that._onLoad(this);
});
this._image.src = this._src;
}
} else {
this._planet._geoImageCreator.add(this);
}
}
/**
* @virtual
* @param {og.planetSegment.Material} material - GeoImage material.
*/
abortMaterialLoading(material) {
this._image && (this._image.src = '');
this._creationProceeding = false;
material.isLoading = false;
material.isReady = false;
}
_renderingProjType1() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
this._refreshFrame && this._createFrame();
this._createSourceTexture();
var f = creator._framebuffer;
f.setSize(this._frameWidth, this._frameHeight);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentMercParams);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
_renderingProjType0() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
this._refreshFrame && this._createFrame();
this._createSourceTexture();
var f = creator._framebuffer;
f.setSize(this._frameWidth, this._frameHeight);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentWgs84Params);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
};
export { GeoImage };

View File

@ -1,143 +0,0 @@
/**
* @module og/layer/GeoTexture2d
*/
'use sctrict';
import * as math from '../math.js';
import { BaseGeoImage } from './BaseGeoImage.js';
class GeoTexture2d extends BaseGeoImage {
constructor(name, options) {
super(name, options);
this._sourceTexture = options.texture || null;
if (options.texture) {
this._sourceReady = true;
this._sourceCreated = true;
}
this._frameWidth = options.frameWidth ? math.nextHighestPowerOfTwo(options.frameWidth) : 256;
this._frameHeight = options.frameHeight ? math.nextHighestPowerOfTwo(options.frameHeight) : 256;
this._animate = true;
}
loadMaterial(material) {
this._planet._geoImageCreator.add(this);
};
bindTexture(texture) {
this._sourceReady = true;
this._sourceCreated = true;
this._sourceTexture = texture;
}
setSize(width, height) {
this._frameWidth = width;
this._frameHeight = height;
this._frameCreated = false;
}
abortMaterialLoading(material) {
this._creationProceeding = false;
material.isLoading = false;
material.isReady = false;
}
_renderingProjType1() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
this._refreshFrame && this._createFrame();
var f = creator._framebuffer;
f.setSize(this._frameWidth, this._frameHeight);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentMercParams);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
_renderingProjType0() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
var width = this._frameWidth,
height = this._frameHeight;
this._refreshFrame && this._createFrame();
var f = creator._framebuffer;
f.setSize(width, height);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentWgs84Params);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
};
export { GeoTexture2d };

View File

@ -1,287 +0,0 @@
/**
* @module og/layer/GeoVideo
*/
'use sctrict';
import { BaseGeoImage } from './BaseGeoImage.js';
/**
* Used to load and display a video stream by specific corners coordinates on the globe, implements og.layer.BaseGeoImage interface.
* @class
* @extends {og.layer.BaseGeoImage}
*/
class GeoVideo extends BaseGeoImage {
constructor(name, options) {
super(name, options);
/**
* @protected
* @const
* @type {Boolean}
*/
this._animate = true;
/**
* HTML5 video element object.
* @private
* @type {Object}
*/
this._video = options.videoElement || null;
/**
* VIdeo source url path.
* @private
* @type {String}
*/
this._src = options.src || null;
}
/**
* Sets video source url path.
* @public
* @param {String} srs - Video url path.
*/
setSrc(src) {
this._planet && this._planet._geoImageCreator.remove(this);
this._src = src;
this._sourceReady = false;
}
/**
* Sets HTML5 video object.
* @public
* @param {Object} video - HTML5 video element object.
*/
setVideoElement(video) {
this._planet && this._planet._geoImageCreator.remove(this);
this._video = video;
this._src = video.src;
this._sourceReady = false;
}
/**
* Sets layer visibility.
* @public
* @param {boolean} visibility - Layer visibility.
*/
setVisibility(visibility) {
if (visibility != this._visibility) {
this._visibility = visibility;
if (this._isBaseLayer && visibility) {
this._planet.setBaseLayer(this);
}
this._planet.updateVisibleLayers();
this.events.dispatch(this.events.visibilitychange, this);
//remove from creator
if (visibility) {
this._sourceReady && this._planet._geoImageCreator.add(this);
this._video && this._video.play();
} else {
this._sourceReady && this._planet._geoImageCreator.remove(this);
this._video && this._video.pause();
}
}
}
/**
* Creates or refresh source video GL texture.
* @virtual
* @protected
*/
_createSourceTexture() {
if (!this._sourceCreated) {
this._sourceTexture = this._planet.renderer.handler.createTexture_n(this._video);
this._sourceCreated = true;
} else {
var gl = this._planet.renderer.handler.gl;
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._video);
}
}
/**
* @private
*/
_onCanPlay(video) {
this._frameWidth = video.videoWidth;
this._frameHeight = video.videoHeight;
video.width = video.videoWidth;
video.height = video.videoHeight;
video.play();
this._sourceReady = true;
this._planet._geoImageCreator.add(this);
}
/**
* @private
*/
_onError(video) {
var err = "unknown error";
switch (video.error.code) {
case 1: err = "video loading aborted"; break;
case 2: err = "network loading error"; break;
case 3: err = "video decoding failed / corrupted data or unsupported codec"; break;
case 4: err = "video not supported"; break;
};
console.log("Error: " + err + " (errorcode=" + video.error.code + ")");
};
/**
* Loads planet segment material. In this case - GeoImage source video.
* @virtual
* @public
* @param {og.planetSegment.Material} material - GeoImage planet material.
*/
loadMaterial(material) {
material.isLoading = true;
this._creationProceeding = true;
if (!this._sourceReady && this._src) {
if (this._video) {
if (this._video.readyState === this._video.HAVE_ENOUGH_DATA) {
this._onCanPlay(this._video);
} else if (this._video.src) {
var that = this;
this._video.addEventListener('canplay', function (e) {
that._onCanPlay(this);
});
}
} else {
this._video = document.createElement('video');
var that = this;
this._video.addEventListener('canplay', function () {
that._onCanPlay(this);
});
this._video.addEventListener('error', function () {
that._onError(this);
});
}
this._video.autoplay = true;
this._video.loop = true;
this._video.src = this._src;
this._video.setAttribute("playsinline", "");
this._video.setAttribute("webkit-playsinline", "");
} else {
this._planet._geoImageCreator.add(this);
}
}
/**
* @virtual
* @param {og.planetSegment.Material} material - GeoImage material.
*/
abortMaterialLoading(material) {
this._video && (this._video.src = '');
this._creationProceeding = false;
material.isLoading = false;
material.isReady = false;
}
_renderingProjType1() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
this._refreshFrame && this._createFrame();
if (this._sourceCreated) {
var gl = this._planet.renderer.handler.gl;
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._video);
} else {
this._sourceTexture = this._planet.renderer.handler.createTexture_n(this._video);
this._sourceCreated = true;
}
var f = creator._framebuffer;
f.setSize(this._frameWidth, this._frameHeight);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentMercParams);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
_renderingProjType0() {
var p = this._planet,
h = p.renderer.handler,
gl = h.gl,
creator = p._geoImageCreator;
this._refreshFrame && this._createFrame();
if (!this._sourceCreated) {
this._sourceTexture = this._planet.renderer.handler.createTexture_n(this._video);
this._sourceCreated = true;
} else {
var gl = this._planet.renderer.handler.gl;
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, gl.RGBA, gl.UNSIGNED_BYTE, this._video);
}
var f = creator._framebuffer;
f.setSize(this._frameWidth, this._frameHeight);
f.activate();
h.shaderPrograms.geoImageTransform.activate();
var sh = h.shaderPrograms.geoImageTransform._program;
var sha = sh.attributes,
shu = sh.uniforms;
var tr = this.transparentColor[0],
tg = this.transparentColor[1],
tb = this.transparentColor[2];
gl.disable(gl.CULL_FACE);
f.bindOutputTexture(this._materialTexture);
gl.clearColor(tr, tg, tb, 0.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.bindBuffer(gl.ARRAY_BUFFER, creator._texCoordsBuffer);
gl.vertexAttribPointer(sha.texCoords._pName, creator._texCoordsBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.bindBuffer(gl.ARRAY_BUFFER, this._gridBuffer);
gl.vertexAttribPointer(sha.corners._pName, this._gridBuffer.itemSize, gl.FLOAT, false, 0, 0);
gl.uniform4fv(shu.extentParams._pName, this._extentWgs84Params);
gl.activeTexture(gl.TEXTURE0);
gl.bindTexture(gl.TEXTURE_2D, this._sourceTexture);
gl.uniform1i(shu.sourceTexture._pName, 0);
sh.drawIndexBuffer(gl.TRIANGLE_STRIP, creator._indexBuffer);
f.deactivate();
gl.enable(gl.CULL_FACE);
this._ready = true;
this._creationProceeding = false;
}
};
export { GeoVideo };

View File

@ -1,649 +0,0 @@
/**
* @module og/layer/Layer
*/
'use sctrict';
import * as utils from '../utils/shared.js';
import * as mercator from '../mercator.js';
import { Events } from '../Events.js';
import { Extent } from '../Extent.js';
import { LonLat } from '../LonLat.js';
import { Material } from './Material.js';
import { Vec3 } from '../math/Vec3.js';
/**
* @classdesc
* Base class; normally only used for creating subclasses and not instantiated in apps.
* A visual representation of raster or vector map data well known as a layer.
* @class
* @param {String} [name="noname"] - Layer name.
* @param {Object} [options] - Layer options:
* @param {number} [options.opacity=1.0] - Layer opacity.
* @param {Array.<number,number,number>} [options.transparentColor=[-1,-1,-1]] - RGB color that defines transparent color.
* @param {number} [options.minZoom=0] - Minimal visibility zoom level.
* @param {number} [options.maxZoom=0] - Maximal visibility zoom level.
* @param {string} [options.attribution] - Layer attribution that displayed in the attribution area on the screen.
* @param {boolean} [options.isBaseLayer=false] - This is a base layer.
* @param {boolean} [options.visibility=true] - Layer visibility.
* @param {og.Extent} [options.extent=[[-180.0, -90.0], [180.0, 90.0]]] - Visible extent.
* @param {og.math.Vector3} [options.ambient=[0.1, 0.1, 0.21]] - Ambient RGB color.
* @param {og.math.Vector3} [options.diffuse=[1.0, 1.0, 1.0]] - Diffuse RGB color.
* @param {og.math.Vector3} [options.specular=[0.00025, 0.00015, 0.0001]] - Specular RGB color.
* @param {Number} [options.shininess=100] - Shininess.
*
* @fires og.layer.Layer#visibilitychange
* @fires og.layer.Layer#add
* @fires og.layer.Layer#remove
* @fires og.layer.Vector#mousemove
* @fires og.layer.Vector#mouseenter
* @fires og.layer.Vector#mouseleave
* @fires og.layer.Vector#lclick
* @fires og.layer.Vector#rclick
* @fires og.layer.Vector#mclick
* @fires og.layer.Vector#ldblclick
* @fires og.layer.Vector#rdblclick
* @fires og.layer.Vector#mdblclick
* @fires og.layer.Vector#lup
* @fires og.layer.Vector#rup
* @fires og.layer.Vector#mup
* @fires og.layer.Vector#ldown
* @fires og.layer.Vector#rdown
* @fires og.layer.Vector#mdown
* @fires og.layer.Vector#lhold
* @fires og.layer.Vector#rhold
* @fires og.layer.Vector#mhold
* @fires og.layer.Vector#mousewheel
* @fires og.layer.Vector#touchmove
* @fires og.layer.Vector#touchstart
* @fires og.layer.Vector#touchend
* @fires og.layer.Vector#doubletouch
*/
class Layer {
constructor(name, options) {
options = options || {};
/**
* Layer user name.
* @public
* @type {string}
*/
this.name = name || "noname";
this.displayInLayerSwitcher = options.displayInLayerSwitcher !== undefined ? options.displayInLayerSwitcher : true;
/**
* Layer global opacity.
* @public
* @type {number}
*/
this.opacity = options.opacity || 1.0;
/**
* Transparent RGB color mask.
* @public
* @type {Array.<number,number,number>}
*/
this.transparentColor = options.transparentColor || [-1, -1, -1];
/**
* Minimal zoom level when layer is visibile.
* @public
* @type {number}
*/
this.minZoom = options.minZoom || 0;
/**
* Maximal zoom level when layer is visibile.
* @public
* @type {number}
*/
this.maxZoom = options.maxZoom || 50;
/**
* Layer light material parameters.
* @public
* @type {Object}
*/
this.ambient = utils.createColorRGB(options.ambient, new Vec3(0.1, 0.1, 0.21));
this.diffuse = utils.createColorRGB(options.diffuse, new Vec3(1.0, 1.0, 1.0));
this.specular = utils.createColorRGB(options.specular, new Vec3(0.00025, 0.00015, 0.0001));
this.shininess = options.shininess || 100.0;
/**
* Planet node.
* @protected
* @type {og.scene.Planet}
*/
this._planet = null;
/**
* Unic identifier.
* @protected
* @type {number}
*/
this._id = Layer.__layersCounter++;
/**
* Layer attribution.
* @protected
* @type {string}
*/
this._attribution = options.attribution || "";
/**
* Layer z-index.
* @protected
* @type {number}
*/
this._zIndex = options.zIndex || 0;
/**
* Base layer type flag.
* @protected
* @type {boolean}
*/
this._isBaseLayer = options.isBaseLayer || false;
/**
* Layer visibility.
* @protected
* @type {boolean}
*/
this._visibility = options.visibility !== undefined ? options.visibility : true;
/**
* Height over the ground.
* @protected
* @type {number}
*/
this._height = options.height || 0;
/**
* Visible degrees extent.
* @protected
* @type {og.Extent}
*/
this._extent = null;
/**
* Visible mercator extent.
* @protected
* @type {og.Extent}
*/
this._extentMerc = null;
//Setting the extent up
this.setExtent(utils.createExtent(options.extent, new Extent(new LonLat(-180, -90), new LonLat(180, 90))));
/**
* Layer picking color. Assign when added to the planet.
* @protected
* @type {og.math.Vector3}
*/
this._pickingColor = new Vec3();
/**
* Events handler.
* @public
* @type {og.Events}
*/
this.events = new Events();
this.events.registerNames(EVENT_NAMES);
}
static getTileIndex(...arr) {
return arr.join("_");
}
static get __layersCounter() {
if (!this.__lcounter && this.__lcounter !== 0) {
this.__lcounter = 0;
}
return this.__lcounter;
}
static set __layersCounter(n) {
this.__lcounter = n;
}
/**
* Returns true if a layer has imagery tiles.
* @public
* @virtual
* @returns {boolean} - Imagery tiles flag.
*/
hasImageryTiles() {
return true;
}
/**
* Gets layer identifier.
* @public
* @returns {string} - Layer object id.
*/
getID() {
return this._id;
}
/**
* Compares layers instances.
* @public
* @param {og.layer.Layer} layer - Layer instance to compare.
* @returns {boolean} - Returns true if the layers is the same instance of the input.
*/
isEqual(layer) {
return layer._id === this._id;
}
/**
* Assign the planet.
* @protected
* @virtual
* @param {og.scene.Planet} planet - Planet render node.
*/
_assignPlanet(planet) {
planet.layers.push(this);
this._planet = planet;
this.events.on("visibilitychange", planet._onLayerVisibilityChanged, planet);
if (this._isBaseLayer && this._visibility) {
planet.setBaseLayer(this);
}
planet.events.dispatch(planet.events.layeradd, this);
this.events.dispatch(this.events.add, planet);
planet.updateVisibleLayers();
this._bindPicking();
}
/**
* Assign picking color to the layer.
* @protected
* @virtual
*/
_bindPicking() {
this._planet && this._planet.renderer.assignPickingColor(this);
}
/**
* Adds layer to the planet.
* @public
* @param {og.scene.Planet} planet - Adds layer to the planet.
*/
addTo(planet) {
this._assignPlanet(planet);
}
/**
* Removes from planet.
* @public
* @returns {og.layer.Layer} -This layer.
*/
remove() {
var p = this._planet;
if (p) {
var lid = this._id;
for (var i = 0; i < p.layers.length; i++) {
if (p.layers[i]._id === lid) {
p.renderer.clearPickingColor(this);
p.layers.splice(i, 1);
p.updateVisibleLayers();
this.clear();
p.events.dispatch(p.events.layerremove, this);
this.events.dispatch(this.events.remove, p);
this._planet = null;
return this;
}
}
}
return this;
}
/**
* Clears layer material.
* @virtual
*/
clear() {
this._planet && this._planet._clearLayerMaterial(this);
}
/**
* Sets layer attribution text.
* @public
* @param {string} html - HTML code that represents layer attribution, it could be just a text.
*/
setAttribution(html) {
this._attribution = html;
this._planet.updateAttributionsList();
}
/**
* Sets height over the ground.
* @public
* @param {number} height - Layer height.
*/
setHeight(height) {
this._height = height;
this._planet.updateVisibleLayers();
}
/**
* Gets layer height.
* @public
* @returns {number} -
*/
getHeight() {
return this._height;
}
/**
* Sets z-index.
* @public
* @param {number} zIndex - Layer z-index.
*/
setZIndex(zIndex) {
this._zIndex = zIndex;
this._planet.updateVisibleLayers();
}
/**
* Gets z-index.
* @public
* @returns {number} -
*/
getZIndex() {
return this._zIndex;
}
/**
* Set zIndex to the maximal value depend on other layers on the planet.
* @public
*/
bringToFront() {
if (this._planet) {
var vl = this._planet.visibleTileLayers;
var l = vl[vl.length - 1];
if (!l.isEqual(this)) {
this.setZIndex(l.getZIndex() + 1);
}
}
}
/**
* Returns true if the layer is a base.
* @public
* @returns {boolean} - Base layer flag.
*/
isBaseLayer() {
return this._isBaseLayer;
}
/**
* Sets base layer type true.
* @public
* @param {boolean} flag - Base layer flag.
*/
setBaseLayer(flag) {
this._isBaseLayer = flag;
if (this._planet && !flag && this.isEqual(this._planet.baseLayer)) {
this._planet.baseLayer = null;
}
this._planet.updateVisibleLayers();
}
/**
* Sets layer visibility.
* @public
* @virtual
* @param {boolean} visibility - Layer visibility.
*/
setVisibility(visibility) {
if (visibility !== this._visibility) {
this._visibility = visibility;
if (this._isBaseLayer && visibility) {
this._planet.setBaseLayer(this);
}
this._planet.updateVisibleLayers();
this.events.dispatch(this.events.visibilitychange, this);
}
}
/**
* Gets layer visibility.
* @public
* @returns {boolean} - Layer visibility.
*/
getVisibility() {
return this._visibility;
}
/**
* Sets visible geographical extent.
* @public
* @param {og.Extent} extent - Layer visible geographical extent.
*/
setExtent(extent) {
var sw = extent.southWest.clone(),
ne = extent.northEast.clone();
if (sw.lat < mercator.MIN_LAT) {
sw.lat = mercator.MIN_LAT;
}
if (ne.lat > mercator.MAX_LAT) {
ne.lat = mercator.MAX_LAT;
}
this._extent = extent.clone();
this._extentMerc = new Extent(sw.forwardMercator(), ne.forwardMercator());
this._correctFullExtent();
}
/**
* Gets layer extent.
* @public
* @return {og.Extent} - Layer geodetic extent.
*/
getExtent() {
return this._extent;
}
/**
* Special correction of the whole globe extent.
* @protected
*/
_correctFullExtent() {
//var e = this._extent,
// em = this._extentMerc;
//var ENLARGE_MERCATOR_LON = og.mercator.POLE + 50000;
//var ENLARGE_MERCATOR_LAT = og.mercator.POLE + 50000;
//if (e.northEast.lat === 90.0) {
// em.northEast.lat = ENLARGE_MERCATOR_LAT;
//}
//if (e.northEast.lon === 180.0) {
// em.northEast.lon = ENLARGE_MERCATOR_LON;
//}
//if (e.southWest.lat === -90.0) {
// em.southWest.lat = -ENLARGE_MERCATOR_LAT;
//}
//if (e.southWest.lon === -180.0) {
// em.southWest.lon = -ENLARGE_MERCATOR_LON;
//}
}
createMaterial(segment) {
return new Material(segment, this);
}
};
const EVENT_NAMES = [
/**
* Triggered when layer visibilty chanched.
* @event og.layer.Layer#visibilitychange
*/
"visibilitychange",
/**
* Triggered when layer has added to the planet.
* @event og.layer.Layer#add
*/
"add",
/**
* Triggered when layer has removed from the planet.
* @event og.layer.Layer#remove
*/
"remove",
/**
* Triggered when mouse moves over the layer.
* @event og.layer.Layer#mousemove
*/
"mousemove",
/**
* Triggered when mouse has entered over the layer.
* @event og.layer.Layer#mouseenter
*/
"mouseenter",
/**
* Triggered when mouse leaves the layer.
* @event og.layer.Layer#mouseenter
*/
"mouseleave",
/**
* Mouse left button clicked.
* @event og.layer.Layer#lclick
*/
"lclick",
/**
* Mouse right button clicked.
* @event og.layer.Layer#rclick
*/
"rclick",
/**
* Mouse right button clicked.
* @event og.layer.Layer#mclick
*/
"mclick",
/**
* Mouse left button double click.
* @event og.layer.Layer#ldblclick
*/
"ldblclick",
/**
* Mouse right button double click.
* @event og.layer.Layer#rdblclick
*/
"rdblclick",
/**
* Mouse middle button double click.
* @event og.layer.Layer#mdblclick
*/
"mdblclick",
/**
* Mouse left button up(stop pressing).
* @event og.layer.Layer#lup
*/
"lup",
/**
* Mouse right button up(stop pressing).
* @event og.layer.Layer#rup
*/
"rup",
/**
* Mouse middle button up(stop pressing).
* @event og.layer.Layer#mup
*/
"mup",
/**
* Mouse left button is just pressed down(start pressing).
* @event og.layer.Layer#ldown
*/
"ldown",
/**
* Mouse right button is just pressed down(start pressing).
* @event og.layer.Layer#rdown
*/
"rdown",
/**
* Mouse middle button is just pressed down(start pressing).
* @event og.layer.Layer#mdown
*/
"mdown",
/**
* Mouse left button is pressing.
* @event og.layer.Layer#lhold
*/
"lhold",
/**
* Mouse right button is pressing.
* @event og.layer.Layer#rhold
*/
"rhold",
/**
* Mouse middle button is pressing.
* @event og.layer.Layer#mhold
*/
"mhold",
/**
* Mouse wheel is rotated.
* @event og.layer.Layer#mousewheel
*/
"mousewheel",
/**
* Triggered when touching moves over the layer.
* @event og.layer.Layer#touchmove
*/
"touchmove",
/**
* Triggered when layer begins to touch.
* @event og.layer.Layer#touchstart
*/
"touchstart",
/**
* Triggered when layer has finished touching.
* @event og.layer.Layer#touchend
*/
"touchend",
/**
* Triggered layer has double touched.
* @event og.layer.Layer#doubletouch
*/
"doubletouch",
/**
* Triggered when touching leaves layer borders.
* @event og.layer.Layer#touchleave
*/
"touchleave",
/**
* Triggered when touch enters over the layer.
* @event og.layer.Layer#touchenter
*/
"touchenter"
];
export { Layer };

View File

@ -1,70 +0,0 @@
/**
* @module og/layer/Material
*/
'use strict';
const Material = function (segment, layer) {
this.segment = segment;
this.layer = layer;
this.isReady = false;
this.isLoading = false;
this.texture = null;
this.pickingMask = null;
this.image = null;
this.textureExists = false;
this.appliedNodeId = 0;
//vector data
this._updateTexture = null;
this._updatePickingMask = null;
this.pickingReady = false;
};
Material.prototype.assignLayer = function (layer) {
this.layer = layer;
};
Material.prototype.abortLoading = function () {
this.layer.abortMaterialLoading(this);
};
Material.prototype.applyImage = function (img) {
if (this.segment.ready) {
this._updateTexture = null;
this.image = img;
this.texture = this.segment.handler.createTexture(img);
this.appliedNodeId = this.segment.node.nodeId;
this.isReady = true;
this.pickingReady = true;
this.textureExists = true;
this.isLoading = false;
}
};
Material.prototype.applyTexture = function (texture, pickingMask) {
this.texture = texture;
this._updateTexture = null;
this.pickingMask = pickingMask || null;
this._updatePickingMask = null;
this.isReady = true;
this.pickingReady = true;
this.textureExists = true;
this.isLoading = false;
this.appliedNodeId = this.segment.node.nodeId;
};
Material.prototype.textureNotExists = function () {
this.isLoading = true;
this.textureExists = false;
};
Material.prototype.clear = function () {
this.layer.clearMaterial(this);
};
export { Material };

View File

@ -1,814 +0,0 @@
/**
* @module og/layer/Vector
*/
'use strict';
import * as math from '../math.js';
import * as mercator from '../mercator.js';
import * as quadTree from '../quadTree/quadTree.js';
import { Entity } from '../entity/Entity.js';
import { EntityCollection } from '../entity/EntityCollection.js';
import { Extent } from '../Extent.js';
import {
EntityCollectionNode,
EntityCollectionNodeWGS84
} from '../quadTree/EntityCollectionNode.js';
import { GeometryHandler } from '../entity/GeometryHandler.js';
import { Layer } from './Layer.js';
import { LonLat } from '../LonLat.js';
import { QueueArray } from '../QueueArray.js';
import { Vec3 } from '../math/Vec3.js';
/**
* Creates entity instance array.
* @static
* @param {og.Entities[] || Object[]} entities - Entity array.
* @returns {og.Entity[]} - Entity object array.
*/
function _entitiesConstructor(entities) {
var res = [];
for (var i = 0; i < entities.length; i++) {
var ei = entities[i];
if (ei instanceof Entity) {
res.push(ei);
} else {
res.push(new Entity(ei));
}
}
return res;
};
/**
* Vector layer represents alternative entities store. Used for geospatial data rendering like
* points, lines, polygons, geometry objects etc.
* @class
* @extends {og.layer.Layer}
* @param {string} [name="noname"] - Layer name.
* @param {Object} [options] - Layer options:
* @param {number} [options.minZoom=0] - Minimal visible zoom. 0 is default
* @param {number} [options.maxZoom=50] - Maximal visible zoom. 50 is default.
* @param {string} [options.attribution] - Layer attribution.
* @param {string} [options.zIndex=0] - Layer Z-order index. 0 is default.
* @param {boolean} [options.visibility=true] - Layer visibility. True is default.
* @param {boolean} [options.isBaseLayer=false] - Layer base layer. False is default.
* @param {Array.<og.Entity>} [options.entities] - Entities array.
* @param {Array.<number,number,number>} [options.scaleByDistance] - Scale by distance parameters.
* First index - near distance to the entity, after entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @param {number} [options.nodeCapacity=30] - Maximum entities quantity in the tree node. Rendering optimization parameter. 30 is default.
* @param {boolean} [options.async=true] - Asynchronous vector data handling before rendering. True for optimization huge data.
* @param {boolean} [options.clampToGround = false] - Clamp vector data to the ground.
* @param {boolean} [options.relativeToGround = false] - Place vector data relative to the ground relief.
*
* @fires og.layer.Vector#entitymove
* @fires og.layer.Vector#draw
* @fires og.layer.Vector#add
* @fires og.layer.Vector#remove
* @fires og.layer.Vector#entityadd
* @fires og.layer.Vector#entityremove
* @fires og.layer.Vector#visibilitychange
*/
class Vector extends Layer {
constructor(name, options) {
options = options || {};
super(name, options);
this.events.registerNames(EVENT_NAMES);
this.isVector = true;
/**
* First index - near distance to the entity, after that entity becomes full scale.
* Second index - far distance to the entity, when entity becomes zero scale.
* Third index - far distance to the entity, when entity becomes invisible.
* @public
* @type {Array.<number,number,number>}
*/
this.scaleByDistance = options.scaleByDistance || [math.MAX32, math.MAX32, math.MAX32];
/**
* Asynchronous data handling before rendering.
* @public
* @type {boolean}
*/
this.async = options.async !== undefined ? options.async : true;
/**
* Vector data clamp to ground flag.
* @public
* @type {boolean}
*/
this.clampToGround = options.clampToGround || false;
/**
* Sets vector data relative to the ground relief.
* @public
* @type {boolean}
*/
this.relativeToGround = options.relativeToGround || false;
/**
* Maximum entities quantity in the tree node.
* @private
*/
this._nodeCapacity = options.nodeCapacity || 30;
this._pickingEnabled = options.pickingEnabled !== undefined ? options.pickingEnabled : true;
/**
* Manimal tree node depth index.
* @private
*/
this._minDepth = options.minDepth || 1;
/**
* Stored entities.
* @private
*/
this._entities = _entitiesConstructor(options.entities || []);
this._polylineEntityCollection = new EntityCollection({
'pickingEnabled': this._pickingEnabled
});
this._bindEventsDefault(this._polylineEntityCollection);
this._geometryHandler = new GeometryHandler(this);
this._entityCollectionsTree = null;
this._entityCollectionsTreeNorth = null;
this._entityCollectionsTreeSouth = null;
this._renderingNodes = {};
this._renderingNodesNorth = {};
this._renderingNodesSouth = {};
this._counter = 0;
this._deferredEntitiesPendingQueue = new QueueArray();
this._pendingsQueue = [];
/** Creates collections tree*/
this.setEntities(this._entities);
}
_bindPicking() {
this._pickingColor.clear();
}
/**
* Adds layer to the planet.
* @public
*/
addTo(planet) {
this._assignPlanet(planet);
this._geometryHandler.assignHandler(planet.renderer.handler);
this._polylineEntityCollection.addTo(planet, true);
this.setEntities(this._entities);
return this;
}
/**
* Returns true if a layer has rasterized vector data like polygons.
* @public
* @virtual
* @returns {boolean}
*/
hasImageryTiles() {
return true;
}
/**
* Returns stored entities.
* @public
* @returns {Array.<og.Entity>}
*/
getEntities() {
return [].concat(this._entities);
}
/**
* @private
*/
_fitExtent(entity) {
var ee = entity.getExtent(),
e = this._extent;
if (ee.southWest.lon < e.southWest.lon) {
e.southWest.lon = ee.southWest.lon;
}
if (ee.southWest.lat < e.southWest.lat) {
e.southWest.lat = ee.southWest.lat;
}
if (ee.northEast.lon > e.northEast.lon) {
e.northEast.lon = ee.northEast.lon;
}
if (ee.northEast.lat > e.northEast.lat) {
e.northEast.lat = ee.northEast.lat;
}
this.setExtent(this._extent);
}
/**
* Adds entity to the layer.
* @public
* @param {og.Entity} entity - Entity.
* @param {boolean} [rightNow] - Entity insertion option. False is deafult.
* @returns {og.layer.Vector} - Returns this layer.
*/
add(entity, rightNow) {
if (!(entity._layer || entity._entityCollection)) {
entity._layer = this;
entity._layerIndex = this._entities.length;
this._entities.push(entity);
this._fitExtent(entity);
//
//...pointCloud, shape, model etc.
//
if (entity.polyline) {
this._polylineEntityCollection.add(entity);
}
if (entity.geometry) {
if (this._planet) {
this._planet.renderer.assignPickingColor(entity);
this._geometryHandler.add(entity.geometry);
}
}
if (entity.billboard || entity.label) {
if (this._planet) {
if (!entity._lonlat) {
entity._lonlat = this.layer._planet.ellipsoid.cartesianToLonLat(entity._cartesian);
}
//poles trees
if (entity._lonlat.lat > mercator.MAX_LAT) {
this._entityCollectionsTreeNorth.insertEntity(entity, rightNow);
} else if (entity._lonlat.lat < mercator.MIN_LAT) {
this._entityCollectionsTreeSouth.insertEntity(entity, rightNow);
} else {
this._entityCollectionsTree.insertEntity(entity, rightNow);
}
}
}
this.events.dispatch(this.events.entityadd, entity);
}
return this;
}
/**
* Adds entity array to the layer.
* @public
* @param {Array.<og.Entity>} entities - Entities array.
* @param {boolean} [rightNow] - Entity insertion option. False is deafult.
* @returns {og.layer.Vector} - Returns this layer.
*/
addEntities(entities, rightNow) {
var i = entities.length;
while (i--) {
this.add(entities[i], rightNow);
}
return this;
}
/**
* Remove entity from layer.
* TODO: memory leaks.
* @public
* @param {og.Entity} entity - Entity to remove.
* @returns {og.layer.Vector} - Returns this layer.
*/
removeEntity(entity) {
if (entity._layer && this.isEqual(entity._layer)) {
this._entities.splice(entity._layerIndex, 1);
this._reindexEntitiesArray(entity._layerIndex);
entity._layer = null;
entity._layerIndex = -1;
if (entity._entityCollection) {
entity._entityCollection._removeEntitySilent(entity);
var node = entity._nodePtr;
while (node) {
node.count--;
node = node.parentNode;
}
if (entity._nodePtr && entity._nodePtr.count === 0 &&
entity._nodePtr.deferredEntities.length === 0) {
entity._nodePtr.entityCollection = null;
//
//...
//
}
} else if (entity._nodePtr &&
entity._nodePtr.deferredEntities.length) {
var defEntities = entity._nodePtr.deferredEntities;
var j = defEntities.length;
while (j--) {
if (defEntities[j].id === entity.id) {
defEntities.splice(j, 1);
var node = entity._nodePtr;
while (node) {
node.count--;
node = node.parentNode;
}
break;
}
}
}
if (entity.geometry) {
if (this._planet) {
this._geometryHandler.remove(entity.geometry);
this._planet.renderer.clearPickingColor(entity);
}
}
entity._nodePtr && (entity._nodePtr = null);
this.events.dispatch(this.events.entityremove, entity);
}
return this;
}
/**
* Set layer picking events active.
* @public
* @param {number} enable
*/
setPickingEnabled(enable) {
this._pickingEnabled = enable;
this._polylineEntityCollection.setPickingEnabled(enable);
this._entityCollectionsTree.traverseTree(function (ec) {
ec.setPickingEnabled(enable);
});
this._entityCollectionsTreeNorth.traverseTree(function (ec) {
ec.setPickingEnabled(enable);
});
this._entityCollectionsTreeSouth.traverseTree(function (ec) {
ec.setPickingEnabled(enable);
});
}
/**
* Refresh collected entities indexes from startIndex entitytes collection array position.
* @public
* @param {number} startIndex - Entity array index.
*/
_reindexEntitiesArray(startIndex) {
var e = this._entities;
for (var i = startIndex; i < e.length; i++) {
e[i]._layerIndex = i;
}
}
/**
* Removes entities from layer.
* @public
* @param {Array.<og.Entity>} entities - Entity array.
* @returns {og.layer.Vector} - Returns this layer.
*/
removeEntities(entities) {
var i = entities.length;
while (i--) {
this.removeEntity(entities[i]);
}
return this;
}
/**
* Sets scale by distance parameters.
* @public
* @param {number} near - Full scale entity distance.
* @param {number} far - Zerol scale entity distance.
* @param {number} [farInvisible] - Entity visibility distance.
*/
setScaleByDistance(near, far, farInisible) {
this.scaleByDistance[0] = near;
this.scaleByDistance[1] = far;
this.scaleByDistance[2] = farInisible || math.MAX32;
return this;
}
/**
* TODO: Clear the layer.
* @public
*/
clear() {
//TODO
}
/**
* Safety entities loop.
* @public
* @param {callback} callback - Entity callback.
*/
each(callback) {
var e = this._entities;
var i = e.length;
while (i--) {
callback(e[i]);
}
}
/**
* Removes current entities from layer and adds new entities.
* @public
* @param {Array.<og.Entity>} entities - New entity array.
*/
setEntities(entities) {
this.clear();
var e = this._extent = new Extent(new LonLat(180, 90), new LonLat(-180, -90));
this._entities = new Array(entities.length);
var entitiesForTree = [];
for (var i = 0; i < entities.length; i++) {
var ei = entities[i];
ei._layer = this;
ei._layerIndex = i;
if (ei.polyline) {
this._polylineEntityCollection.add(ei);
} else if (ei.billboard || ei.label || ei.shape) {
entitiesForTree.push(ei);
}
if (ei.geometry) {
if (this._planet) {
this._planet.renderer.assignPickingColor(ei);
this._geometryHandler.add(ei.geometry);
}
}
this._entities[i] = ei;
var ext = ei.getExtent();
if (ext.northEast.lon > e.northEast.lon) e.northEast.lon = ext.northEast.lon;
if (ext.northEast.lat > e.northEast.lat) e.northEast.lat = ext.northEast.lat;
if (ext.southWest.lon < e.southWest.lon) e.southWest.lon = ext.southWest.lon;
if (ext.southWest.lat < e.southWest.lat) e.southWest.lat = ext.southWest.lat;
}
this._createEntityCollectionsTree(entitiesForTree);
return this;
}
_createEntityCollectionsTree(entitiesForTree) {
if (this._planet) {
this._entityCollectionsTree = new EntityCollectionNode(this, quadTree.NW, null, 0,
Extent.createFromArray([-20037508.34, -20037508.34, 20037508.34, 20037508.34]), this._planet, 0);
this._entityCollectionsTreeNorth = new EntityCollectionNodeWGS84(this, quadTree.NW, null, 0,
Extent.createFromArray([-180, mercator.MAX_LAT, 180, 90]), this._planet, 0);
this._entityCollectionsTreeSouth = new EntityCollectionNodeWGS84(this, quadTree.NW, null, 0,
Extent.createFromArray([-180, -90, 180, mercator.MIN_LAT]), this._planet, 0);
this._entityCollectionsTree.buildTree(entitiesForTree);
this._entityCollectionsTreeNorth.buildTree(entitiesForTree);
this._entityCollectionsTreeSouth.buildTree(entitiesForTree);
}
}
_bindEventsDefault(entityCollection) {
var ve = this.events;
entityCollection.events.on("entitymove", function (e) {
ve.dispatch(ve.entitymove, e);
});
entityCollection.events.on("mousemove", function (e) {
ve.dispatch(ve.mousemove, e);
});
entityCollection.events.on("mouseenter", function (e) {
ve.dispatch(ve.mouseenter, e);
});
entityCollection.events.on("mouseleave", function (e) {
ve.dispatch(ve.mouseleave, e);
});
entityCollection.events.on("lclick", function (e) {
ve.dispatch(ve.lclick, e);
});
entityCollection.events.on("rclick", function (e) {
ve.dispatch(ve.rclick, e);
});
entityCollection.events.on("mclick", function (e) {
ve.dispatch(ve.mclick, e);
});
entityCollection.events.on("ldblclick", function (e) {
ve.dispatch(ve.ldblclick, e);
});
entityCollection.events.on("rdblclick", function (e) {
ve.dispatch(ve.rdblclick, e);
});
entityCollection.events.on("mdblclick", function (e) {
ve.dispatch(ve.mdblclick, e);
});
entityCollection.events.on("lup", function (e) {
ve.dispatch(ve.lup, e);
});
entityCollection.events.on("rup", function (e) {
ve.dispatch(ve.rup, e);
});
entityCollection.events.on("mup", function (e) {
ve.dispatch(ve.mup, e);
});
entityCollection.events.on("ldown", function (e) {
ve.dispatch(ve.ldown, e);
});
entityCollection.events.on("rdown", function (e) {
ve.dispatch(ve.rdown, e);
});
entityCollection.events.on("mdown", function (e) {
ve.dispatch(ve.mdown, e);
});
entityCollection.events.on("lhold", function (e) {
ve.dispatch(ve.lhold, e);
});
entityCollection.events.on("rhold", function (e) {
ve.dispatch(ve.rhold, e);
});
entityCollection.events.on("mhold", function (e) {
ve.dispatch(ve.mhold, e);
});
entityCollection.events.on("mousewheel", function (e) {
ve.dispatch(ve.mousewheel, e);
});
entityCollection.events.on("touchmove", function (e) {
ve.dispatch(ve.touchmove, e);
});
entityCollection.events.on("touchstart", function (e) {
ve.dispatch(ve.touchstart, e);
});
entityCollection.events.on("touchend", function (e) {
ve.dispatch(ve.touchend, e);
});
entityCollection.events.on("doubletouch", function (e) {
ve.dispatch(ve.doubletouch, e);
});
entityCollection.events.on("touchleave", function (e) {
ve.dispatch(ve.touchleave, e);
});
entityCollection.events.on("touchenter", function (e) {
ve.dispatch(ve.touchenter, e);
});
}
_collectPolylineCollectionPASS(outArr) {
outArr.push(this._polylineEntityCollection);
if (this.clampToGround || this.relativeToGround) {
var rtg = this.relativeToGround;
var nodes = this._planet._renderedNodes;
var visibleExtent = this._planet.getViewExtent();
var e = this._polylineEntityCollection._entities;
var e_i = e.length;
while (e_i--) {
var p = e[e_i].polyline;
if (visibleExtent.overlaps(p._extent)) {
var coords = p._pathLonLatMerc;
var c_j = coords.length;
while (c_j--) {
var c_j_h = coords[c_j].length;
while (c_j_h--) {
var ll = coords[c_j][c_j_h];
var n_k = nodes.length;
while (n_k--) {
var seg = nodes[n_k].segment;
if (seg._extent.isInside(ll)) {
var cart = p._path3v[c_j][c_j_h];
var res = new Vec3();
seg.getTerrainPoint(res, cart, ll);
p.setPoint3v(res.addA(res.normal().scale(rtg && p.altitude + 1.0)), c_j_h, c_j, true);
break;
}
}
}
}
}
}
}
}
collectVisibleCollections(outArr) {
var p = this._planet;
if (this.minZoom <= this._planet.maxCurrZoom && this.maxZoom >= p.maxCurrZoom) {
this._renderingNodes = {};
this._renderingNodesNorth = {};
this._renderingNodesSouth = {};
//Common collection first
this._collectPolylineCollectionPASS(outArr);
//Merc nodes
this._secondPASS = [];
this._entityCollectionsTree.collectRenderCollectionsPASS1(p._visibleNodes, outArr);
var i = this._secondPASS.length;
while (i--) {
this._secondPASS[i].collectRenderCollectionsPASS2(p._visibleNodes, outArr, this._secondPASS[i].nodeId);
}
//North nodes
this._secondPASS = [];
this._entityCollectionsTreeNorth.collectRenderCollectionsPASS1(p._visibleNodesNorth, outArr);
i = this._secondPASS.length;
while (i--) {
this._secondPASS[i].collectRenderCollectionsPASS2(p._visibleNodesNorth, outArr, this._secondPASS[i].nodeId);
}
//South nodes
this._secondPASS = [];
this._entityCollectionsTreeSouth.collectRenderCollectionsPASS1(p._visibleNodesSouth, outArr);
i = this._secondPASS.length;
while (i--) {
this._secondPASS[i].collectRenderCollectionsPASS2(p._visibleNodesSouth, outArr, this._secondPASS[i].nodeId);
}
}
}
_queueDeferredNode(node) {
if (this._visibility) {
node._inTheQueue = true;
if (this._counter >= 1) {
this._deferredEntitiesPendingQueue.push(node);
} else {
this._execDeferredNode(node);
}
}
}
_execDeferredNode(node) {
this._counter++;
var that = this;
setTimeout(function () {
node.applyCollection();
that._counter--;
if (that._deferredEntitiesPendingQueue.length && that._counter < 1) {
while (that._deferredEntitiesPendingQueue.length) {
var n = that._deferredEntitiesPendingQueue.pop();
n._inTheQueue = false;
if (n.isVisible()) {
that._execDeferredNode(node);
return;
}
}
}
}, 0);
}
/**
* Start to load tile material.
* @public
* @virtual
* @param {og.Segment.Material} material - Current material.
*/
loadMaterial(material) {
var seg = material.segment;
if (this._isBaseLayer) {
material.texture = seg._isNorth ? seg.planet.solidTextureOne : seg.planet.solidTextureTwo;
} else {
material.texture = seg.planet.transparentTexture;
}
if (this._planet.layerLock.isFree()) {
material.isReady = false;
material.isLoading = true;
this._planet._vectorTileCreator.add(material);
}
}
/**
* Abort exact material loading.
* @public
* @param {og.planetSegment.Material} material - Segment material.
*/
abortMaterialLoading(material) {
material.isLoading = false;
material.isReady = false;
}
applyMaterial(material) {
if (material.isReady) {
return [0, 0, 1, 1];
} else {
!material.isLoading && this.loadMaterial(material);
var segment = material.segment;
var pn = segment.node,
notEmpty = false;
var mId = this._id;
var psegm = material;
var i = 0;
while (pn.parentNode && i < 2) {
if (psegm && psegm.isReady) {
notEmpty = true;
break;
}
pn = pn.parentNode;
psegm = pn.segment.materials[mId];
}
if (notEmpty) {
material.appliedNodeId = pn.nodeId;
material.texture = psegm.texture;
material.pickingMask = psegm.pickingMask;
var dZ2 = 1.0 / (2 << (segment.tileZoom - pn.segment.tileZoom - 1));
return [
segment.tileX * dZ2 - pn.segment.tileX,
segment.tileY * dZ2 - pn.segment.tileY,
dZ2,
dZ2
];
} else {
if (material.textureExists && material._updateTexture) {
material.texture = material._updateTexture;
material.pickingMask = material._updatePickingMask;
} else {
material.texture = segment.planet.transparentTexture;
material.pickingMask = segment.planet.transparentTexture;
}
return [0, 0, 1, 1];
}
}
}
clearMaterial(material) {
if (material.isReady) {
var gl = material.segment.handler.gl;
material.isReady = false;
material.pickingReady = false;
var t = material.texture;
material.texture = null;
t && !t.default && gl.deleteTexture(t);
t = material.pickingMask;
material.pickingMask = null;
t && !t.default && gl.deleteTexture(t);
t = material._updateTexture;
material._updateTexture = null;
t && !t.default && gl.deleteTexture(t);
t = material._updatePickingMask;
material._updatePickingMask = null;
t && !t.default && gl.deleteTexture(t);
}
this.abortMaterialLoading(material);
material.isLoading = false;
material.textureExists = false;
}
update() {
this._geometryHandler.update();
this.collectVisibleCollections(this._planet._frustumEntityCollections);
this.events.dispatch(this.events.draw, this);
}
};
const EVENT_NAMES = [
/**
* Triggered when entity has moved.
* @event og.layer.Vector#draw
*/
"entitymove",
/**
* Triggered when layer begin draw.
* @event og.layer.Vector#draw
*/
"draw",
/**
* Triggered when new entity added to the layer.
* @event og.layer.Vector#entityadd
*/
"entityadd",
/**
* Triggered when entity removes from the collection.
* @event og.layer.Vector#entityremove
*/
"entityremove"
];
export { Vector };

Some files were not shown because too many files have changed in this diff Show More