diff --git a/dev-docs/ROADMAP.md b/dev-docs/ROADMAP.md index 003f4a30..73d9f3cf 100644 --- a/dev-docs/ROADMAP.md +++ b/dev-docs/ROADMAP.md @@ -1,10 +1,23 @@ # Roadmap -## Performance +## 3D Primitives -TBA: +- Add a submodule with the geometry primitives from luma.gl. -- Quantify -- Add bench target +### Geometry Processing -## About Library Size +- Provide a library for CPU side geometry processing, for calculating normals, ray casting etc. +- There is initial code in `@loaders.gl/math` that should be cleaned up and moved to math.gl. + +### Improved Columnar Table Support + +- Geometries are essentially columnar tables, emphasize this further to simplify integration with columnar table systems, primarily ArrowJS. + +### GPU Powered Math? + +- TBA + +## Interoperability and Framework Independence + +- An ambition is that math.gl should be able to serve a general purpose 3D math library, enabling the creation of framework-independent 3D and Geospatial code that interoperates with a variety of frameworks. +- math.gl modules (such as geospatial math) should be usable by applications using other frameworks, without having to use the core math.gl classes. diff --git a/docs/modules/core/wip/features.md.disabled b/dev-docs/design-notes.md similarity index 100% rename from docs/modules/core/wip/features.md.disabled rename to dev-docs/design-notes.md diff --git a/docs/README.md b/docs/README.md index eb3f335c..2092a5cb 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,22 +1,28 @@ # Introduction -Welcome to math.gl! math.gl is JavaScript math library focused on **geospatial** and **3D** use cases, designed as a composable, **modular toolbox**. math.gl provides a core module with classic vector and matrix classes, and a suite of optional modules implementing various aspects of geospatial and 3D math. +Welcome to math.gl! math.gl is JavaScript (TypeScript) math library focused on **geospatial** and **3D** use cases. Designed as a composable, **modular toolbox**. math.gl provides a core module with classic vector and matrix classes, and a suite of optional modules implementing various aspects of geospatial and 3D math. -While the math.gl is highly **optimized for use with the WebGL and WebGPU APIs**, math.gl itself has no WebGL dependencies. +While math.gl is highly **optimized for use with the WebGL and WebGPU APIs**, it has no WebGL dependencies and is designed to be usable in any application. + +## Features + +- **3D math** - Basic vectors and matrices, as well as 3D primitives and culling: **`@math.gl/types`**, **`@math.gl/core`**, **`@math.gl/culling`** +- **Geospatial projections** - Support for a variety of geospatial projections **`@math.gl/geospatial`**, **`@math.gl/geoid`**, **`@math.gl/proj4`**, **`@math.gl/web-mercator`** +- **Geospatial utilities** - Cutting polygons and calculating sun position and direction **`@math.gl/polygon`**, **`@math.gl/sun`** +- **Discrete Global Grids** - Standardized interfaces to a number of the major discrete global grids. **`@math.gl/geohash`**, **`@math.gl/quadkey`**, **`@math.gl/s2`** ## Modules math.gl is a toolbox that offers a suite of composable modules. -| **Core math libraries** | Module | Description | -| --------------------------------------------------- | ------------------------------------ | -------------------------------------------------- | -| | | | -| | **`@math.gl/types`** | Basic math type helpers (`NumericArray` etc) | -| ![core](./images/core.png 'core') | **`@math.gl/core`** | 3D math classes (vectors, matrices, etc) | -| ![culling](./images/culling.png 'culling') | **`@math.gl/culling`** | Bounding volumes and intersection testing. | +| **Core math libraries** | Module | Description | +| ------------------------------------------ | ------------------------------------ | -------------------------------------------- | +| | **`@math.gl/types`** | Basic math type helpers (`NumericArray` etc) | +| ![core](./images/core.png 'core') | **`@math.gl/core`** | 3D math classes (vectors, matrices, etc) | +| ![culling](./images/culling.png 'culling') | **`@math.gl/culling`** | Bounding volumes and intersection testing. | | **Geospatial math libraries** | Module | Description | -| --------------------------------------------------- | --------------------------- | -------------------------------------------------- | +| --------------------------------------------------- | ------------------------------------ | -------------------------------------------------- | | ![geospatial](./images/geospatial.svg 'geospatial') | **`@math.gl/geospatial`** | Ellipsoidal math for WGS84 coordinates. | | ![geoid](./images/geoid.png 'geoid') | **`@math.gl/geoid`** | Earth Gravity Model support . | | | **`@math.gl/polygon`** | Polygon math, including geospatial cutting etc. | @@ -24,12 +30,12 @@ math.gl is a toolbox that offers a suite of composable modules. | | **`@math.gl/sun`** | Solar position / direction from position and time. | | | **`@math.gl/web-mercator`** | Supports 3D Web Mercator (spherical) projections. | -| **DGGS (Discrete global grid support) libraries** | Module | Description | -| --------------------------------------------------- | --------------------------- | -------------------------------------------------- | -| | | | -| ![geohash](./images/dggs/geohash.png 'geohash') | **`@math.gl/geohash`** | Get geometry of GeoHash tokens. | -| ![quadkey](./images/dggs/quadkey.png 'quadkey') | **`@math.gl/quadkey`** | Get geometry of QuadKey tokens | -| ![s2](./images/dggs/s2.png 's2') | **`@math.gl/s2`** | Get geometry of S2 tokens. | +| **DGGS (Discrete global grid support) libraries** | Module | Description | +| ------------------------------------------------- | ------------------------------------ | ------------------------------- | +| | | | +| ![geohash](./images/dggs/geohash.png 'geohash') | **`@math.gl/geohash`** | Get geometry of GeoHash tokens. | +| ![quadkey](./images/dggs/quadkey.png 'quadkey') | **`@math.gl/quadkey`** | Get geometry of QuadKey tokens | +| ![s2](./images/dggs/s2.png 's2') | **`@math.gl/s2`** | Get geometry of S2 tokens. |
In addition, math.gl provides a few deprecated legacy modules, to avoid breaking older applications. diff --git a/docs/modules/core/developer-guide/debugging.md b/docs/developer-guide/debugging.md similarity index 100% rename from docs/modules/core/developer-guide/debugging.md rename to docs/developer-guide/debugging.md diff --git a/docs/modules/core/developer-guide/external-frameworks.md b/docs/developer-guide/external-frameworks.md similarity index 100% rename from docs/modules/core/developer-guide/external-frameworks.md rename to docs/developer-guide/external-frameworks.md diff --git a/docs/developer-guide/dggs.md b/docs/developer-guide/geospatial/dggs.md similarity index 72% rename from docs/developer-guide/dggs.md rename to docs/developer-guide/geospatial/dggs.md index 03267b00..d62482a9 100644 --- a/docs/developer-guide/dggs.md +++ b/docs/developer-guide/geospatial/dggs.md @@ -33,3 +33,34 @@ Rather than expose the original function names as in the existing JavaScript lib | Get cell center | `getS2LngLat` | `getQuadKeyLngLat` | `getGeoHashLngLat` | `getH3LngLat` | | Get cell boundary | `getS2Boundary` | `getQuadKeyBoundary` | `getGeoHashBoundary` | `getH3Boundary` | | Get cell boundary flat | `getS2BoundaryFlat` | `getQuadKeyBoundaryFlat` | `getGeoHashBoundaryFlat` | `getH3BoundaryFlat` | + +## Comparison of DGGS Systems + +### H3 + +H3, initally developed at Uber, is now widely used across the geospatial indusry. +While not directly supported by math.gl, is in fact the DGGS we would recommend for most applications. + +- Extensive, optimized, evolving API. +- Superb cross-language support. +- Equal distance between neighboring cells +- Similar size between all cells. +- K-ring formation for filtering and convolutions + +Downsides: +- More complex projection math. + +### GeoHash + +Geohash is common choice open source word http://en.wikipedia.org/wiki/Geohash + +Good cross-language support. + +### QuadKey + +Bing Maps uses a [quadkey](http://msdn.microsoft.com/en-us/library/bb259689.aspx.) structure as their tiling scheme. Here is an overview of the concept + +- Quadtrees are more predictable in that each level spans a square (at least in terms of coordinates), whereas in geohash representation sometimes squares sometimes rectangles are spanned. + +### Other systems + diff --git a/docs/developer-guide/geospatial-models.md b/docs/developer-guide/geospatial/geospatial-models.md similarity index 100% rename from docs/developer-guide/geospatial-models.md rename to docs/developer-guide/geospatial/geospatial-models.md diff --git a/docs/modules/core/concepts/coordinate-systems.md b/docs/developer-guide/math/coordinate-systems.md similarity index 100% rename from docs/modules/core/concepts/coordinate-systems.md rename to docs/developer-guide/math/coordinate-systems.md diff --git a/docs/modules/core/developer-guide/floating-point.md b/docs/developer-guide/math/floating-point.md similarity index 100% rename from docs/modules/core/developer-guide/floating-point.md rename to docs/developer-guide/math/floating-point.md diff --git a/docs/modules/core/concepts/homogeneous-coordinates.md b/docs/developer-guide/math/homogeneous-coordinates.md similarity index 100% rename from docs/modules/core/concepts/homogeneous-coordinates.md rename to docs/developer-guide/math/homogeneous-coordinates.md diff --git a/docs/modules/core/concepts/rotations.md b/docs/developer-guide/math/rotations.md similarity index 61% rename from docs/modules/core/concepts/rotations.md rename to docs/developer-guide/math/rotations.md index 5982ae5b..3ca81496 100644 --- a/docs/modules/core/concepts/rotations.md +++ b/docs/developer-guide/math/rotations.md @@ -1,18 +1,6 @@ # 3D Rotations -> This article is a work in progress. - -math.gl provides a "standard 3D library complement" of mathematical classes for handling rotations in 2D and 3D, such as classes for manipulating `Euler` angles and `Quaternion`s. As in any 3D math library, the key goals are enabling applications to easily and intuitively specify (parametrize) rotations, combine them with other rotations and other transformations, and ultimately transform points with the rotations or resulting transformations. - -While math.gl is intended to help programmers' implement the typical 3D application's rotation functionality with a minimum amount of knowledge, and does not even attempt to support rotations in more than 3 dimensions, it should be pointed out that the mathematical treatment of rotations can be very complicated. For some context on this see the background section at the end of this article. - -### Properties of 3D Rotations - -- In contrast to 2D rotations, 3D rotations are not order-independent, meaning that applying the same two rotations in different order will often yield different results. -- However, by [Euler's Rotation Theorem](https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem), two 3D rotations around the origin can always be expressed as (combined into) another single 3D rotation around the origin. -- A 3D rotation requires a minimum of three values to be fully specified (and even then can require careful definitions of which conventions are used). - -Also, a simple observation: Rotations around arbitrary points can be treated as rotations around the origin simply by applying a translation before the rotation, and the inverse translation after the rotation. Therefore, for simplicity, this discussion focuses solely on rotations around the origin. +The math.gl core module aims to provide the standard "3D math library" arsenal of mathematical tools. This includes tools for handling rotations in 2D and 3D via `Euler` angles, `Quaternion`s and 4x4 matrix operations. As in any 3D math library, the key goals are enabling applications to easily and intuitively specify (parametrize) rotations, combine them with other rotations and other transformations, and ultimately transform points with the rotations or resulting transformations. ## Parametrizing 3D Rotations @@ -43,7 +31,7 @@ Because of the variability, a good approach is often to be extremely careful whe ### Unit Quaternions -"Unit quaternions" are normally the best representation for "manipulation" of 3D rotations. Manpulation here mainly refers to the "composition" or "addition" and interpolation of rotations. +"Unit quaternions" are normally the best representation for "manipulation" of 3D rotations. Manipulation here mainly refers to the "composition" or "addition" and interpolation of rotations. Note that unit quaternions are simply quaternions of norm (or length) equal to `1`, and while a general quaternion (as the name suggests) contains four components, a unit quaternion needs only three values to be fully specified. @@ -55,7 +43,9 @@ Interpolation of quaternions is done using Spherical Linear intERPolation (aka S ## Rotation Matrices -When combining rotations with other transformations (translations, scalings, projections etc), 4x4 matrices are the representation of choice. +Rotations around arbitrary points can be treated as rotations around the origin simply by applying a translation before the rotation, and the inverse translation after the rotation. + +Thus, when combining rotations with other transformations (translations, scalings, projections etc), 4x4 matrices are the representation of choice. ## Properties of Rotation Matrices @@ -109,22 +99,23 @@ Calculate the quaternion that represents the rotation you want to apply (e.g. mo ## Background: Rotations are Complicated -If you are new to working with rotations and the amount of complications outlined in this article seem overwhelming, take some comfort in the fact that rotations in three and higher dimensional spaces are indeed quite complicated to treat mathematically. +If you are new to working with 3D rotations it can be good to have an awareness of how they differ mathematically from 2D rotations -As an example, several fundamental properties of rotations are highly dependent on the number of dimensions involved. To help the reader who has not worked extensively with rotations build some "intuition" for the fact that 3D rotations are non-trivial, the following summary shows how the nice, structured properties of 2D rotations gradually disappear as the number of dimensions increase: - -- In two dimensions, rotations are highly structured and intuitive: +In two dimensions, rotations represent a highly structured and intuitive set of operations: - A series of 2D rotations can be applied in any order (they commute). + - The combination of two 2D rotations can always be expressed as another single rotation (simply by taking the sum of the angles of the two rotations). - Any 2D rotation can be fully parametrized by a single value (the "angle"). - The combination of two 2D rotations can always be expressed as another single rotation (simply by taking the sum of the angles of the two rotations). -- In three dimensions rotation start to loose some structure: - _ In 3D, rotations are no longer order-independent (they are not commutative), meaning that applying the same two rotations in different order will often yield different results. - _ However, by [Euler's Rotation Theorem](https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem), two 3D rotations around the origin can still always be expressed as (combined into) another single 3D rotation around the origin. \* Also, a 3D rotation requires not two, but a minimum of three values to be fully specified. -- To give some contrast, in four and higher dimensions: - - Naturally, rotations still no longer commutative. - - And worse: Euler's Rotation Theorem no longer holds. There are now two different types of basic rotations, and the combination of two rotations will in general not result in another "rotation", but another, more complex transformation. - - In addition, the number of parameters (degrees of freedom) required to fully specify a rotation grows with mind-boggling rapidity, as 2^(n-1) - 1, meaning that e.g. a "21 dimensional rotation" would require over one million values to be fully specified! +However, in three dimensions, rotations start to loose some "structure": + - In 3D, rotations are no longer order-independent (they are not commutative), meaning that applying the same two rotations in different order will often yield different results. + - However, by [Euler's Rotation Theorem](https://en.wikipedia.org/wiki/Euler%27s_rotation_theorem), two 3D rotations around the origin can still always be expressed as (combined into) another single 3D rotation around the origin. + - Also, a 3D rotation requires not two, but three values to be fully specified. + +While math.gl does not support rotations in four and higher dimensions, it should be no surprised that rotations continue to "loose structure" as the number of dimensions increase: + - Higher dimension rotations are also not commutative. + - Euler's Rotation Theorem no longer holds. There are now two different "types" of basic rotations, and the combination of two rotations will in general not even result in another "rotation", but another, more complex transformation. + - In addition, the number of parameters (degrees of freedom) required to fully specify a rotation grows with mind-boggling rapidity, as `2^(n-1) - 1`, (meaning that e.g. a "21 dimensional rotation" would require over one million values to be fully specified). + ## Background: More on Euler Angles [Euler angle values](https://en.wikipedia.org/wiki/Euler_angles) @@ -138,4 +129,4 @@ As an example, several fundamental properties of rotations are highly dependent ## Remarks - In this article, the word "axes" represents the plural of a (coordinate) "axis" (normally, the word "axes" refers to the X, Y and Z coordinate axes). -- **Note** that one of the most efficient way to specify rotations is to use the Euler-Rodrigues parameters, which has some of the quaternion representation without requiring the introduction of quaternion algebra. math.gl does not directly support this representation though although the vector/angle can easily be converted. +- **Note** that one of the most efficient way to specify rotations is to use the Euler-Rodrigues parameters, which has some of the quaternion representation without requiring the introduction of quaternion algebra. math.gl does not directly support this representation although the vector/angle can easily be converted. diff --git a/docs/modules/core/developer-guide/transformations.md b/docs/developer-guide/math/transformations.md similarity index 100% rename from docs/modules/core/developer-guide/transformations.md rename to docs/developer-guide/math/transformations.md diff --git a/docs/modules/core/developer-guide/view-and-projection.md b/docs/developer-guide/math/view-and-projection.md similarity index 82% rename from docs/modules/core/developer-guide/view-and-projection.md rename to docs/developer-guide/math/view-and-projection.md index 05c3c012..8f4ed705 100644 --- a/docs/modules/core/developer-guide/view-and-projection.md +++ b/docs/developer-guide/math/view-and-projection.md @@ -1,11 +1,11 @@ -## View and Projection Matrices +# View and Projection Matrices -One of the major functions of any 3D math library is to let applications create view and projection matrices to enable positioning of the viewer in a 3D world and projection of a field-of-view onto a flat "screen". - -## View and Projection Matrices +One of the major functions of any 3D math library is to let applications create view and projection matrices to enable positioning of the viewer in a 3D world and projection of 3D geometries via a field-of-view onto a flat "screen". To set up a 4x4 view projection matrix you need a view matrix (specifying the position, direction and orientation of the camera) and a projection matrix (specifying the characteristics of the camera such as its field of view etc). +## View Matrices + The purpose of the view matrix is to translate and rotate your world coordinates so that the eye is located in the origin `[0, 0, 0]`, looking down the positive `Z` axis, rotated so that the right direction is `up`. This is called the "view coordinate system". The purpose of the projection matrix is to transform from view coordinates to "clipspace" coordinates (which is the only coordinate system that the GPU can work directly with). If a point is between `-1` and `1` (after `w` scaling) in clipspace, it will be rendered. The `z` coordinate in clipspace is also scaled (using 'near' and 'far' planes) and if between `-1` and `1` it is used for depth test. @@ -22,7 +22,11 @@ Normally positions are transformed by the view matrix. If doing work (e.g. light ## Projection Matrices -Projection matrices typically show everything inside a frustum (truncated pyramid) or a cube in the view space. Their job is to "scale" or "skew" the geometry inside this virtual shape into the clipspace cube, which is the coordinate system the GPU takes as input. +A perspective projection typically shows everything inside a frustum (truncated pyramid) or a cube in the view space. Their job is to "scale" or "skew" the geometry inside this virtual shape into the clipspace cube, which is the coordinate system the GPU takes as input. + +This projection matrices map your geometry into a "normalized box" where `x` and `y` values of `-1` and `1` represent the bounds of your screen or frame buffer. + +Projection matrices can also be ortographic, meaning that 3D objects are mapped via parallel lines onto the screen, rather than via a frustum. ### Perspective Projection Matrix @@ -30,7 +34,7 @@ To create a projection matrix use: - `Matrix4.perspective({fov, aspect, near, far})` -### Creating an Orthographic Projection Matrix +### Orthographic Projection Matrix math.gl provides the traditional function create an orhtographic projection matrix by providing the "box" extents: @@ -46,7 +50,7 @@ In applications it is not unusual to want to offer both perspective and orthogra ## About Projection Matrices -An ortograhic projection matrix essentially just scales your view to show everything within a box. As can be seen in the matrix below, it just centers your view between the bounds of the box, and scales your positions so that the box limits fall on -1 and +1 in each direction. It also does an inversion of the X and Y coordinates. +An ortograhic projection matrix scales your view to show everything within a box. As can be seen in the matrix below, it centers your view between the bounds of the box, and scales your positions so that the box limits fall on -1 and +1 in each direction. It also does an inversion of the X and Y coordinates. @@ -119,4 +123,4 @@ TBA ## Remarks -- As always, matrices are presented here in row major notation, however math.gl stores them internally in column major format to match WebGL requirements. +- As always, matrices are presented here in row major notation, however math.gl stores them internally in column major format to match WebGL conventions. diff --git a/docs/modules/core/developer-guide/performance.md b/docs/developer-guide/performance.md similarity index 100% rename from docs/modules/core/developer-guide/performance.md rename to docs/developer-guide/performance.md diff --git a/docs/docs-sidebar.json b/docs/docs-sidebar.json index c7292044..e3eb7e0f 100644 --- a/docs/docs-sidebar.json +++ b/docs/docs-sidebar.json @@ -5,8 +5,7 @@ "items": [ "README", "whats-new", - "upgrade-guide", - "roadmap" + "upgrade-guide" ] }, { @@ -18,34 +17,37 @@ "label": "Basics", "items": [ "developer-guide/get-started", - "modules/core/developer-guide/debugging", - "modules/core/developer-guide/floating-point", - "modules/core/developer-guide/performance", - "modules/core/developer-guide/external-frameworks" + "developer-guide/debugging", + "developer-guide/performance", + "developer-guide/external-frameworks" ] }, { "type": "category", "label": "3D Math", "items": [ - "modules/core/developer-guide/transformations", - "modules/core/developer-guide/view-and-projection" + "developer-guide/core/transformations", + "developer-guide/core/view-and-projection", + "developer-guide/core/homogeneous-coordinates", + "developer-guide/core/coordinate-systems", + "developer-guide/core/rotations", + "developer-guide/core/floating-point" ] }, { "type": "category", "label": "Geospatial Math", "items": [ - "developer-guide/geospatial-models", - "modules/web-mercator/developer-guide/about-coordinates", - "modules/web-mercator/developer-guide/offset-projection-accuracy" + "developer-guide/geospatial/geospatial-models", + "developer-guide/geospatial/dggs", + "developer-guide/web-mercator/about-coordinates", + "developer-guide/web-mercator/offset-projection-accuracy" ] }, { "type": "category", "label": "DGGS Math", "items": [ - "developer-guide/dggs" ] } ] @@ -177,14 +179,5 @@ ] } ] - }, - { - "type": "category", - "label": "Concepts", - "items": [ - "modules/core/concepts/homogeneous-coordinates", - "modules/core/concepts/coordinate-systems", - "modules/core/concepts/rotations" - ] } ] diff --git a/docs/modules/core/wip/using-vectors.md.disabled b/docs/modules/core/wip/using-vectors.md.disabled deleted file mode 100644 index 6abfc3d7..00000000 --- a/docs/modules/core/wip/using-vectors.md.disabled +++ /dev/null @@ -1,30 +0,0 @@ -# About the Vector Classes (WIP) - -> This document is Work-In-Progress. - -Two, three and four dimensional vector classes - -## Vector2, Vector3, Vector4 Methods - -| **Method** | **Description** | -| ------------- | ------------------------------------------------------------------- | -| `constructor` | Creates a Vector | -| `ELEMENTS` | Get the dimensionality of the vector | -| `x` | Set/get x component | -| `y` | Set/get y component | -| `z` | Set/get z component (`Vector3` and `Vector4` only) | -| `w` | Set/get w component (`Vector4` only) | -| `set` | Set values | -| `add` | Vectors addition | -| `subtract` | Vectors subtraction | -| `multiply` | Vectors multiplication | -| `divide` | Vectors division | -| `scale` | Scales a Vector by a scalar number | -| `scaleAndAdd` | Adds two vectors after scaling the second operand by a scalar value | -| `negate` | Negate a vector | -| `inverse` | Inverse a vector (`Vector3` and `Vector4` only | -| `normalize` | Normalize a vector | -| `dot` | Dot product of two vectors | -| `cross` | Cross product of two vectors (`Vector3` only) | -| `lerp` | Linear interpolation between two Vector | -| `operation` | Apply general operations on all vectors | diff --git a/docs/modules/web-mercator/developer-guide/about-coordinates.md b/docs/modules/web-mercator/developer-guide/about-coordinates.md deleted file mode 100644 index df7d27ae..00000000 --- a/docs/modules/web-mercator/developer-guide/about-coordinates.md +++ /dev/null @@ -1,41 +0,0 @@ -# Web Mercator Coordinates - -| Coordinates | Description | -| ----------- | ------------------------------------- | -| LngLat | `[lng, lat, alt]` on earth | -| World | `[x, y, z]` on the Web Mercator plane | -| Pixels | `[x, y, depth]` on screen | - -### LngLat Coordinates - -LngLat coordinates are specified in -`[longitude, latitude, elevation]` where longitude and latitude are in degrees from Greenwich meridian and the equator respectively, and altitude is in meters above sea level. - -Notes: - -- Order is `[lng, lat]` (it can help to think of them as `[x, y]` to remember the order). -- lng goes from -180 to 180. -- lat goes from -85.051129 to 85.051129. - -The reason for the latitude cutoff is that the cylindrical mercator projection projects the earth sphere onto an infinitely tall strip, with the poles being projected at infinity. The reason that the cutoff is at ~85 degrees is that cutting off at this value makes the remaining projected area into a square (which at zoom 0 is projected onto 512x512 "pixels"). For details see e.g. https://en.wikipedia.org/wiki/Web_Mercator. - -### World Coordinates - -World coordinates specifies a location on the linear Web Mercator plane. Each unit is a "pixel" on the Web Mercator tile. It is unique for each lngLat location at a specific zoom level. `[x, y, z]` corresponds to `[longitude, latitude, elevation]` in the LngLat system. - -### Pixel Coordinates - -Pixel coordinates specifies a point on screen in the format of `[x, y, z]` where x and y are in pixels on screen and `z` is pixel depth, normally between `-1` and `1`. - -By default, the pixel coordinate system of the viewport is defined with the origin in the top left, where the positive x-axis goes right, and the positive y-axis goes down. That is, the top left corner is `[0, 0]` and the bottom right corner is `[width - 1, height - 1]`. The `project`/`unproject` functions have a flag that can reverse this convention. - -### Additional Notes - -- Per cartographic tradition, all angles including `latitude`, `longitude`, - `pitch` and `bearing` are specified in degrees, not radians. - -- It is possible to query the PerspectiveMercatorViewport for a meters per pixel scale. - Note that that distance scales are latitude dependent under - web mercator projection [see](http://wiki.openstreetmap.org/wiki/Zoom_levels), - so scaling will depend on the viewport center and any linear scale factor - should only be expected to be locally correct. diff --git a/docs/modules/web-mercator/developer-guide/offset-projection-accuracy.md b/docs/modules/web-mercator/developer-guide/offset-projection-accuracy.md deleted file mode 100644 index 7dff72fb..00000000 --- a/docs/modules/web-mercator/developer-guide/offset-projection-accuracy.md +++ /dev/null @@ -1,87 +0,0 @@ -# Accuracy of Offset Projection - -`getDistanceScales` offers a cheap way to project lng/lat or meter offset to pixels. It is useful when using the GPU to project a cluster of coordinates near an origin point, without suffering the precision loss of WebGL. - -This article discusses the usage and accuracy of the distance scales. - -# Meter offset to pixels - -Regular meter offset to pixels projection: - -``` -uniform vec3 unitsPerMeter; -vec3 meters_offset_to_pixels_offset(vec3 meters) { - return meters * unitsPerMeter; -} -``` - -When `getDistanceScales` is called with flag `highPrecision: true`, it generates additional multipliers to compensate for precision loss over latitude change. More precise meter offset to pixels projection: - -``` -uniform vec3 unitsPerMeter; -uniform vec3 unitsPerMeter2; -vec3 meters_offset_to_pixels_offset_adjusted(vec3 meters) { - return meters * (unitsPerMeter + unitsPerMeter2 * meters.y); -} -``` - -Accuracy at San Francisco (37N, z = 12): - -| R | X unadjusted | X adjusted | -| ------------ | ---------------------------- | ---------------------------- | -| 100 meters | off by -0.000 pixels, 0.001% | off by 0.000 pixels, 0.001% | -| 1000 meters | off by -0.008 pixels, 0.012% | off by 0.000 pixels, 0.001% | -| 5000 meters | off by -0.200 pixels, 0.060% | off by 0.002 pixels, 0.001% | -| 10000 meters | off by -0.804 pixels, 0.121% | off by 0.003 pixels, 0.000% | -| 30000 meters | off by -7.277 pixels, 0.366% | off by -0.021 pixels, 0.001% | - -Accuracy at high latitude (75N, z = 12): - -| R | X unadjusted | X adjusted | -| ------------ | ------------------------------ | ---------------------------- | -| 100 meters | off by -0.001 pixels, 0.006% | off by 0.000 pixels, 0.001% | -| 1000 meters | off by -0.130 pixels, 0.061% | off by 0.001 pixels, 0.001% | -| 5000 meters | off by -3.290 pixels, 0.309% | off by -0.001 pixels, 0.000% | -| 10000 meters | off by -13.200 pixels, 0.620% | off by -0.044 pixels, 0.002% | -| 30000 meters | off by -119.884 pixels, 1.877% | off by -1.473 pixels, 0.023% | - -# LngLat offset to pixels - -Regular lng_lat offset to pixels projection: - -``` -uniform vec3 unitsPerDegree; -vec3 lnglat_offset_to_pixels_offset(vec3 lngLatZ) { - return lngLatZ * unitsPerDegree; -} -``` - -When `getDistanceScales` is called with flag `highPrecision: true`, it generates additional multipliers to compensate for precision loss over latitude change. More precise meter offset to pixels projection: - -``` -uniform vec3 unitsPerDegree; -uniform vec3 unitsPerDegree2; -vec3 lnglat_offset_to_pixels_offset_adjusted(vec3 lngLatZ) { - return lngLatZ * (unitsPerDegree + unitsPerDegree2 * lngLatZ.y); -} -``` - -Accuracy at San Francisco (37N, z = 12): - -| R | Y unadjusted | Y adjusted | -| ------------- | ---------------------------- | ---------------------------- | -| 0.001 degrees | off by -0.000 pixels, 0.001% | off by -0.000 pixels, 0.000% | -| 0.01 degrees | off by -0.005 pixels, 0.007% | off by -0.000 pixels, 0.000% | -| 0.05 degrees | off by -0.125 pixels, 0.034% | off by -0.000 pixels, 0.000% | -| 0.1 degrees | off by -0.499 pixels, 0.068% | off by -0.001 pixels, 0.000% | -| 0.3 degrees | off by -4.508 pixels, 0.204% | off by -0.022 pixels, 0.001% | - -Accuracy at high latitude (75N, z = 12): - -| R | Y unadjusted | Y adjusted | -| ------------- | ----------------------------- | ---------------------------- | -| 0.001 degrees | off by -0.001 pixels, 0.003% | off by -0.000 pixels, 0.000% | -| 0.01 degrees | off by -0.081 pixels, 0.034% | off by -0.000 pixels, 0.000% | -| 0.05 degrees | off by -2.038 pixels, 0.172% | off by -0.005 pixels, 0.000% | -| 0.1 degrees | off by -8.172 pixels, 0.345% | off by -0.039 pixels, 0.002% | -| 0.3 degrees | off by -74.258 pixels, 1.046% | off by -1.055 pixels, 0.015% | diff --git a/docs/roadmap.md b/docs/roadmap.md deleted file mode 100644 index 73d9f3cf..00000000 --- a/docs/roadmap.md +++ /dev/null @@ -1,23 +0,0 @@ -# Roadmap - -## 3D Primitives - -- Add a submodule with the geometry primitives from luma.gl. - -### Geometry Processing - -- Provide a library for CPU side geometry processing, for calculating normals, ray casting etc. -- There is initial code in `@loaders.gl/math` that should be cleaned up and moved to math.gl. - -### Improved Columnar Table Support - -- Geometries are essentially columnar tables, emphasize this further to simplify integration with columnar table systems, primarily ArrowJS. - -### GPU Powered Math? - -- TBA - -## Interoperability and Framework Independence - -- An ambition is that math.gl should be able to serve a general purpose 3D math library, enabling the creation of framework-independent 3D and Geospatial code that interoperates with a variety of frameworks. -- math.gl modules (such as geospatial math) should be usable by applications using other frameworks, without having to use the core math.gl classes. diff --git a/docs/table-of-contents.json b/docs/table-of-contents.json deleted file mode 100644 index f8988599..00000000 --- a/docs/table-of-contents.json +++ /dev/null @@ -1,173 +0,0 @@ -{ - "id": "table-of-contents", - "chapters": [ - { - "title": "Overview", - "entries": [ - {"entry": "docs/README"}, - {"entry": "docs/whats-new"}, - {"entry": "docs/upgrade-guide"}, - {"entry": "docs/roadmap"} - ] - }, - { - "title": "Developer Guide", - "chapters": [ - { - "title": "Basics", - "entries": [ - {"entry": "docs/developer-guide/get-started"}, - {"entry": "modules/core/docs/developer-guide/debugging"}, - {"entry": "modules/core/docs/developer-guide/floating-point"}, - {"entry": "modules/core/docs/developer-guide/performance"}, - {"entry": "modules/core/docs/developer-guide/external-frameworks"} - ] - }, - { - "title": "3D Math", - "entries": [ - {"entry": "modules/core/docs/developer-guide/transformations"}, - {"entry": "modules/core/docs/developer-guide/view-and-projection"} - ] - }, - { - "title": "Geospatial Math", - "entries": [ - {"entry": "docs/developer-guide/geospatial-models"}, - {"entry": "modules/web-mercator/docs/developer-guide/about-coordinates"}, - {"entry": "modules/web-mercator/docs/developer-guide/offset-projection-accuracy"} - ] - }, - { - "title": "DGGS Math", - "entries": [ - {"entry": "docs/developer-guide/dggs"} - ] - } - ] - }, - { - "title": "API Reference", - "chapters": [ - { - "title": "@math.gl/types", - "entries": [ - {"entry": "modules/types/docs"}, - {"entry": "modules/types/docs/api-reference/is-array"} - ] - }, - { - "title": "@math.gl/core", - "entries": [ - {"entry": "modules/core/docs"}, - {"entry": "modules/core/docs/api-reference/euler"}, - {"entry": "modules/core/docs/api-reference/math-array"}, - {"entry": "modules/core/docs/api-reference/matrix"}, - {"entry": "modules/core/docs/api-reference/matrix3"}, - {"entry": "modules/core/docs/api-reference/matrix4"}, - {"entry": "modules/core/docs/api-reference/pose"}, - {"entry": "modules/core/docs/api-reference/quaternion"}, - {"entry": "modules/core/docs/api-reference/spherical-coordinates"}, - {"entry": "modules/core/docs/api-reference/utilities"}, - {"entry": "modules/core/docs/api-reference/vector"}, - {"entry": "modules/core/docs/api-reference/vector2"}, - {"entry": "modules/core/docs/api-reference/vector3"}, - {"entry": "modules/core/docs/api-reference/vector4"} - ] - }, - { - "title": "@math.gl/culling", - "entries": [ - {"entry": "modules/culling/docs"}, - {"entry": "modules/culling/docs/api-reference/axis-aligned-bounding-box"}, - {"entry": "modules/culling/docs/api-reference/bounding-sphere"}, - {"entry": "modules/culling/docs/api-reference/bounding-volume"}, - {"entry": "modules/culling/docs/api-reference/culling-volume"}, - {"entry": "modules/culling/docs/api-reference/oriented-bounding-box"}, - {"entry": "modules/culling/docs/api-reference/plane"} - ] - }, - { - "title": "@math.gl/geoid", - "entries": [ - {"entry": "modules/geoid/docs"}, - {"entry": "modules/geoid/docs/api-reference/geoid"}, - {"entry": "modules/geoid/docs/api-reference/parse-pgm"} - ] - }, - { - "title": "@math.gl/geospatial", - "entries": [ - {"entry": "modules/geospatial/docs"}, - {"entry": "modules/geospatial/docs/api-reference/ellipsoid"}, - {"entry": "modules/geospatial/docs/api-reference/helpers"} - ] - }, - { - "title": "@math.gl/polygon", - "entries": [ - {"entry": "modules/polygon/docs/api-reference/clip-polygon"}, - {"entry": "modules/polygon/docs/api-reference/clip-polyline"}, - {"entry": "modules/polygon/docs/api-reference/cut-polygon-by-grid"}, - {"entry": "modules/polygon/docs/api-reference/cut-polyline-by-grid"}, - {"entry": "modules/polygon/docs/api-reference/cut-polygon-by-mercator-bounds"}, - {"entry": "modules/polygon/docs/api-reference/cut-polyline-by-mercator-bounds"}, - {"entry": "modules/polygon/docs/api-reference/polygon"} - ] - }, - { - "title": "@math.gl/proj4", - "entries": [ - {"entry": "modules/proj4/docs"}, - {"entry": "modules/proj4/docs/api-reference/proj4-projection"} - ] - }, - { - "title": "@math.gl/sun", - "entries": [ - {"entry": "modules/sun/docs"}, - {"entry": "modules/sun/docs/api-reference/get-sun"}, - {"entry": "modules/sun/docs/api-reference/get-sun-direction"} - ] - }, - { - "title": "@math.gl/web-mercator", - "entries": [ - {"entry": "modules/web-mercator/docs"}, - {"entry": "modules/web-mercator/docs/api-reference/web-mercator-utils"}, - {"entry": "modules/web-mercator/docs/api-reference/web-mercator-viewport"} - ] - }, - { - "title": "@math.gl/geohash", - "entries": [ - {"entry": "modules/geohash/docs"}, - {"entry": "modules/geohash/docs/api-reference/geohash"} - ] - }, - { - "title": "@math.gl/quadkey", - "entries": [ - {"entry": "modules/quadkey/docs"}, - {"entry": "modules/quadkey/docs/api-reference/quadkey"} - ] - }, - { - "title": "@math.gl/s2", - "entries": [ - {"entry": "modules/s2/docs"}, - {"entry": "modules/s2/docs/api-reference/s2"} - ] - } - ] - }, - { - "title": "Concepts", - "entries": [ - {"entry": "modules/core/docs/concepts/homogeneous-coordinates"}, - {"entry": "modules/core/docs/concepts/coordinate-systems"}, - {"entry": "modules/core/docs/concepts/rotations"} - ] - } - ] -} diff --git a/docs/whats-new.md b/docs/whats-new.md index dcd2b426..72ca2d0c 100644 --- a/docs/whats-new.md +++ b/docs/whats-new.md @@ -51,6 +51,7 @@ Target Release Date: March, 2023 - Three new modules for working with DGGS (Discrete Global Grid System) math. - Node.js v18 is now officially supported. +- Typescript v5 now used **`@math.gl/geohash`** (NEW MODULE) diff --git a/modules/core/src/classes/base/matrix.ts b/modules/core/src/classes/base/matrix.ts index b203d826..35789b56 100644 --- a/modules/core/src/classes/base/matrix.ts +++ b/modules/core/src/classes/base/matrix.ts @@ -56,7 +56,10 @@ export abstract class Matrix extends MathArray { getColumn(columnIndex: number, result: NumArrayT): NumArrayT; getColumn(columnIndex: number): number[]; - getColumn(columnIndex: number, result: number[] = new Array(this.RANK).fill(-0)): number[] { + getColumn( + columnIndex: number, + result: number[] = new Array(this.RANK).fill(-0) + ): number[] { const firstIndex = columnIndex * this.RANK; for (let i = 0; i < this.RANK; ++i) { result[i] = this[firstIndex + i]; diff --git a/modules/core/src/classes/euler.ts b/modules/core/src/classes/euler.ts index 2ed1281a..4bd2aa93 100644 --- a/modules/core/src/classes/euler.ts +++ b/modules/core/src/classes/euler.ts @@ -92,6 +92,7 @@ export class Euler extends MathArray { return this.set(roll, pitch, yaw, Euler.RollPitchYaw); } + // eslint-disable-next-line @typescript-eslint/no-unused-vars fromObject(object: Record): this { throw new Error('not implemented'); // return this.set(object.x, object.y, object.z, object.order); diff --git a/modules/core/src/classes/matrix3.ts b/modules/core/src/classes/matrix3.ts index 18b70454..0a68fb48 100644 --- a/modules/core/src/classes/matrix3.ts +++ b/modules/core/src/classes/matrix3.ts @@ -89,12 +89,14 @@ export class Matrix3 extends Matrix { * @param object * @returns self */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars fromObject(object: {[key: string]: any}): this { return this.check(); } - // Calculates a 3x3 matrix from the given quaternion - // q quat Quaternion to create matrix from + /** Calculates a 3x3 matrix from the given quaternion + * q quat Quaternion to create matrix from + */ fromQuaternion(q: Readonly): this { mat3.fromQuat(this, q); return this.check(); diff --git a/modules/core/src/classes/matrix4.ts b/modules/core/src/classes/matrix4.ts index 1653425b..b05f7ec5 100644 --- a/modules/core/src/classes/matrix4.ts +++ b/modules/core/src/classes/matrix4.ts @@ -203,6 +203,7 @@ export class Matrix4 extends Matrix { * @param object * @returns self */ + // eslint-disable-next-line @typescript-eslint/no-unused-vars fromObject(object: {[key: string]: any}): this { return this.check(); } diff --git a/modules/core/src/lib/common.ts b/modules/core/src/lib/common.ts index bb4acf99..cc4c5fce 100644 --- a/modules/core/src/lib/common.ts +++ b/modules/core/src/lib/common.ts @@ -291,7 +291,8 @@ function round(value: number): number { // If the array has a clone function, calls it, otherwise returns a copy function duplicateArray(array: NumericArray): NumericArray { // @ts-expect-error We check for math.gl class methods - return array.clone ? array.clone() : (new Array(array.length) as number[]); + // eslint-disable-next-line @typescript-eslint/no-unsafe-call + return array.clone ? (array.clone() as NumericArray) : (new Array(array.length) as number[]); } // If the argument value is an array, applies the func element wise, diff --git a/modules/core/src/lib/validators.ts b/modules/core/src/lib/validators.ts index d0af7bcc..1b8c79d8 100644 --- a/modules/core/src/lib/validators.ts +++ b/modules/core/src/lib/validators.ts @@ -35,7 +35,7 @@ export function validateVector(v: NumberArray, length: number): boolean { export function checkNumber(value: unknown): number { if (!Number.isFinite(value)) { - throw new Error(`Invalid number ${value}`); + throw new Error(`Invalid number ${JSON.stringify(value)}`); } return value as number; } diff --git a/modules/s2/src/converters/s2-to-obb-points.ts b/modules/s2/src/converters/s2-to-obb-points.ts index d457fa99..a34ab075 100644 --- a/modules/s2/src/converters/s2-to-obb-points.ts +++ b/modules/s2/src/converters/s2-to-obb-points.ts @@ -1,6 +1,5 @@ // math.gl, MIT license -import {Vector3} from '@math.gl/core'; import {getS2Cell} from '../s2geometry/s2-cell-utils'; import {getS2Region} from './s2-to-region'; import {getS2IndexFromToken} from '../s2-token-functions'; @@ -24,7 +23,7 @@ export type S2HeightInfo = { export function getS2OrientedBoundingBoxCornerPoints( s2token: string, // This can be an S2 key or token heighInfo?: S2HeightInfo -): Vector3[] { +): number[][] { const min: number = heighInfo?.minimumHeight || 0; const max: number = heighInfo?.maximumHeight || 0; @@ -38,17 +37,17 @@ export function getS2OrientedBoundingBoxCornerPoints( const E = region[2]; const N = region[3]; - const points: Vector3[] = []; + const points: number[][] = []; - points.push(new Vector3(W, N, min)); - points.push(new Vector3(E, N, min)); - points.push(new Vector3(E, S, min)); - points.push(new Vector3(W, S, min)); + points.push([W, N, min]); + points.push([E, N, min]); + points.push([E, S, min]); + points.push([W, S, min]); - points.push(new Vector3(W, N, max)); - points.push(new Vector3(E, N, max)); - points.push(new Vector3(E, S, max)); - points.push(new Vector3(W, S, max)); + points.push([W, N, max]); + points.push([E, N, max]); + points.push([E, S, max]); + points.push([W, S, max]); return points; } diff --git a/package.json b/package.json index 52e94de2..be985563 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,7 @@ "babel-plugin-transform-builtin-extend": "^1.1.2", "ocular-dev-tools": "2.0.0-alpha.3", "pre-commit": "^1.2.2", - "typescript": "^4.9.4" + "typescript": "^5.0.4" }, "resolutions_notes": [ "Note: tape 4.12 and higher no longer compares 0 and -0 equally...", diff --git a/website/docusaurus.config.js b/website/docusaurus.config.js index 66a61404..a25b8ec6 100644 --- a/website/docusaurus.config.js +++ b/website/docusaurus.config.js @@ -96,6 +96,29 @@ const config = { breadcrumbs: false, docItemComponent: resolve('./src/components/example/doc-item-component.jsx') }, + ], + [ + require.resolve('@cmfcmf/docusaurus-search-local'), + { + // Options here + } + ], + [ + '@docusaurus/plugin-client-redirects', + { + createRedirects(existingPath) { + // docs/modules/*/api-reference <= modules/*/docs/api-reference + if (existingPath.includes('/docs/modules/')) { + return [ + existingPath + .replace('/docs/modules/', '/modules/') + // Replaces api-reference if present + .replace('/api-reference/', '/docs/api-reference/') + ]; + } + return undefined; // Return a falsy value: no redirect created + } + } ] ], diff --git a/website/package.json b/website/package.json index 69f8ea1d..a37c7c90 100644 --- a/website/package.json +++ b/website/package.json @@ -15,6 +15,7 @@ "deploy": "docusaurus deploy" }, "dependencies": { + "@algolia/autocomplete-js": "^1.8.3", "@loaders.gl/i3s": "^3.3.1", "@loaders.gl/las": "^3.3.1", "@loaders.gl/obj": "^3.3.1", @@ -22,25 +23,21 @@ "@material-ui/core": "^4.10.2", "@material-ui/icons": "^4.9.1", "@material-ui/lab": "^4.0.0-alpha.57", - "@turf/turf": "^6.5.0", - "brace": "^0.11.1", "d3-color": "^3.1.0", - "d3-hierarchy": "^2.0.0", "d3-request": "^1.0.6", - "d3-scale": "^3.2.1", - "expr-eval": "^2.0.2", "mapbox-gl": "^2.0.0", "maplibre-gl": "^2.4.0", "react": "^18.0.0", - "react-ace": "^6.1.4", "react-dom": "^18.0.0", "react-map-gl": "^7.0.0", "styled-components": "^5.3.3" }, "devDependencies": { - "@docusaurus/core": "^2.2.0", - "@docusaurus/plugin-content-docs": "^2.2.0", - "@docusaurus/preset-classic": "^2.2.0", + "@cmfcmf/docusaurus-search-local": "^1.0.0", + "@docusaurus/core": "^2.4.0", + "@docusaurus/plugin-client-redirects": "^2.4.0", + "@docusaurus/plugin-content-docs": "^2.4.0", + "@docusaurus/preset-classic": "^2.4.0", "@mdx-js/react": "^1.6.22", "babel-plugin-styled-components": "^2.0.0", "prism-react-renderer": "^1.2.1", diff --git a/yarn.lock b/yarn.lock index 05e33259..bacb8125 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12089,10 +12089,10 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= -typescript@^4.9.4: - version "4.9.4" - resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.9.4.tgz#a2a3d2756c079abda241d75f149df9d561091e78" - integrity sha512-Uz+dTXYzxXXbsFpM86Wh3dKCxrQqUcVMxwU54orwlJjOpO3ao8L7j5lH+dWfTwgCwIuM9GQ2kvVotzYJMXTBZg== +typescript@^5.0.4: + version "5.0.4" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.0.4.tgz#b217fd20119bd61a94d4011274e0ab369058da3b" + integrity sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw== typescript@~4.6.0: version "4.6.4"