Skip to content

Commit 0a0dfb5

Browse files
ibgreenRaimund Schnürer
andauthored
feat(geospatial): Add makeOBBFromRegion() (#43)
Co-authored-by: Raimund Schnürer <[email protected]>
1 parent 0e77187 commit 0a0dfb5

File tree

20 files changed

+687
-10
lines changed

20 files changed

+687
-10
lines changed

modules/core/src/classes/matrix3.ts

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55

66
import {NumericArray, NumericArray9} from '@math.gl/types';
77
import {Matrix} from './base/matrix';
8+
import {Vector3} from './vector3';
89
import {checkVector} from '../lib/validators';
910

1011
import {vec4_transformMat3} from '../lib/gl-matrix-extras';
@@ -202,6 +203,54 @@ export class Matrix3 extends Matrix {
202203
return this.check();
203204
}
204205

206+
/**
207+
* Computes the product of this matrix and a column vector.
208+
*
209+
* @param {Vector3} cartesian The column.
210+
* @param {Vector3} result The object onto which to store the result.
211+
* @returns {Vector3} The modified result parameter.
212+
*/
213+
multiplyByVector(cartesian: Vector3, result?: Vector3): Vector3 {
214+
if (!result) result = new Vector3();
215+
216+
const vX = cartesian.x;
217+
const vY = cartesian.y;
218+
const vZ = cartesian.z;
219+
220+
const x = this[0] * vX + this[3] * vY + this[6] * vZ;
221+
const y = this[1] * vX + this[4] * vY + this[7] * vZ;
222+
const z = this[2] * vX + this[5] * vY + this[8] * vZ;
223+
224+
result.x = x;
225+
result.y = y;
226+
result.z = z;
227+
228+
return result;
229+
}
230+
231+
/**
232+
* Computes the product of this matrix times a (non-uniform) scale, as if the scale were a scale matrix.
233+
*
234+
* @param {Vector3} scale The non-uniform scale on the right-hand side.
235+
* @param {Matrix3} result The object onto which to store the result.
236+
* @returns {Matrix3} The modified result parameter.
237+
*/
238+
multiplyByScale(scale: Vector3, result?: Matrix3): Matrix3 {
239+
if (!result) result = new Matrix3();
240+
241+
result[0] = this[0] * scale.x;
242+
result[1] = this[1] * scale.x;
243+
result[2] = this[2] * scale.x;
244+
result[3] = this[3] * scale.y;
245+
result[4] = this[4] * scale.y;
246+
result[5] = this[5] * scale.y;
247+
result[6] = this[6] * scale.z;
248+
result[7] = this[7] * scale.z;
249+
result[8] = this[8] * scale.z;
250+
251+
return result;
252+
}
253+
205254
rotate(radians: number): this {
206255
mat3_rotate(this, this, radians);
207256
return this.check();

modules/core/src/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ export {
4848
// math.gl global utility methods
4949
config,
5050
configure,
51+
safeMod,
52+
normalizeAngle,
5153
formatValue,
5254
isArray,
5355
clone,

modules/core/src/lib/common.ts

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
import type {NumericArray} from '@math.gl/types';
88

99
import type {MathArray} from '../classes/base/math-array';
10+
import {EPSILON14, TWO_PI, PI} from './math-utils';
1011

1112
const RADIANS_TO_DEGREES = (1 / Math.PI) * 180;
1213
const DEGREES_TO_RADIANS = (1 / 180) * Math.PI;
@@ -122,6 +123,72 @@ export function degrees(
122123
return map(radians, (radians) => radians * RADIANS_TO_DEGREES, result);
123124
}
124125

126+
/**
127+
* The modulo operation that also works for negative dividends.
128+
*
129+
* @param m The dividend.
130+
* @param n The divisor.
131+
* @returns The remainder.
132+
*/
133+
export function safeMod(m: number, n: number): number {
134+
if (Math.sign(m) === Math.sign(n) && Math.abs(m) < Math.abs(n)) {
135+
return m;
136+
}
137+
138+
return ((m % n) + n) % n;
139+
}
140+
141+
/**
142+
* Produces an angle restricted to its equivalent in a normalized range
143+
*
144+
* @param angle in radians
145+
* @param range 'zero-to-two-pi' - in the range 0 <= angle <= 2PI, | 'negative-pi-to-pi' - -Pi <= angle <= Pi
146+
* @returns The angle in the range [0, <code>TWO_PI</code>] or [<code>-PI</code>, <code>PI</code>]..
147+
*/
148+
export function normalizeAngle(
149+
angle: number,
150+
range: 'zero-to-two-pi' | 'negative-pi-to-pi'
151+
): number {
152+
switch (range) {
153+
case 'negative-pi-to-pi':
154+
return negativePiToPi(angle);
155+
case 'zero-to-two-pi':
156+
return zeroToTwoPi(angle);
157+
default:
158+
return angle;
159+
}
160+
}
161+
162+
/**
163+
* Produces an angle in the range 0 <= angle <= 2Pi which is equivalent to the provided angle.
164+
*
165+
* @param angle in radians
166+
* @returns The angle in the range [0, <code>TWO_PI</code>].
167+
*/
168+
function zeroToTwoPi(angle: number): number {
169+
if (angle >= 0 && angle <= TWO_PI) {
170+
return angle;
171+
}
172+
const remainder = safeMod(angle, TWO_PI);
173+
if (Math.abs(remainder) < EPSILON14 && Math.abs(angle) > EPSILON14) {
174+
return TWO_PI;
175+
}
176+
return remainder;
177+
}
178+
179+
/**
180+
* Produces an angle in the range -Pi <= angle <= Pi which is equivalent to the provided angle.
181+
*
182+
* @param angle in radians
183+
* @returns The angle in the range [<code>-PI</code>, <code>PI</code>].
184+
*/
185+
function negativePiToPi(angle: number): number {
186+
if (angle >= -PI && angle <= PI) {
187+
return angle;
188+
}
189+
return zeroToTwoPi(angle + PI) - PI;
190+
}
191+
125192
/**
126193
* "GLSL equivalent" of `Math.sin`: Works on single values and vectors
127194
* @deprecated

modules/core/src/lib/math-utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,4 +29,5 @@ export const PI_OVER_TWO = Math.PI / 2;
2929
export const PI_OVER_FOUR = Math.PI / 4;
3030
export const PI_OVER_SIX = Math.PI / 6;
3131

32+
export const PI = Math.PI;
3233
export const TWO_PI = Math.PI * 2;

modules/culling/src/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export {BoundingSphere} from './lib/bounding-volumes/bounding-sphere';
99
export {OrientedBoundingBox} from './lib/bounding-volumes/oriented-bounding-box';
1010
export {CullingVolume} from './lib/culling-volume';
1111
export {Plane} from './lib/plane';
12+
export {Ray} from './lib/ray';
1213

1314
export {PerspectiveOffCenterFrustum as _PerspectiveOffCenterFrustum} from './lib/perspective-off-center-frustum';
1415
export {PerspectiveFrustum as _PerspectiveFrustum} from './lib/perspective-frustum';

modules/culling/src/lib/bounding-volumes/oriented-bounding-box.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,10 @@
77

88
import {NumericArray} from '@math.gl/types';
99
import {Vector3, Matrix3, Matrix4, Quaternion} from '@math.gl/core';
10+
1011
import type {BoundingVolume} from './bounding-volume';
1112
import {BoundingSphere} from './bounding-sphere';
12-
import type {Plane} from '../plane';
13+
import {Plane} from '../plane';
1314
import {INTERSECTION} from '../../constants';
1415

1516
const scratchVector3 = new Vector3();

modules/culling/src/lib/plane.ts

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,8 @@
66
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
77

88
/* eslint-disable */
9-
import {Vector3, equals, assert, NumericArray} from '@math.gl/core';
9+
import {Vector3, equals, assert, NumericArray, _MathUtils} from '@math.gl/core';
10+
import {Ray} from './ray';
1011

1112
const scratchPosition = new Vector3();
1213
const scratchNormal = new Vector3();
@@ -86,4 +87,33 @@ export class Plane {
8687

8788
return scratchPoint.subtract(scaledNormal).to(result);
8889
}
90+
91+
/**
92+
* Computes the intersection of a ray and this plane.
93+
*
94+
* @param {Ray} ray The ray.
95+
* @param {Vector3} [result] The object onto which to store the result.
96+
* @returns {Vector3} The intersection point or undefined if there is no intersections.
97+
*/
98+
intersectWithRay(ray: Ray, result?: Vector3): Vector3 {
99+
if (!result) result = new Vector3();
100+
101+
const origin = ray.origin;
102+
const direction = ray.direction;
103+
const normal = this.normal;
104+
const denominator = normal.dot(direction);
105+
106+
if (Math.abs(denominator) < _MathUtils.EPSILON15) {
107+
return undefined;
108+
}
109+
110+
const t = (-this.distance - normal.dot(origin)) / denominator;
111+
112+
if (t < 0) {
113+
return undefined;
114+
}
115+
116+
result = result.copy(direction).multiplyByScalar(t);
117+
return origin.add(result);
118+
}
89119
}

modules/culling/src/lib/ray.ts

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
// math.gl
2+
// SPDX-License-Identifier: MIT and Apache-2.0
3+
// Copyright (c) vis.gl contributors
4+
5+
// This file is derived from the Cesium library under Apache 2 license
6+
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
7+
8+
import {Vector3} from '@math.gl/core';
9+
10+
/* Represents a ray that extends infinitely from the provided origin in the provided direction. */
11+
export class Ray {
12+
origin: Vector3;
13+
direction: Vector3;
14+
15+
/**
16+
* Creates a new ray that extends infinitely from the provided origin in the provided direction.
17+
*
18+
* @param [origin=Vector3] The origin of the ray.
19+
* @param [direction=Vector3] The direction of the ray.
20+
*/
21+
constructor(origin?: Vector3, direction?: Vector3) {
22+
if (origin) origin = origin.clone();
23+
else origin = new Vector3();
24+
25+
if (direction) direction = direction.clone().normalize();
26+
else direction = new Vector3();
27+
28+
this.origin = origin;
29+
this.direction = direction;
30+
}
31+
}
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
// This file is derived from the Cesium math library under Apache 2 license
2+
// See LICENSE.md and https://github.com/AnalyticalGraphicsInc/cesium/blob/master/LICENSE.md
3+
4+
/* eslint-disable */
5+
import test from 'tape-promise/tape';
6+
// import {tapeEquals} from 'test/utils/tape-assertions';
7+
8+
import {Vector3, _MathUtils} from '@math.gl/core';
9+
import {Ray} from '@math.gl/culling';
10+
11+
test('Ray#constructs', (t) => {
12+
const ray = new Ray(new Vector3(1, 0, 0));
13+
t.ok(ray);
14+
t.end();
15+
});

modules/geospatial/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
],
4141
"dependencies": {
4242
"@math.gl/core": "4.1.0-alpha.9",
43+
"@math.gl/culling": "4.1.0-alpha.9",
4344
"@math.gl/types": "4.1.0-alpha.9"
4445
},
4546
"gitHead": "e1a95300cb225a90da6e90333d4adf290f7ba501"

0 commit comments

Comments
 (0)