Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Calculate oriented bounding box from bounding region for 3D tiles of Cesium's OSM buildings #40

Open
wants to merge 20 commits into
base: master
Choose a base branch
from

Conversation

sraimund
Copy link
Contributor

@sraimund sraimund commented Jan 4, 2025

Here the ported code from Cesium to fix the calculation of the bounding box from a region on the WGS84 ellipsoid (see issue visgl/loaders.gl#3144). The function signature fromRegion() in oriented-bounding-box.ts (math.gl/culling) is similar to the previous createObbFromRegion function in bounding-volume.ts (loaders.gl/tiles). The other functions are nearly a 1:1 mapping from Cesium, except that these are now class methods.

Test:
https://stackblitz.com/edit/stackblitz-starters-pode72re (takes ~2mins to build and load)

Notes:

  • I could only build the culling module when adding // @ts-ignore // eslint-disable-next-line import/no-unresolved above import {Ellipsoid} from '@math.gl/geospatial'; in oriented-bounding-box.ts and import {Ellipsoid} from '@math.gl/geospatial'; in ellipsoid-tangent-plane.ts.

  • I'm not sure whether the 'lint' command worked correctly since it only showed some warnings for the dev-docs.

Copy link
Contributor

@ibgreen ibgreen left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sraimund Thanks for doing this relatively extensive work, that was definitely a good amount of code!

Apart from some smaller nits (optional suggestion) in my comments, the main missing pieces are docs and tests, at least for the publicly exported functions.

I understand if you have limits on the amount of time you can put on this PR, just let me know what you can do, and then we will get it landed and published.

* @param {Vector3} result The object onto which to store the result.
* @returns {Vector3} The modified result parameter.
*/
multiplyByVector(cartesian: Vector3, result?: Vector3): Vector3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is the same as m3.transform(v3) below? The name comes from viewing the matrix as a transform on vectors.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's indeed the same. I removed the method 2cb1e6b

* @param {Matrix3} result The object onto which to store the result.
* @returns {Matrix3} The modified result parameter.
*/
multiplyByScale(scale: Vector3, result?: Matrix3): Matrix3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method is inherited from Matrix3 < Matrix < MathArray. Called m3.scale(v3)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I now reused the parent scale method, see 801904f The overridden scale method in Matrix3 multiplies it with a Vector2. There I'm not sure if adding another check whether the array length is 2 or 3 impacts the performance in case the method is called many times.

/**
* The modulo operation that also works for negative dividends.
*
* @param {number} m The dividend.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Avoid adding types in the TSDoc, they are inferred from the typescript types.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 2222cc5

* @returns {OrientedBoundingBox} The modified result parameter or a new OrientedBoundingBox instance if none was provided.
*/
// eslint-disable-next-line max-statements
fromRegion(region: number[]): OrientedBoundingBox {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: From tree shaking (bundle size) perspective, it would be preferable to offer this as a global function rather than a method on the OBB class. That way we could also avoid this file from growing too big.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 5c2bd42. I renamed it to makeOrientedBoundingBoxFromRegion() similarly to the other function names in the algorithms folder.

* Computes an OrientedBoundingBox that bounds a region on the surface of the WGS84 ellipsoid.
* There are no guarantees about the orientation of the bounding box.
*
* @param {number[]} region The cartographic region ([west, south, east, north, minimum height, maximum height])
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Remove type annotations here.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 2222cc5

@@ -58,6 +58,9 @@ export {
// math.gl "GLSL"-style functions
radians,
degrees,
mod,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

At least a trivial, minimal test case for every global export is normally expected.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 0f89190

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In bounding-box-from-region.spec.ts, however, I added only two tests since there are too many to port from Cesium. Moreover, these tests are based on a unit sphere and math.gl supports only a WGS84 ellipsoid currently.

const scratchDirection = new Vector3();

/** A plane tangent to the WGS84 ellipsoid at the provided origin */
export class EllipsoidTangentPlane {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are there any tests for this class that could be ported? (even if most are commented out, still nice to have them)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 0f89190

* @param {Vector3} [result] The object onto which to store the result.
* @returns {Vector3} The intersection point or undefined if there is no intersections.
*/
intersectWithRay(ray: Ray, result?: Vector3): Vector3 {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Might have preferred as a global function to avoid pulling in Ray for every app.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. See 5c2bd42

import {Vector3, negativePiToPi, _MathUtils} from '@math.gl/core'

/** A two dimensional region specified as longitude and latitude coordinates. */
export class Rectangle {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Maybe this should be called LngLatRectangle given its special handling of geospatial coordinates (it is certainly not a generic Rectangle class).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I renamed it to GeoRectangle ae5cef2 (similarly to https://doc.qt.io/qt-6/qgeorectangle.html). Concerning your proposition, I would be a bit confused if it is called LngLatRectangle or LatLngRectangle.

@sraimund
Copy link
Contributor Author

sraimund commented Jan 6, 2025

I've also updated https://stackblitz.com/edit/stackblitz-starters-pode72re with a new build from the recent commits.

Do the docs need to be manually added or can they be somehow automatically transferred from TSdoc?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants