@openglobus/og 0.16.3 → 0.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/css/og.css +24 -2
- package/dist/@openglobus/og.css +1 -1
- package/dist/@openglobus/og.esm.js +2 -2
- package/dist/@openglobus/og.esm.js.map +1 -1
- package/dist/@openglobus/og.umd.js +2 -2
- package/dist/@openglobus/og.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/og/Clock.js +1 -5
- package/src/og/Events.js +2 -6
- package/src/og/Extent.js +5 -9
- package/src/og/Globe.js +93 -56
- package/src/og/ImageCanvas.js +13 -6
- package/src/og/Lock.js +44 -48
- package/src/og/LonLat.js +1 -5
- package/src/og/Object3d.js +2 -2
- package/src/og/QueueArray.js +1 -1
- package/src/og/Stack.js +49 -53
- package/src/og/astro/earth.js +112 -116
- package/src/og/astro/jd.js +514 -518
- package/src/og/astro/orbit.js +119 -123
- package/src/og/astro/rotation.js +36 -40
- package/src/og/bv/Box.js +77 -81
- package/src/og/bv/Sphere.js +57 -61
- package/src/og/camera/Camera.js +20 -7
- package/src/og/camera/Frustum.js +4 -4
- package/src/og/camera/PlanetCamera.js +15 -22
- package/src/og/cons.js +1 -1
- package/src/og/control/Atmosphere.js +0 -4
- package/src/og/control/Control.js +9 -8
- package/src/og/control/DebugInfo.js +3 -7
- package/src/og/control/DrawingSwitcher.js +117 -0
- package/src/og/control/EarthCoordinates.js +214 -214
- package/src/og/control/EarthNavigation.js +6 -13
- package/src/og/control/GeoImageDragControl.js +0 -4
- package/src/og/control/KeyboardNavigation.js +0 -4
- package/src/og/control/LayerAnimation.js +0 -4
- package/src/og/control/LayerSwitcher.js +2 -4
- package/src/og/control/Lighting.js +12 -16
- package/src/og/control/MouseNavigation.js +1 -5
- package/src/og/control/MouseWheelZoomControl.js +0 -4
- package/src/og/control/RulerSwitcher.js +0 -4
- package/src/og/control/ScaleControl.js +2 -6
- package/src/og/control/ShowFps.js +40 -44
- package/src/og/control/SimpleNavigation.js +10 -10
- package/src/og/control/SimpleSkyBackground.js +0 -4
- package/src/og/control/Sun.js +0 -4
- package/src/og/control/ToggleWireframe.js +35 -39
- package/src/og/control/ZoomControl.js +0 -4
- package/src/og/control/drawing/DrawingControl.js +51 -0
- package/src/og/control/drawing/LineStringDrawingScene.js +203 -0
- package/src/og/control/drawing/PolygonDrawingScene.js +785 -0
- package/src/og/control/elevationProfile/ElevationProfile.js +275 -0
- package/src/og/control/index.js +5 -1
- package/src/og/control/ruler/Ruler.js +0 -4
- package/src/og/control/ruler/RulerScene.js +3 -2
- package/src/og/control/selection/Selection.js +0 -4
- package/src/og/control/selection/SelectionScene.js +2 -4
- package/src/og/control/timeline/TimelineControl.js +4 -4
- package/src/og/control/timeline/TimelineModel.js +2 -2
- package/src/og/control/timeline/TimelineView.js +1 -0
- package/src/og/control/visibleExtent/Segment.js +7 -7
- package/src/og/control/visibleExtent/drawnode.js +0 -4
- package/src/og/ellipsoid/Ellipsoid.js +236 -325
- package/src/og/ellipsoid/wgs84.js +0 -4
- package/src/og/entity/BaseBillboard.js +375 -379
- package/src/og/entity/Billboard.js +0 -4
- package/src/og/entity/BillboardHandler.js +3 -7
- package/src/og/entity/Entity.js +22 -22
- package/src/og/entity/EntityCollection.js +14 -18
- package/src/og/entity/GeoObject.js +6 -8
- package/src/og/entity/GeoObjectHandler.js +30 -24
- package/src/og/entity/Geometry.js +5 -4
- package/src/og/entity/GeometryHandler.js +18 -19
- package/src/og/entity/Label.js +0 -4
- package/src/og/entity/LabelHandler.js +10 -14
- package/src/og/entity/LabelWorker.js +1 -1
- package/src/og/entity/PointCloud.js +2 -6
- package/src/og/entity/PointCloudHandler.js +122 -126
- package/src/og/entity/Polyline.js +15 -17
- package/src/og/entity/PolylineHandler.js +104 -108
- package/src/og/entity/Ray.js +29 -29
- package/src/og/entity/RayHandler.js +2 -2
- package/src/og/entity/Strip.js +1 -1
- package/src/og/entity/StripHandler.js +2 -2
- package/src/og/index.js +3 -1
- package/src/og/input/KeyboardHandler.js +128 -132
- package/src/og/input/MouseHandler.js +94 -98
- package/src/og/input/TouchHandler.js +59 -63
- package/src/og/input/input.js +44 -48
- package/src/og/layer/BaseGeoImage.js +6 -9
- package/src/og/layer/CanvasTiles.js +1 -5
- package/src/og/layer/GeoImage.js +0 -4
- package/src/og/layer/GeoTexture2d.js +0 -4
- package/src/og/layer/GeoVideo.js +0 -4
- package/src/og/layer/KML.js +1 -0
- package/src/og/layer/Layer.js +22 -26
- package/src/og/layer/Material.js +0 -4
- package/src/og/layer/Vector.js +25 -22
- package/src/og/layer/WMS.js +182 -186
- package/src/og/layer/XYZ.js +0 -4
- package/src/og/light/LightSource.js +0 -4
- package/src/og/math/Line2.js +28 -32
- package/src/og/math/Mat3.js +152 -156
- package/src/og/math/Ray.js +0 -4
- package/src/og/math/Vec2.js +0 -4
- package/src/og/math/Vec3.js +5 -4
- package/src/og/math/Vec4.js +0 -4
- package/src/og/math/coder.js +104 -104
- package/src/og/math.js +42 -10
- package/src/og/mercator.js +1 -1
- package/src/og/proj/EPSG3857.js +13 -13
- package/src/og/proj/Proj.js +59 -63
- package/src/og/quadTree/EPSG4326QuadTreeStrategy.js +1 -0
- package/src/og/quadTree/EarthQuadTreeStrategy.js +1 -0
- package/src/og/quadTree/EntityCollectionNode.js +12 -16
- package/src/og/quadTree/MarsQuadTreeStrategy.js +1 -0
- package/src/og/quadTree/Node.js +15 -14
- package/src/og/quadTree/QuadTreeStrategy.js +1 -0
- package/src/og/quadTree/Wgs84QuadTreeStrategy.js +1 -0
- package/src/og/renderer/Renderer.js +114 -27
- package/src/og/renderer/RendererEvents.js +0 -4
- package/src/og/scene/Axes.js +74 -78
- package/src/og/scene/BaseNode.js +1 -5
- package/src/og/scene/Planet.js +127 -130
- package/src/og/scene/RenderNode.js +20 -12
- package/src/og/scene/SkyBox.js +104 -108
- package/src/og/segment/Segment.js +10 -6
- package/src/og/segment/SegmentLonLat.js +3 -7
- package/src/og/segment/segmentHelper.js +229 -225
- package/src/og/shaders/atmos.js +1 -1
- package/src/og/shaders/billboard.js +0 -4
- package/src/og/shaders/drawnode.js +5 -9
- package/src/og/shaders/geoObject.js +0 -4
- package/src/og/shaders/label.js +0 -4
- package/src/og/shaders/pickingMask.js +0 -4
- package/src/og/shaders/pointCloud.js +0 -4
- package/src/og/shaders/polyline.js +0 -4
- package/src/og/shaders/ray.js +0 -4
- package/src/og/shaders/skybox.js +0 -4
- package/src/og/terrain/EmptyTerrain.js +0 -4
- package/src/og/utils/FontAtlas.js +0 -4
- package/src/og/utils/GeoImageCreator.js +2 -3
- package/src/og/utils/NormalMapCreator.js +11 -12
- package/src/og/utils/PlainSegmentWorker.js +9 -9
- package/src/og/utils/TerrainWorker.js +2 -2
- package/src/og/utils/TextureAtlas.js +1 -1
- package/src/og/utils/VectorTileCreator.js +3 -9
- package/src/og/utils/earcut.js +8 -8
- package/src/og/utils/shared.js +30 -11
- package/src/og/webgl/Framebuffer.js +2 -6
- package/src/og/webgl/Handler.js +46 -20
- package/src/og/webgl/Multisample.js +2 -6
- package/src/og/webgl/Program.js +4 -8
- package/src/og/webgl/ProgramController.js +2 -2
- package/types/Clock.d.ts +1 -1
- package/types/Extent.d.ts +5 -5
- package/types/Globe.d.ts +15 -1
- package/types/ImageCanvas.d.ts +5 -0
- package/types/bv/Box.d.ts +1 -1
- package/types/bv/Sphere.d.ts +3 -3
- package/types/camera/Camera.d.ts +3 -2
- package/types/camera/PlanetCamera.d.ts +4 -4
- package/types/control/DrawingSwitcher.d.ts +13 -0
- package/types/control/EarthCoordinates.d.ts +1 -1
- package/types/control/Lighting.d.ts +8 -8
- package/types/control/drawing/DrawingControl.d.ts +14 -0
- package/types/control/drawing/LineStringDrawingScene.d.ts +5 -0
- package/types/control/drawing/PolygonDrawingScene.d.ts +99 -0
- package/types/control/index.d.ts +3 -1
- package/types/control/ruler/RulerScene.d.ts +0 -1
- package/types/control/selection/SelectionScene.d.ts +0 -1
- package/types/ellipsoid/Ellipsoid.d.ts +53 -64
- package/types/entity/Entity.d.ts +3 -2
- package/types/entity/GeoObject.d.ts +1 -2
- package/types/entity/Geometry.d.ts +5 -0
- package/types/entity/Polyline.d.ts +1 -1
- package/types/entity/Ray.d.ts +1 -0
- package/types/index.d.ts +1 -0
- package/types/layer/BaseGeoImage.d.ts +1 -1
- package/types/layer/CanvasTiles.d.ts +1 -1
- package/types/layer/Layer.d.ts +1 -1
- package/types/layer/Vector.d.ts +1 -0
- package/types/math/Vec3.d.ts +2 -0
- package/types/math.d.ts +7 -0
- package/types/renderer/Renderer.d.ts +7 -1
- package/types/scene/Axes.d.ts +0 -1
- package/types/scene/Planet.d.ts +27 -26
- package/types/scene/RenderNode.d.ts +2 -0
- package/types/scene/SkyBox.d.ts +0 -1
- package/types/segment/Segment.d.ts +3 -2
- package/types/segment/SegmentLonLat.d.ts +0 -1
- package/types/utils/GeoImageCreator.d.ts +1 -1
- package/types/utils/NormalMapCreator.d.ts +1 -1
- package/types/utils/VectorTileCreator.d.ts +2 -2
- package/types/utils/shared.d.ts +2 -0
- package/types/webgl/Handler.d.ts +6 -4
|
@@ -1,12 +1,9 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @module og/ellipsoid/Ellipsoid
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
1
|
"use strict";
|
|
6
2
|
|
|
7
3
|
import { LonLat } from "../LonLat.js";
|
|
8
4
|
import { DEGREES, EPS1, EPS12, EPS15, RADIANS, zeroTwoPI } from "../math.js";
|
|
9
5
|
import { Vec3 } from "../math/Vec3.js";
|
|
6
|
+
import { Quat } from "../math/Quat.js";
|
|
10
7
|
|
|
11
8
|
/**
|
|
12
9
|
* Class represents a plant ellipsoid.
|
|
@@ -37,40 +34,14 @@ class Ellipsoid {
|
|
|
37
34
|
this._k = qa2b2 / polarSize;
|
|
38
35
|
this._k2 = this._k * this._k;
|
|
39
36
|
|
|
40
|
-
this._radii = new Vec3(equatorialSize,
|
|
41
|
-
this._radii2 = new Vec3(this._a2, this.
|
|
42
|
-
this._invRadii = new Vec3(1.0 / equatorialSize, 1.0 /
|
|
43
|
-
this._invRadii2 = new Vec3(1.0 / this._a2, 1.0 / this.
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
/**
|
|
47
|
-
* Returns angle between to bearin angles
|
|
48
|
-
* @param {number} a - First bearing angle
|
|
49
|
-
* @param {number} b - Second bearing angle
|
|
50
|
-
* @returns {number}
|
|
51
|
-
*/
|
|
52
|
-
static getAngleBetweenTwoBearings(a, b) {
|
|
53
|
-
a = zeroTwoPI(a);
|
|
54
|
-
b = zeroTwoPI(b);
|
|
55
|
-
return ((((a - b) % 360) + 360 + 180) % 360) - 180;
|
|
56
|
-
}
|
|
57
|
-
|
|
58
|
-
static getRelativeBearing(a, b) {
|
|
59
|
-
let a_y = Math.cos(a),
|
|
60
|
-
a_x = Math.sin(a),
|
|
61
|
-
b_y = Math.cos(b),
|
|
62
|
-
b_x = Math.sin(b);
|
|
63
|
-
let c = a_y * b_x - b_y * a_x,
|
|
64
|
-
d = a_x * b_x + a_y * b_y;
|
|
65
|
-
if (c > 0.0) {
|
|
66
|
-
return Math.acos(d);
|
|
67
|
-
}
|
|
68
|
-
return -Math.acos(d);
|
|
37
|
+
this._radii = new Vec3(equatorialSize, equatorialSize, polarSize);
|
|
38
|
+
this._radii2 = new Vec3(this._a2, this._a2, this._b2);
|
|
39
|
+
this._invRadii = new Vec3(1.0 / equatorialSize, 1.0 / equatorialSize, 1.0 / polarSize);
|
|
40
|
+
this._invRadii2 = new Vec3(1.0 / this._a2, 1.0 / this._a2, 1.0 / this._b2);
|
|
69
41
|
}
|
|
70
42
|
|
|
71
43
|
/**
|
|
72
44
|
* Returns the distance travelling from ‘this’ point to destination point along a rhumb line.
|
|
73
|
-
*
|
|
74
45
|
* @param {LonLat} start coordinates.
|
|
75
46
|
* @param {LonLat} end coordinates
|
|
76
47
|
* @returns {number} Distance in m between this point and destination point (same units as radius).
|
|
@@ -87,30 +58,6 @@ class Ellipsoid {
|
|
|
87
58
|
return t * this._a;
|
|
88
59
|
}
|
|
89
60
|
|
|
90
|
-
/**
|
|
91
|
-
* Returns the midpoint between two points on the great circle.
|
|
92
|
-
* @param {LonLat} lonLat1 - Longitude/latitude of first point.
|
|
93
|
-
* @param {LonLat} lonLat2 - Longitude/latitude of second point.
|
|
94
|
-
* @return {LonLat} Midpoint between points.
|
|
95
|
-
*/
|
|
96
|
-
static getMiddlePointOnGreatCircle(lonLat1, lonLat2) {
|
|
97
|
-
var f1 = lonLat1.lat * RADIANS,
|
|
98
|
-
l1 = lonLat1.lon * RADIANS;
|
|
99
|
-
var f2 = lonLat2.lat * RADIANS;
|
|
100
|
-
var dl = (lonLat2.lon - lonLat1.lon) * RADIANS;
|
|
101
|
-
|
|
102
|
-
var Bx = Math.cos(f2) * Math.cos(dl);
|
|
103
|
-
var By = Math.cos(f2) * Math.sin(dl);
|
|
104
|
-
|
|
105
|
-
var x = Math.sqrt((Math.cos(f1) + Bx) * (Math.cos(f1) + Bx) + By * By);
|
|
106
|
-
var y = Math.sin(f1) + Math.sin(f2);
|
|
107
|
-
var f3 = Math.atan2(y, x);
|
|
108
|
-
|
|
109
|
-
var l3 = l1 + Math.atan2(By, Math.cos(f1) + Bx);
|
|
110
|
-
|
|
111
|
-
return new LonLat(((l3 * DEGREES + 540) % 360) - 180, f3 * DEGREES);
|
|
112
|
-
}
|
|
113
|
-
|
|
114
61
|
/**
|
|
115
62
|
* Returns the point at given fraction between two points on the great circle.
|
|
116
63
|
* @param {LonLat} lonLat1 - Longitude/Latitude of source point.
|
|
@@ -118,57 +65,23 @@ class Ellipsoid {
|
|
|
118
65
|
* @param {number} fraction - Fraction between the two points (0 = source point, 1 = destination point).
|
|
119
66
|
* @returns {LonLat} Intermediate point between points.
|
|
120
67
|
*/
|
|
121
|
-
|
|
122
|
-
var f1 = lonLat1.lat * RADIANS,
|
|
123
|
-
l1 = lonLat1.lon * RADIANS;
|
|
124
|
-
var f2 = lonLat2.lat * RADIANS,
|
|
125
|
-
l2 = lonLat2.lon * RADIANS;
|
|
126
|
-
|
|
127
|
-
var sinf1 = Math.sin(f1),
|
|
128
|
-
cosf1 = Math.cos(f1),
|
|
129
|
-
sinl1 = Math.sin(l1),
|
|
130
|
-
cosl1 = Math.cos(l1);
|
|
131
|
-
var sinf2 = Math.sin(f2),
|
|
132
|
-
cosf2 = Math.cos(f2),
|
|
133
|
-
sinl2 = Math.sin(l2),
|
|
134
|
-
cosl2 = Math.cos(l2);
|
|
135
|
-
|
|
136
|
-
var df = f2 - f1,
|
|
137
|
-
dl = l2 - l1;
|
|
138
|
-
var a =
|
|
139
|
-
Math.sin(df / 2) * Math.sin(df / 2) +
|
|
140
|
-
Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2);
|
|
141
|
-
var d = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
142
|
-
|
|
143
|
-
var A = Math.sin((1 - fraction) * d) / Math.sin(d);
|
|
144
|
-
var B = Math.sin(fraction * d) / Math.sin(d);
|
|
145
|
-
|
|
146
|
-
var x = A * cosf1 * cosl1 + B * cosf2 * cosl2;
|
|
147
|
-
var y = A * cosf1 * sinl1 + B * cosf2 * sinl2;
|
|
148
|
-
var z = A * sinf1 + B * sinf2;
|
|
68
|
+
getIntermediatePointOnGreatCircle(lonLat1, lonLat2, fraction) {
|
|
149
69
|
|
|
150
|
-
|
|
151
|
-
|
|
70
|
+
if (fraction == 0) return lonLat1.clone();
|
|
71
|
+
if (fraction == 1) return lonLat2.clone();
|
|
152
72
|
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
var dLon = (lonLat2.lon - lonLat1.lon) * RADIANS;
|
|
158
|
-
var dPhi = Math.log(
|
|
159
|
-
Math.tan((lonLat2.lat * RADIANS) / 2 + Math.PI / 4) /
|
|
160
|
-
Math.tan((lonLat1.lat * RADIANS) / 2 + Math.PI / 4)
|
|
161
|
-
);
|
|
162
|
-
if (Math.abs(dLon) > Math.PI) {
|
|
163
|
-
if (dLon > 0) {
|
|
164
|
-
dLon = (2 * Math.PI - dLon) * -1;
|
|
165
|
-
} else {
|
|
166
|
-
dLon = 2 * Math.PI + dLon;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
return (Math.atan2(dLon, dPhi) * DEGREES + 360) % 360;
|
|
73
|
+
const inverse = this.inverse(lonLat1, lonLat2);
|
|
74
|
+
const dist = inverse.distance;
|
|
75
|
+
const azimuth = inverse.initialAzimuth;
|
|
76
|
+
return isNaN(azimuth) ? lonLat1 : this.getGreatCircleDestination(lonLat1, azimuth, dist * fraction);
|
|
170
77
|
}
|
|
171
78
|
|
|
79
|
+
/**
|
|
80
|
+
* REMOVE ASAP after
|
|
81
|
+
* @param lonLat1
|
|
82
|
+
* @param lonLat2
|
|
83
|
+
* @returns {number}
|
|
84
|
+
*/
|
|
172
85
|
static getBearing(lonLat1, lonLat2) {
|
|
173
86
|
var f1 = lonLat1.lat * RADIANS,
|
|
174
87
|
l1 = lonLat1.lon * RADIANS;
|
|
@@ -179,101 +92,8 @@ class Ellipsoid {
|
|
|
179
92
|
return Math.atan2(y, x) * DEGREES;
|
|
180
93
|
}
|
|
181
94
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
* @param {LonLat} lonLat1 - Longitude/latitude of source point.
|
|
185
|
-
* @param {LonLat} lonLat2 - Longitude/latitude of destination point.
|
|
186
|
-
* @return {number} Initial bearing in degrees from north.
|
|
187
|
-
*/
|
|
188
|
-
static getInitialBearing(lonLat1, lonLat2) {
|
|
189
|
-
var f1 = lonLat1.lat * RADIANS,
|
|
190
|
-
f2 = lonLat2.lat * RADIANS;
|
|
191
|
-
var dl = (lonLat2.lon - lonLat1.lon) * RADIANS;
|
|
192
|
-
var y = Math.sin(dl) * Math.cos(f2);
|
|
193
|
-
var x = Math.cos(f1) * Math.sin(f2) - Math.sin(f1) * Math.cos(f2) * Math.cos(dl);
|
|
194
|
-
var D = Math.atan2(y, x);
|
|
195
|
-
return (D * DEGREES + 360) % 360;
|
|
196
|
-
}
|
|
197
|
-
|
|
198
|
-
/**
|
|
199
|
-
* Returns the point of intersection of two paths defined by point and bearing.
|
|
200
|
-
* @param {LonLat} p1 - First point.
|
|
201
|
-
* @param {number} brng1 - Initial bearing from first point.
|
|
202
|
-
* @param {LonLat} p2 - Second point.
|
|
203
|
-
* @param {number} brng2 - Initial bearing from second point.
|
|
204
|
-
* @return {LonLat|null} Destination point (null if no unique intersection defined).
|
|
205
|
-
*/
|
|
206
|
-
static intersection(p1, brng1, p2, brng2) {
|
|
207
|
-
var f1 = p1.lat * RADIANS,
|
|
208
|
-
l1 = p1.lon * RADIANS;
|
|
209
|
-
var f2 = p2.lat * RADIANS,
|
|
210
|
-
l2 = p2.lon * RADIANS;
|
|
211
|
-
var D13 = brng1 * RADIANS,
|
|
212
|
-
D23 = brng2 * RADIANS;
|
|
213
|
-
var df = f2 - f1,
|
|
214
|
-
dl = l2 - l1;
|
|
215
|
-
|
|
216
|
-
var d12 =
|
|
217
|
-
2 *
|
|
218
|
-
Math.asin(
|
|
219
|
-
Math.sqrt(
|
|
220
|
-
Math.sin(df / 2) * Math.sin(df / 2) +
|
|
221
|
-
Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2)
|
|
222
|
-
)
|
|
223
|
-
);
|
|
224
|
-
if (d12 == 0) return null;
|
|
225
|
-
|
|
226
|
-
// initial/final bearings between points
|
|
227
|
-
var Da = Math.acos(
|
|
228
|
-
(Math.sin(f2) - Math.sin(f1) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f1))
|
|
229
|
-
);
|
|
230
|
-
if (isNaN(Da)) Da = 0; // protect against rounding
|
|
231
|
-
var Db = Math.acos(
|
|
232
|
-
(Math.sin(f1) - Math.sin(f2) * Math.cos(d12)) / (Math.sin(d12) * Math.cos(f2))
|
|
233
|
-
);
|
|
234
|
-
|
|
235
|
-
var D12 = Math.sin(l2 - l1) > 0 ? Da : 2 * Math.PI - Da;
|
|
236
|
-
var D21 = Math.sin(l2 - l1) > 0 ? 2 * Math.PI - Db : Db;
|
|
237
|
-
|
|
238
|
-
var a1 = ((D13 - D12 + Math.PI) % (2 * Math.PI)) - Math.PI;
|
|
239
|
-
var a2 = ((D21 - D23 + Math.PI) % (2 * Math.PI)) - Math.PI;
|
|
240
|
-
|
|
241
|
-
if (Math.sin(a1) == 0 && Math.sin(a2) == 0) return null; // infinite intersections
|
|
242
|
-
if (Math.sin(a1) * Math.sin(a2) < 0) return null; // ambiguous intersection
|
|
243
|
-
|
|
244
|
-
// a1 = Math.abs(a1);
|
|
245
|
-
// a2 = Math.abs(a2);
|
|
246
|
-
// ... Ed Williams takes abs of a1/a2, but seems to break calculation?
|
|
247
|
-
|
|
248
|
-
var a3 = Math.acos(
|
|
249
|
-
-Math.cos(a1) * Math.cos(a2) + Math.sin(a1) * Math.sin(a2) * Math.cos(d12)
|
|
250
|
-
);
|
|
251
|
-
var d13 = Math.atan2(
|
|
252
|
-
Math.sin(d12) * Math.sin(a1) * Math.sin(a2),
|
|
253
|
-
Math.cos(a2) + Math.cos(a1) * Math.cos(a3)
|
|
254
|
-
);
|
|
255
|
-
var f3 = Math.asin(
|
|
256
|
-
Math.sin(f1) * Math.cos(d13) + Math.cos(f1) * Math.sin(d13) * Math.cos(D13)
|
|
257
|
-
);
|
|
258
|
-
var dl13 = Math.atan2(
|
|
259
|
-
Math.sin(D13) * Math.sin(d13) * Math.cos(f1),
|
|
260
|
-
Math.cos(d13) - Math.sin(f1) * Math.sin(f3)
|
|
261
|
-
);
|
|
262
|
-
var l3 = l1 + dl13;
|
|
263
|
-
|
|
264
|
-
return new LonLat(((l3 * DEGREES + 540) % 360) - 180, f3 * DEGREES);
|
|
265
|
-
}
|
|
266
|
-
|
|
267
|
-
/**
|
|
268
|
-
* Returns final bearing arriving at destination destination point from lonLat1 point; the final bearing
|
|
269
|
-
* will differ from the initial bearing by varying degrees according to distance and latitude.
|
|
270
|
-
* @param {LonLat} lonLat1 - Longitude/latitude of source point.
|
|
271
|
-
* @param {LonLat} lonLat2 - Longitude/latitude of destination point.
|
|
272
|
-
* @return {number} Final bearing in degrees from north.
|
|
273
|
-
*/
|
|
274
|
-
static getFinalBearing(lonLat1, lonLat2) {
|
|
275
|
-
// get initial bearing from destination lonLat2 to lonLat1 & reverse it by adding 180°
|
|
276
|
-
return (Ellipsoid.getInitialBearing(lonLat2, lonLat1) + 180) % 360;
|
|
95
|
+
getFlattening() {
|
|
96
|
+
return this._flattening;
|
|
277
97
|
}
|
|
278
98
|
|
|
279
99
|
/**
|
|
@@ -295,48 +115,24 @@ class Ellipsoid {
|
|
|
295
115
|
}
|
|
296
116
|
|
|
297
117
|
/**
|
|
298
|
-
*
|
|
118
|
+
* Calculate cartesian coordinates by its ECEF geodetic coordinates.
|
|
299
119
|
* @public
|
|
300
|
-
* @param {LonLat} lonlat -
|
|
120
|
+
* @param {LonLat} lonlat - Geodetic coordinates.
|
|
301
121
|
* @returns {Vec3} -
|
|
302
122
|
*/
|
|
303
123
|
lonLatToCartesian(lonlat) {
|
|
304
|
-
|
|
305
|
-
lonrad = RADIANS * lonlat.lon;
|
|
306
|
-
|
|
307
|
-
var slt = Math.sin(latrad);
|
|
308
|
-
|
|
309
|
-
var N = this._a / Math.sqrt(1.0 - this._e2 * slt * slt);
|
|
310
|
-
var nc = (N + lonlat.height) * Math.cos(latrad);
|
|
311
|
-
|
|
312
|
-
return new Vec3(
|
|
313
|
-
nc * Math.sin(lonrad),
|
|
314
|
-
(N * (1.0 - this._e2) + lonlat.height) * slt,
|
|
315
|
-
nc * Math.cos(lonrad)
|
|
316
|
-
);
|
|
124
|
+
return this.geodeticToCartesian(lonlat.lon, lonlat.lat, lonlat.height);
|
|
317
125
|
}
|
|
318
126
|
|
|
319
127
|
/**
|
|
320
|
-
*
|
|
128
|
+
* Calculate cartesian coordinates by its ECEF geodetic coordinates.
|
|
321
129
|
* @public
|
|
322
|
-
* @param {LonLat} lonlat -
|
|
323
|
-
* @param {Vec3} res - Output
|
|
130
|
+
* @param {LonLat} lonlat - Geodetic coordinates.
|
|
131
|
+
* @param {Vec3} res - Output variable reference.
|
|
324
132
|
* @returns {Vec3} -
|
|
325
133
|
*/
|
|
326
134
|
lonLatToCartesianRes(lonlat, res) {
|
|
327
|
-
|
|
328
|
-
lonrad = RADIANS * lonlat.lon;
|
|
329
|
-
|
|
330
|
-
var slt = Math.sin(latrad);
|
|
331
|
-
|
|
332
|
-
var N = this._a / Math.sqrt(1.0 - this._e2 * slt * slt);
|
|
333
|
-
var nc = (N + lonlat.height) * Math.cos(latrad);
|
|
334
|
-
|
|
335
|
-
res.x = nc * Math.sin(lonrad);
|
|
336
|
-
res.y = (N * (1.0 - this._e2) + lonlat.height) * slt;
|
|
337
|
-
res.z = nc * Math.cos(lonrad);
|
|
338
|
-
|
|
339
|
-
return res;
|
|
135
|
+
return this.geodeticToCartesian(lonlat.lon, lonlat.lat, lonlat.height, res);
|
|
340
136
|
}
|
|
341
137
|
|
|
342
138
|
/**
|
|
@@ -347,20 +143,22 @@ class Ellipsoid {
|
|
|
347
143
|
* @param {Number} height - Height.
|
|
348
144
|
* @returns {Vec3} -
|
|
349
145
|
*/
|
|
350
|
-
geodeticToCartesian(lon, lat, height = 0) {
|
|
351
|
-
|
|
146
|
+
geodeticToCartesian(lon, lat, height = 0, res) {
|
|
147
|
+
res = res || new Vec3();
|
|
148
|
+
|
|
149
|
+
let latrad = RADIANS * lat,
|
|
352
150
|
lonrad = RADIANS * lon;
|
|
353
151
|
|
|
354
|
-
|
|
152
|
+
let slt = Math.sin(latrad);
|
|
355
153
|
|
|
356
|
-
|
|
357
|
-
|
|
154
|
+
let N = this._a / Math.sqrt(1 - this._e2 * slt * slt);
|
|
155
|
+
let nc = (N + height) * Math.cos(latrad);
|
|
358
156
|
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
157
|
+
res.x = nc * Math.cos(lonrad);
|
|
158
|
+
res.y = nc * Math.sin(lonrad);
|
|
159
|
+
res.z = (N * (1 - this._e2) + height) * slt;
|
|
160
|
+
|
|
161
|
+
return res;
|
|
364
162
|
}
|
|
365
163
|
|
|
366
164
|
/**
|
|
@@ -375,6 +173,8 @@ class Ellipsoid {
|
|
|
375
173
|
pY = p.y || 0.0,
|
|
376
174
|
pZ = p.z || 0.0;
|
|
377
175
|
|
|
176
|
+
let length = Math.sqrt(pX * pX + pY * pY + pZ * pZ);
|
|
177
|
+
|
|
378
178
|
let invRadii2X = this._invRadii2.x,
|
|
379
179
|
invRadii2Y = this._invRadii2.y,
|
|
380
180
|
invRadii2Z = this._invRadii2.z;
|
|
@@ -391,9 +191,9 @@ class Ellipsoid {
|
|
|
391
191
|
return !Number.isFinite(ratio) ? new Vec3() : first
|
|
392
192
|
}
|
|
393
193
|
|
|
394
|
-
let lambda = ((1.0 - ratio) *
|
|
194
|
+
let lambda = ((1.0 - ratio) * length) / first.mulA(this._invRadii2).length();
|
|
395
195
|
|
|
396
|
-
let m_X, m_Y, m_Z;
|
|
196
|
+
let m_X = 0.0, m_Y = 0.0, m_Z = 0.0;
|
|
397
197
|
|
|
398
198
|
do {
|
|
399
199
|
m_X = 1.0 / (1.0 + lambda * invRadii2X);
|
|
@@ -427,14 +227,7 @@ class Ellipsoid {
|
|
|
427
227
|
* @returns {LonLat} - Geodetic coordinates
|
|
428
228
|
*/
|
|
429
229
|
cartesianToLonLat(cart) {
|
|
430
|
-
|
|
431
|
-
let n = this.getSurfaceNormal3v(p),
|
|
432
|
-
h = cart.sub(p);
|
|
433
|
-
return new LonLat(
|
|
434
|
-
Math.atan2(n.x, n.z) * DEGREES,
|
|
435
|
-
Math.asin(n.y) * DEGREES,
|
|
436
|
-
Math.sign(h.dot(cart)) * h.length()
|
|
437
|
-
);
|
|
230
|
+
return this.cartesianToLonLatRes(cart);
|
|
438
231
|
}
|
|
439
232
|
|
|
440
233
|
/**
|
|
@@ -444,12 +237,15 @@ class Ellipsoid {
|
|
|
444
237
|
* @returns {LonLat} - Geodetic coordinates
|
|
445
238
|
*/
|
|
446
239
|
cartesianToLonLatRes(cart, res) {
|
|
240
|
+
res = res || new LonLat();
|
|
447
241
|
let p = this.projToSurface(cart);
|
|
448
242
|
let n = this.getSurfaceNormal3v(p),
|
|
449
243
|
h = cart.sub(p);
|
|
450
|
-
|
|
451
|
-
res.
|
|
244
|
+
|
|
245
|
+
res.lon = Math.atan2(n.y, n.x) * DEGREES;
|
|
246
|
+
res.lat = Math.asin(n.z) * DEGREES;
|
|
452
247
|
res.height = Math.sign(h.dot(cart)) * h.length();
|
|
248
|
+
|
|
453
249
|
return res;
|
|
454
250
|
}
|
|
455
251
|
|
|
@@ -468,65 +264,96 @@ class Ellipsoid {
|
|
|
468
264
|
return new Vec3(nx * l, ny * l, nz * l);
|
|
469
265
|
}
|
|
470
266
|
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
* @param {LonLat} lonLat1
|
|
474
|
-
* @param {number} [bearing]
|
|
475
|
-
* @param {number} [distance]
|
|
476
|
-
* @return {LonLat} -
|
|
477
|
-
*/
|
|
478
|
-
getBearingDestination(lonLat1, bearing = 0.0, distance = 0) {
|
|
479
|
-
bearing = bearing * RADIANS;
|
|
480
|
-
var nlon = ((lonLat1.lon + 540) % 360) - 180;
|
|
481
|
-
var f1 = lonLat1.lat * RADIANS,
|
|
482
|
-
l1 = nlon * RADIANS;
|
|
483
|
-
var dR = distance / this._a;
|
|
484
|
-
var f2 = Math.asin(
|
|
485
|
-
Math.sin(f1) * Math.cos(dR) + Math.cos(f1) * Math.sin(dR) * Math.cos(bearing)
|
|
486
|
-
);
|
|
487
|
-
return new LonLat(
|
|
488
|
-
(l1 +
|
|
489
|
-
Math.atan2(
|
|
490
|
-
Math.sin(bearing) * Math.sin(dR) * Math.cos(f1),
|
|
491
|
-
Math.cos(dR) - Math.sin(f1) * Math.sin(f2)
|
|
492
|
-
)) *
|
|
493
|
-
DEGREES,
|
|
494
|
-
f2 * DEGREES
|
|
495
|
-
);
|
|
267
|
+
getGreatCircleDistance(lonLat1, lonLat2) {
|
|
268
|
+
return this.inverse(lonLat1, lonLat2).distance;
|
|
496
269
|
}
|
|
497
270
|
|
|
498
271
|
/**
|
|
499
|
-
*
|
|
500
|
-
*
|
|
501
|
-
*
|
|
502
|
-
* @
|
|
272
|
+
* Calculates the destination point given start point lat / lon, azimuth(deg) and distance (m).
|
|
273
|
+
* Source: http://movable-type.co.uk/scripts/latlong-vincenty-direct.html and optimized / cleaned up by Mathias Bynens <http://mathiasbynens.be/>
|
|
274
|
+
* Based on the Vincenty direct formula by T. Vincenty, “Direct and Inverse Solutions of Geodesics on the Ellipsoid with application of nested equations”, Survey Review, vol XXII no 176, 1975 <http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf>
|
|
275
|
+
* @param {LonLat} lonLat - Origin coordinates
|
|
276
|
+
* @param {number} azimuth - View azimuth in degrees
|
|
277
|
+
* @param {number} dist - Distance to the destination point coordinates in meters
|
|
278
|
+
* @returns {LonLat} - Destination point coordinates
|
|
503
279
|
*/
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
280
|
+
getGreatCircleDestination(lonLat, azimuth, dist) {
|
|
281
|
+
return this.direct(lonLat, azimuth, dist).destination;
|
|
282
|
+
}
|
|
283
|
+
|
|
284
|
+
inverse(lonLat1, lonLat2) {
|
|
285
|
+
|
|
286
|
+
let a = this._a, b = this._b, f = this._flattening;
|
|
287
|
+
|
|
288
|
+
const fi1 = lonLat1.lat * RADIANS, lambda1 = lonLat1.lon * RADIANS;
|
|
289
|
+
const fi2 = lonLat2.lat * RADIANS, lambda2 = lonLat2.lon * RADIANS;
|
|
290
|
+
|
|
291
|
+
const L = lambda2 - lambda1; // L = difference in longitude, U = reduced latitude, defined by tan U = (1-f)·tanφ.
|
|
292
|
+
const tanU1 = (1 - f) * Math.tan(fi1), cosU1 = 1 / Math.sqrt((1 + tanU1 * tanU1)), sinU1 = tanU1 * cosU1;
|
|
293
|
+
const tanU2 = (1 - f) * Math.tan(fi2), cosU2 = 1 / Math.sqrt((1 + tanU2 * tanU2)), sinU2 = tanU2 * cosU2;
|
|
294
|
+
|
|
295
|
+
const antipodal = Math.abs(L) > Math.PI / 2 || Math.abs(fi2 - fi1) > Math.PI / 2;
|
|
296
|
+
|
|
297
|
+
let lmb = L, sinLmb = null, cosLmb = null; // lmb - difference in longitude on an auxiliary sphere
|
|
298
|
+
let s = antipodal ? Math.PI : 0, sin_s = 0, cos_s = antipodal ? -1 : 1, sinSqs = null; // s - angular distance lonLat1 lonLat2 on the sphere
|
|
299
|
+
let cos2sm = 1; // sm - angular distance on the sphere from the equator to the midpoint of the line
|
|
300
|
+
let cosSqa = 1; // a - azimuth of the geodesic at the equator
|
|
301
|
+
|
|
302
|
+
let lmb_ = null, iterations = 0;
|
|
303
|
+
do {
|
|
304
|
+
sinLmb = Math.sin(lmb);
|
|
305
|
+
cosLmb = Math.cos(lmb);
|
|
306
|
+
sinSqs = (cosU2 * sinLmb) ** 2 + (cosU1 * sinU2 - sinU1 * cosU2 * cosLmb) ** 2;
|
|
307
|
+
if (Math.abs(sinSqs) < 1e-24) break; // co-incident/antipodal points (σ < ≈0.006mm)
|
|
308
|
+
sin_s = Math.sqrt(sinSqs);
|
|
309
|
+
cos_s = sinU1 * sinU2 + cosU1 * cosU2 * cosLmb;
|
|
310
|
+
s = Math.atan2(sin_s, cos_s);
|
|
311
|
+
const sin_a = cosU1 * cosU2 * sinLmb / sin_s;
|
|
312
|
+
cosSqa = 1 - sin_a * sin_a;
|
|
313
|
+
cos2sm = (cosSqa != 0) ? (cos_s - 2 * sinU1 * sinU2 / cosSqa) : 0; // on equatorial line cos²α = 0 (§6)
|
|
314
|
+
const C = f / 16 * cosSqa * (4 + f * (4 - 3 * cosSqa));
|
|
315
|
+
lmb_ = lmb;
|
|
316
|
+
lmb = L + (1 - C) * f * sin_a * (s + C * sin_s * (cos2sm + C * cos_s * (-1 + 2 * cos2sm * cos2sm)));
|
|
317
|
+
} while (Math.abs(lmb - lmb_) > EPS12 && ++iterations < 1000);
|
|
318
|
+
|
|
319
|
+
const uSq = cosSqa * (a * a - b * b) / (b * b);
|
|
320
|
+
const A = 1 + uSq / 16384 * (4096 + uSq * (-768 + uSq * (320 - 175 * uSq)));
|
|
321
|
+
const B = uSq / 1024 * (256 + uSq * (-128 + uSq * (74 - 47 * uSq)));
|
|
322
|
+
const ds = B * sin_s * (cos2sm + B / 4 * (cos_s * (-1 + 2 * cos2sm * cos2sm) - B / 6 * cos2sm * (-3 + 4 * sin_s * sin_s) * (-3 + 4 * cos2sm * cos2sm)));
|
|
323
|
+
|
|
324
|
+
const dist = b * A * (s - ds); // s = length of the geodesic
|
|
325
|
+
|
|
326
|
+
// note special handling of exactly antipodal points where sin²σ = 0 (due to discontinuity
|
|
327
|
+
// atan2(0, 0) = 0 but atan2(ε, 0) = π/2 / 90°) - in which case bearing is always meridional,
|
|
328
|
+
// due north (or due south!)
|
|
329
|
+
// α = azimuths of the geodesic; α2 the direction P₁ P₂ produced
|
|
330
|
+
const a1 = Math.abs(sinSqs) < Number.EPSILON ? 0 : Math.atan2(cosU2 * sinLmb, cosU1 * sinU2 - sinU1 * cosU2 * cosLmb);
|
|
331
|
+
const a2 = Math.abs(sinSqs) < Number.EPSILON ? Math.PI : Math.atan2(cosU1 * sinLmb, -sinU1 * cosU2 + cosU1 * sinU2 * cosLmb);
|
|
332
|
+
|
|
333
|
+
return {
|
|
334
|
+
distance: dist,
|
|
335
|
+
initialAzimuth: Math.abs(dist) < Number.EPSILON ? NaN : zeroTwoPI(a1) * DEGREES,
|
|
336
|
+
finalAzimuth: Math.abs(dist) < Number.EPSILON ? NaN : zeroTwoPI(a2) * DEGREES
|
|
337
|
+
};
|
|
514
338
|
}
|
|
515
339
|
|
|
516
340
|
/**
|
|
517
|
-
* Calculates the destination point given start point lat / lon,
|
|
518
|
-
*
|
|
519
|
-
* Taken from http://movable-type.co.uk/scripts/latlong-vincenty-direct.html and optimized / cleaned up by Mathias Bynens <http://mathiasbynens.be/>
|
|
341
|
+
* Calculates the destination point given start point lat / lon, azimuth(deg) and distance (m).
|
|
342
|
+
* Source: http://movable-type.co.uk/scripts/latlong-vincenty-direct.html and optimized / cleaned up by Mathias Bynens <http://mathiasbynens.be/>
|
|
520
343
|
* Based on the Vincenty direct formula by T. Vincenty, “Direct and Inverse Solutions of Geodesics on the Ellipsoid with application of nested equations”, Survey Review, vol XXII no 176, 1975 <http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf>
|
|
344
|
+
* @param {LonLat} lonLat - Origin coordinates
|
|
345
|
+
* @param {number} azimuth - View azimuth in degrees
|
|
346
|
+
* @param {number} dist - Distance to the destination point coordinates in meters
|
|
347
|
+
* @returns {LonLat} - Destination point coordinates
|
|
521
348
|
*/
|
|
522
|
-
|
|
523
|
-
|
|
349
|
+
direct(lonLat, azimuth, dist) {
|
|
350
|
+
let lon1 = lonLat.lon,
|
|
524
351
|
lat1 = lonLat.lat;
|
|
525
|
-
|
|
352
|
+
let a = this._a,
|
|
526
353
|
b = this._b,
|
|
527
|
-
f =
|
|
354
|
+
f = this._flattening,
|
|
528
355
|
s = dist,
|
|
529
|
-
alpha1 =
|
|
356
|
+
alpha1 = azimuth * RADIANS,
|
|
530
357
|
sinAlpha1 = Math.sin(alpha1),
|
|
531
358
|
cosAlpha1 = Math.cos(alpha1),
|
|
532
359
|
tanU1 = (1 - f) * Math.tan(lat1 * RADIANS),
|
|
@@ -544,20 +371,16 @@ class Ellipsoid {
|
|
|
544
371
|
var cos2SigmaM = Math.cos(2 * sigma1 + sigma),
|
|
545
372
|
sinSigma = Math.sin(sigma),
|
|
546
373
|
cosSigma = Math.cos(sigma),
|
|
547
|
-
deltaSigma =
|
|
548
|
-
B *
|
|
549
|
-
|
|
550
|
-
|
|
551
|
-
|
|
552
|
-
|
|
553
|
-
(B / 6) *
|
|
554
|
-
cos2SigmaM *
|
|
555
|
-
(-3 + 4 * sinSigma * sinSigma) *
|
|
556
|
-
(-3 + 4 * cos2SigmaM * cos2SigmaM)));
|
|
374
|
+
deltaSigma = B * sinSigma *
|
|
375
|
+
(cos2SigmaM + (B / 4) *
|
|
376
|
+
(
|
|
377
|
+
cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM) -
|
|
378
|
+
(B / 6) * cos2SigmaM * (-3 + 4 * sinSigma * sinSigma) * (-3 + 4 * cos2SigmaM * cos2SigmaM)
|
|
379
|
+
));
|
|
557
380
|
sigmaP = sigma;
|
|
558
381
|
sigma = s / (b * A) + deltaSigma;
|
|
559
382
|
}
|
|
560
|
-
|
|
383
|
+
let tmp = sinU1 * sinSigma - cosU1 * cosSigma * cosAlpha1,
|
|
561
384
|
lat2 = Math.atan2(
|
|
562
385
|
sinU1 * cosSigma + cosU1 * sinSigma * cosAlpha1,
|
|
563
386
|
(1 - f) * Math.sqrt(sinAlpha * sinAlpha + tmp * tmp)
|
|
@@ -566,22 +389,19 @@ class Ellipsoid {
|
|
|
566
389
|
sinSigma * sinAlpha1,
|
|
567
390
|
cosU1 * cosSigma - sinU1 * sinSigma * cosAlpha1
|
|
568
391
|
),
|
|
569
|
-
C = (f / 16) * cosSqAlpha * (4 + f * (4 - 3 * cosSqAlpha)),
|
|
570
|
-
L =
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
sinSigma *
|
|
578
|
-
(cos2SigmaM + C * cosSigma * (-1 + 2 * cos2SigmaM * cos2SigmaM))),
|
|
579
|
-
revAz = Math.atan2(sinAlpha, -tmp); // final bearing
|
|
580
|
-
return new LonLat(lon1 + L * DEGREES, lat2 * DEGREES);
|
|
392
|
+
C = (f / 16.0) * cosSqAlpha * (4.0 + f * (4.0 - 3.0 * cosSqAlpha)),
|
|
393
|
+
L = lambda - (1.0 - C) * f * sinAlpha * (sigma + C * sinSigma * (cos2SigmaM + C * cosSigma * (-1.0 + 2.0 * cos2SigmaM * cos2SigmaM))),
|
|
394
|
+
revAz = Math.atan2(sinAlpha, -tmp);
|
|
395
|
+
|
|
396
|
+
return {
|
|
397
|
+
destination: new LonLat(lon1 + L * DEGREES, lat2 * DEGREES),
|
|
398
|
+
finalAzimuth: revAz * DEGREES
|
|
399
|
+
};
|
|
581
400
|
}
|
|
582
401
|
|
|
402
|
+
|
|
583
403
|
/**
|
|
584
|
-
* Returns ray
|
|
404
|
+
* Returns cartesian coordinates of the intersection of a ray and an ellipsoid.
|
|
585
405
|
* If the ray doesn't hit ellipsoid returns null.
|
|
586
406
|
* @public
|
|
587
407
|
* @param {Vec3} origin - Ray origin point.
|
|
@@ -646,9 +466,100 @@ class Ellipsoid {
|
|
|
646
466
|
return origin.add(direction.scaleTo(-qw / w2));
|
|
647
467
|
}
|
|
648
468
|
// qw >= 0.0. Looking outward or tangent.
|
|
649
|
-
return
|
|
469
|
+
// return undefined
|
|
650
470
|
}
|
|
651
471
|
}
|
|
472
|
+
|
|
473
|
+
getNorthFrameRotation(cartesian) {
|
|
474
|
+
let n = this.getSurfaceNormal3v(cartesian);
|
|
475
|
+
let t = Vec3.proj_b_to_plane(Vec3.NORTH, n);
|
|
476
|
+
return Quat.getLookRotation(t, n);
|
|
477
|
+
}
|
|
478
|
+
|
|
479
|
+
/**
|
|
480
|
+
* @todo this is not precise function, needs to be replaced or removed
|
|
481
|
+
* @param lonLat1
|
|
482
|
+
* @param bearing
|
|
483
|
+
* @param distance
|
|
484
|
+
* @returns {LonLat}
|
|
485
|
+
*/
|
|
486
|
+
getBearingDestination(lonLat1, bearing = 0.0, distance = 0) {
|
|
487
|
+
bearing = bearing * RADIANS;
|
|
488
|
+
var nlon = ((lonLat1.lon + 540) % 360) - 180;
|
|
489
|
+
var f1 = lonLat1.lat * RADIANS,
|
|
490
|
+
l1 = nlon * RADIANS;
|
|
491
|
+
var dR = distance / this._a;
|
|
492
|
+
var f2 = Math.asin(
|
|
493
|
+
Math.sin(f1) * Math.cos(dR) + Math.cos(f1) * Math.sin(dR) * Math.cos(bearing)
|
|
494
|
+
);
|
|
495
|
+
return new LonLat(
|
|
496
|
+
(l1 +
|
|
497
|
+
Math.atan2(
|
|
498
|
+
Math.sin(bearing) * Math.sin(dR) * Math.cos(f1),
|
|
499
|
+
Math.cos(dR) - Math.sin(f1) * Math.sin(f2)
|
|
500
|
+
)) *
|
|
501
|
+
DEGREES,
|
|
502
|
+
f2 * DEGREES
|
|
503
|
+
);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Returns the point at given fraction between two points on the great circle.
|
|
508
|
+
* @param {LonLat} lonLat1 - Longitude/Latitude of source point.
|
|
509
|
+
* @param {LonLat} lonLat2 - Longitude/Latitude of destination point.
|
|
510
|
+
* @param {number} fraction - Fraction between the two points (0 = source point, 1 = destination point).
|
|
511
|
+
* @returns {LonLat} Intermediate point between points.
|
|
512
|
+
*/
|
|
513
|
+
static getIntermediatePointOnGreatCircle(lonLat1, lonLat2, fraction) {
|
|
514
|
+
var f1 = lonLat1.lat * RADIANS,
|
|
515
|
+
l1 = lonLat1.lon * RADIANS;
|
|
516
|
+
var f2 = lonLat2.lat * RADIANS,
|
|
517
|
+
l2 = lonLat2.lon * RADIANS;
|
|
518
|
+
|
|
519
|
+
var sinf1 = Math.sin(f1),
|
|
520
|
+
cosf1 = Math.cos(f1),
|
|
521
|
+
sinl1 = Math.sin(l1),
|
|
522
|
+
cosl1 = Math.cos(l1);
|
|
523
|
+
var sinf2 = Math.sin(f2),
|
|
524
|
+
cosf2 = Math.cos(f2),
|
|
525
|
+
sinl2 = Math.sin(l2),
|
|
526
|
+
cosl2 = Math.cos(l2);
|
|
527
|
+
|
|
528
|
+
var df = f2 - f1,
|
|
529
|
+
dl = l2 - l1;
|
|
530
|
+
var a =
|
|
531
|
+
Math.sin(df / 2) * Math.sin(df / 2) +
|
|
532
|
+
Math.cos(f1) * Math.cos(f2) * Math.sin(dl / 2) * Math.sin(dl / 2);
|
|
533
|
+
var d = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
|
|
534
|
+
|
|
535
|
+
var A = Math.sin((1 - fraction) * d) / Math.sin(d);
|
|
536
|
+
var B = Math.sin(fraction * d) / Math.sin(d);
|
|
537
|
+
|
|
538
|
+
var x = A * cosf1 * cosl1 + B * cosf2 * cosl2;
|
|
539
|
+
var y = A * cosf1 * sinl1 + B * cosf2 * sinl2;
|
|
540
|
+
var z = A * sinf1 + B * sinf2;
|
|
541
|
+
|
|
542
|
+
var f3 = Math.atan2(z, Math.sqrt(x * x + y * y));
|
|
543
|
+
var l3 = Math.atan2(y, x);
|
|
544
|
+
|
|
545
|
+
return new LonLat(((l3 * DEGREES + 540) % 360) - 180, f3 * DEGREES);
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
static getRhumbBearing(lonLat1, lonLat2) {
|
|
549
|
+
var dLon = (lonLat2.lon - lonLat1.lon) * RADIANS;
|
|
550
|
+
var dPhi = Math.log(
|
|
551
|
+
Math.tan((lonLat2.lat * RADIANS) / 2 + Math.PI / 4) /
|
|
552
|
+
Math.tan((lonLat1.lat * RADIANS) / 2 + Math.PI / 4)
|
|
553
|
+
);
|
|
554
|
+
if (Math.abs(dLon) > Math.PI) {
|
|
555
|
+
if (dLon > 0) {
|
|
556
|
+
dLon = (2 * Math.PI - dLon) * -1;
|
|
557
|
+
} else {
|
|
558
|
+
dLon = 2 * Math.PI + dLon;
|
|
559
|
+
}
|
|
560
|
+
}
|
|
561
|
+
return (Math.atan2(dLon, dPhi) * DEGREES + 360) % 360;
|
|
562
|
+
}
|
|
652
563
|
}
|
|
653
564
|
|
|
654
565
|
export { Ellipsoid };
|