123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169 |
- var mode = {
- N_POLE: 0,
- S_POLE: 1,
- EQUIT: 2,
- OBLIQ: 3
- };
- import { D2R, HALF_PI, EPSLN } from "../constants/values";
- import hypot from "../common/hypot";
- var params = {
- h: { def: 100000, num: true }, // default is Karman line, no default in PROJ.7
- azi: { def: 0, num: true, degrees: true }, // default is North
- tilt: { def: 0, num: true, degrees: true }, // default is Nadir
- long0: { def: 0, num: true }, // default is Greenwich, conversion to rad is automatic
- lat0: { def: 0, num: true } // default is Equator, conversion to rad is automatic
- };
- export function init() {
- Object.keys(params).forEach(function (p) {
- if (typeof this[p] === "undefined") {
- this[p] = params[p].def;
- } else if (params[p].num && isNaN(this[p])) {
- throw new Error("Invalid parameter value, must be numeric " + p + " = " + this[p]);
- } else if (params[p].num) {
- this[p] = parseFloat(this[p]);
- }
- if (params[p].degrees) {
- this[p] = this[p] * D2R;
- }
- }.bind(this));
- if (Math.abs((Math.abs(this.lat0) - HALF_PI)) < EPSLN) {
- this.mode = this.lat0 < 0 ? mode.S_POLE : mode.N_POLE;
- } else if (Math.abs(this.lat0) < EPSLN) {
- this.mode = mode.EQUIT;
- } else {
- this.mode = mode.OBLIQ;
- this.sinph0 = Math.sin(this.lat0);
- this.cosph0 = Math.cos(this.lat0);
- }
- this.pn1 = this.h / this.a; // Normalize relative to the Earth's radius
- if (this.pn1 <= 0 || this.pn1 > 1e10) {
- throw new Error("Invalid height");
- }
-
- this.p = 1 + this.pn1;
- this.rp = 1 / this.p;
- this.h1 = 1 / this.pn1;
- this.pfact = (this.p + 1) * this.h1;
- this.es = 0;
- var omega = this.tilt;
- var gamma = this.azi;
- this.cg = Math.cos(gamma);
- this.sg = Math.sin(gamma);
- this.cw = Math.cos(omega);
- this.sw = Math.sin(omega);
- }
- export function forward(p) {
- p.x -= this.long0;
- var sinphi = Math.sin(p.y);
- var cosphi = Math.cos(p.y);
- var coslam = Math.cos(p.x);
- var x, y;
- switch (this.mode) {
- case mode.OBLIQ:
- y = this.sinph0 * sinphi + this.cosph0 * cosphi * coslam;
- break;
- case mode.EQUIT:
- y = cosphi * coslam;
- break;
- case mode.S_POLE:
- y = -sinphi;
- break;
- case mode.N_POLE:
- y = sinphi;
- break;
- }
- y = this.pn1 / (this.p - y);
- x = y * cosphi * Math.sin(p.x);
- switch (this.mode) {
- case mode.OBLIQ:
- y *= this.cosph0 * sinphi - this.sinph0 * cosphi * coslam;
- break;
- case mode.EQUIT:
- y *= sinphi;
- break;
- case mode.N_POLE:
- y *= -(cosphi * coslam);
- break;
- case mode.S_POLE:
- y *= cosphi * coslam;
- break;
- }
- // Tilt
- var yt, ba;
- yt = y * this.cg + x * this.sg;
- ba = 1 / (yt * this.sw * this.h1 + this.cw);
- x = (x * this.cg - y * this.sg) * this.cw * ba;
- y = yt * ba;
- p.x = x * this.a;
- p.y = y * this.a;
- return p;
- }
- export function inverse(p) {
- p.x /= this.a;
- p.y /= this.a;
- var r = { x: p.x, y: p.y };
- // Un-Tilt
- var bm, bq, yt;
- yt = 1 / (this.pn1 - p.y * this.sw);
- bm = this.pn1 * p.x * yt;
- bq = this.pn1 * p.y * this.cw * yt;
- p.x = bm * this.cg + bq * this.sg;
- p.y = bq * this.cg - bm * this.sg;
- var rh = hypot(p.x, p.y);
- if (Math.abs(rh) < EPSLN) {
- r.x = 0;
- r.y = p.y;
- } else {
- var cosz, sinz;
- sinz = 1 - rh * rh * this.pfact;
- sinz = (this.p - Math.sqrt(sinz)) / (this.pn1 / rh + rh / this.pn1);
- cosz = Math.sqrt(1 - sinz * sinz);
- switch (this.mode) {
- case mode.OBLIQ:
- r.y = Math.asin(cosz * this.sinph0 + p.y * sinz * this.cosph0 / rh);
- p.y = (cosz - this.sinph0 * Math.sin(r.y)) * rh;
- p.x *= sinz * this.cosph0;
- break;
- case mode.EQUIT:
- r.y = Math.asin(p.y * sinz / rh);
- p.y = cosz * rh;
- p.x *= sinz;
- break;
- case mode.N_POLE:
- r.y = Math.asin(cosz);
- p.y = -p.y;
- break;
- case mode.S_POLE:
- r.y = -Math.asin(cosz);
- break;
- }
- r.x = Math.atan2(p.x, p.y);
- }
- p.x = r.x + this.long0;
- p.y = r.y;
- return p;
- }
- export var names = ["Tilted_Perspective", "tpers"];
- export default {
- init: init,
- forward: forward,
- inverse: inverse,
- names: names
- };
|