h3o-wasm
Version:
An experimental WASM package from Rust implementation of the H3 geospatial indexing system
143 lines (114 loc) • 5.77 kB
Markdown
# h3o-wasm
[](https://crates.io/crates/h3o)
[](https://docs.rs/h3o)
[](https://github.com/HydroniumLabs/h3o/actions)
[](https://app.codecov.io/gh/HydroniumLabs/h3o)
[](https://opensource.org/licenses/BSD-3-Clause)
A [Rust](https://rustlang.org) implementation of the [H3](https://h3geo.org) geospatial indexing system, compiled to
WebAssembly for use in JavaScript projects.
## Design
**Experimental**: this package compiles some functions from `h3o` to WASM (see check-list). Performance might be slower than the
reference [`h3-js`](https://github.com/uber/h3-js) implementation in browsers, as the reference implementation compiles the C code to asm.js, which is already
optimized for the browser. Performance has not been tested in Node.js yet, but it should be faster than the reference. I will add some testing soon.
I'm adding the functions one by one, as time permits, but it should be complete soon. See available methods below.
H3 should also be easy to compile to Wasm, using the emscripten toolchain, changing the flags to use the wasm target instead of asm.js.
`h3o` is a Rust reimplementation of the H3 geospatial indexing system, designed with the following goals:
- Leverage Rust's strong typing for safer usage.
- Provide a 100% Rust solution, eliminating C dependencies for painless compilation to WebAssembly and easier link-time
optimization.
- Match or exceed the performance of the reference H3 library.
`h3o-wasm` exposes `h3o` functions to Javascript
# Available methods and properties
The goal is to provide equivalent functions to all H3 functions
h3o
- [ ] .UNITS
- [ ] .h3IndexToSplitLong(h3Index) ⇒ SplitLong
- [ ] .splitLongToH3Index(lower, upper) ⇒ H3Index
- [x] .isValidCell(h3Index) ⇒ boolean
- [x] .isPentagon(h3Index) ⇒ boolean
- [x] .isResClassIII(h3Index) ⇒ boolean
- [x] .getBaseCellNumber(h3Index) ⇒ number
- [ ] .getIcosahedronFaces(h3Index) ⇒ Array.<number>
- [x] .getResolution(h3Index) ⇒ number
- [x] .latLngToCell(lat, lng, res) ⇒ H3Index
- [x] .cellToLatLng(h3Index) ⇒ CoordPair
- [x] .cellToBoundary(h3Index, [formatAsGeoJson]) ⇒ Array.<CoordPair>
- [x] .cellToParent(h3Index, res) ⇒ H3Index
- [x] .cellToChildren(h3Index, res) ⇒ Array.<H3Index>
- [ ] .cellToChildrenSize(h3Index, res) ⇒ number
- [x] .cellToCenterChild(h3Index, res) ⇒ H3Index
- [ ] .cellToChildPos(h3Index, parentRes) ⇒ number
- [ ] .childPosToCell(childPos, h3Index, childRes) ⇒ H3Index
- [ ] .gridDisk(h3Index, ringSize) ⇒ Array.<H3Index>
- [ ] .gridDiskDistances(h3Index, ringSize) ⇒ Array.<Array.<H3Index>>
- [ ] .gridRingUnsafe(h3Index, ringSize) ⇒ Array.<H3Index>
- [x] .polygonToCells(coordinates, res, [isGeoJson]) ⇒ Array.<H3Index>
- [ ] .cellsToMultiPolygon(h3Indexes, [formatAsGeoJson]) ⇒ Array.<Array.<Array.<CoordPair>>>
- [ ] .compactCells(h3Set) ⇒ Array.<H3Index>
- [ ] .uncompactCells(compactedSet, res) ⇒ Array.<H3Index>
- [ ] .areNeighborCells(origin, destination) ⇒ boolean
- [ ] .cellsToDirectedEdge(origin, destination) ⇒ H3Index
- [ ] .getDirectedEdgeOrigin(edgeIndex) ⇒ H3Index
- [ ] .getDirectedEdgeDestination(edgeIndex) ⇒ H3Index
- [ ] .isValidDirectedEdge(edgeIndex) ⇒ boolean
- [ ] .directedEdgeToCells(edgeIndex) ⇒ Array.<H3Index>
- [ ] .originToDirectedEdges(h3Index) ⇒ Array.<H3Index>
- [ ] .directedEdgeToBoundary(edgeIndex, [formatAsGeoJson]) ⇒ Array.<CoordPair>
- [ ] .gridDistance(origin, destination) ⇒ number
- [ ] .gridPathCells(origin, destination) ⇒ Array.<H3Index>
- [ ] .cellToLocalIj(origin, destination) ⇒ CoordIJ
- [ ] .localIjToCell(origin, coords) ⇒ H3Index
- [ ] .greatCircleDistance(latLng1, latLng2, unit) ⇒ number
- [x] .cellArea(h3Index, unit) ⇒ number
- [x] .edgeLength(edge, unit) ⇒ number
- [ ] .getHexagonAreaAvg(res, unit) ⇒ number
- [ ] .getHexagonEdgeLengthAvg(res, unit) ⇒ number
- [ ] .cellToVertex(h3Index, vertexNum) ⇒ H3Index
- [ ] .cellToVertexes(h3Index) ⇒ Array.<H3Index>
- [ ] .vertexToLatLng(h3Index) ⇒ CoordPair
- [ ] .isValidVertex(h3Index) ⇒ boolean
- [ ] .getNumCells(res) ⇒ number
- [ ] .getRes0Cells() ⇒ Array.<H3Index>
- [ ] .getPentagons(res) ⇒ Array.<H3Index>
- [ ] .degsToRads(deg) ⇒ number
- [ ] .radsToDegs(rad) ⇒ number
- [ ] .H3Index : string
- [ ] .H3IndexInput : string | Array.<number>
- [ ] .CoordIJ
- [ ] .H3Error
- [ ] .CoordPair : Array.<number>
- [ ] .SplitLong : Array.<number>
## Installation
The `h3o-wasm` package is distributed via npm.
```bash
npm install h3o-wasm
```
## Building
* Install the rust toolchain in order to have cargo installed by following
[this](https://www.rust-lang.org/tools/install) guide.
* run `cargo install wasm-bindgen-cli`
* run `wasm-pack build --target web`
## Usage
```javascript
import init, * as h3o from "h3o-wasm";
async function run() {
await init(); // Initialize the WASM module
const h3Index = h3o.latLngToCell(37.3615593, -122.0553238, 7);
console.log("H3 Index: ", h3Index);
}
run();
```
### Testing performance (browser)
An example file is available in the root of the repository, to run it you can use a simple http server
like `http-server`:
```bash
npm -g install http-server
http-server .
```
## Why this name?
Rust is an iron oxide.
A Rust version of H3 is an H3 oxide, in other word $H_3O$ (a.k.a hydronium).
Chemically speaking this is wrong ( $H_3O$ is produced by protonation of
$H_2O$, not oxidation of $H_3$), but ¯\\_(ツ)_/¯
## License
[BSD 3-Clause](./LICENSE)