mirror of
https://github.com/openglobus/openglobus.git
synced 2025-12-08 19:25:27 +00:00
remove globus
This commit is contained in:
parent
f2783e2876
commit
be25af6bef
170
src/og/Clock.js
170
src/og/Clock.js
@ -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 };
|
||||
170
src/og/Events.js
170
src/og/Events.js
@ -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 };
|
||||
316
src/og/Extent.js
316
src/og/Extent.js
@ -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 };
|
||||
@ -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 };
|
||||
258
src/og/Globe.js
258
src/og/Globe.js
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
175
src/og/LonLat.js
175
src/og/LonLat.js
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
214
src/og/ajax.js
214
src/og/ajax.js
@ -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 };
|
||||
@ -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;
|
||||
};
|
||||
@ -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;
|
||||
};
|
||||
@ -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);
|
||||
@ -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;
|
||||
};
|
||||
@ -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;
|
||||
};
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
170
src/og/clock.js
170
src/og/clock.js
@ -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 };
|
||||
109
src/og/cons.js
109
src/og/cons.js
@ -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();
|
||||
|
||||
@ -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 };
|
||||
@ -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 = " ";
|
||||
for (var i = dl; i < fixed; i++) {
|
||||
white += ' ';
|
||||
}
|
||||
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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 = " ";
|
||||
for (var i = dl; i < fixed; i++) {
|
||||
white += ' ';
|
||||
}
|
||||
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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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);
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
164
src/og/index.js
164
src/og/index.js
@ -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
|
||||
};
|
||||
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* @module og/inherits
|
||||
*/
|
||||
|
||||
export function inherits(childCtor, parentCtor) {
|
||||
childCtor.prototype = Object.create(parentCtor.prototype);
|
||||
childCtor.prototype.constructor = childCtor;
|
||||
};
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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
|
||||
};
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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 };
|
||||
@ -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
Loading…
x
Reference in New Issue
Block a user