Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 5 additions & 4 deletions website/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,9 @@
"@mdx-js/react": "^1.6.22",
"deck.gl": "^9.0.12",
"docusaurus-lunr-search": "^3.6.0",
"geojson2h3": "^1.2.0",
"global": "^4.4.0",
"h3-js": "4.2.1",
"h3-js": "4.4.0",
"h3-jsv3": "npm:h3-js@^3.7.1",
"mapbox-gl": "^3.4.0",
"prettier": "^3.2.5",
Expand All @@ -33,7 +34,8 @@
"rehype-katex": "4",
"remark-math": "3",
"styled-components": "^6.1.9",
"use-location-state": "^3.1.2"
"use-location-state": "^3.1.2",
"wkt": "^0.1.1"
},
"browserslist": {
"production": [
Expand All @@ -50,6 +52,5 @@
"volta": {
"node": "16.18.1",
"yarn": "1.22.10"
},
"packageManager": "yarn@1.22.22+sha512.a6b2f7906b721bba3d67d4aff083df04dad64c399707841b7acf00f6b133b7ac24255f2652fa22ae3534329dc6180534e98d17432037ff6fd140556e2bb3137e"
}
}
63 changes: 61 additions & 2 deletions website/src/components/explorer/index.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ import { useQueryState } from "use-location-state";
import { SelectedHexDetails } from "./details";
import { ExplorerMap } from "./map";
import { WhereAmIButton } from "./where-am-i";
import geojson2h3 from "geojson2h3";
import wkt from "wkt";

const CELL_COUNT_THRESHOLD = 50;

function fullyTrim(str) {
if (!str) {
Expand Down Expand Up @@ -63,14 +67,68 @@ function maybePrefixedHexCell(input) {
return null;
}

function geoJsonToCells(geoJson) {
// TODO: Handle point geometries, lines, etc. Only polygons and multipolygons supported.
if (geoJson.type === "Polygon" || geoJson.type === "MultiPolygon") {
geoJson = {
type: "Feature",
geometry: geoJson,
};
}

for (let res = 0; res < 16; res++) {
const cells = geojson2h3.featureToH3Set(geoJson, res);
if (cells.length > CELL_COUNT_THRESHOLD || res === 15) {
return {
splitUserInput: cells,
showCellId: false,
inputGeoJson: geoJson,
};
}
}
return null;
}

function tryParsePolygonInput(input) {
try {
const parsed = JSON.parse(input);
if (parsed && parsed.type) {
const geoJsonResult = geoJsonToCells(parsed);
if (geoJsonResult) {
return geoJsonResult;
}
}
} catch {
// No-op
}

try {
const parsed = wkt.parse(input);
if (parsed && parsed.type) {
const wktResult = geoJsonToCells(parsed);
if (wktResult) {
return wktResult;
}
}
} catch {
// No-op
}
}

function doSplitUserInput(userInput) {
if (userInput) {
// Acceptable inputs, in order of test preference:
// GeoJSON
// WKT
// Valid hexadecimal cell ID
// Valid hexadecimal cell ID, prefixed by 0x
// Valid decimal cell ID
// lat,lng coordinate pairs
// TODO: support WKT, GeoJSON inputs here too. Those would consume the entire input

const resultPolygon = tryParsePolygonInput(userInput);
if (resultPolygon) {
return resultPolygon;
}

let showCellId = false;
const unwrapAnyArray = fullyUnwrap(userInput);
Expand Down Expand Up @@ -131,7 +189,7 @@ function zoomToResolution(zoom) {
export default function HomeExporer({ children }) {
const [userInput, setUserInput] = useQueryState("hex", "");

const { splitUserInput, showCellId } = useMemo(
const { splitUserInput, showCellId, inputGeoJson } = useMemo(
() => doSplitUserInput(userInput),
[userInput],
);
Expand Down Expand Up @@ -185,6 +243,7 @@ export default function HomeExporer({ children }) {
<DemoContainer>
<ExplorerMap
userInput={splitUserInput}
inputGeoJson={inputGeoJson}
userValidHex={userValidHex}
objectOnClick={objectOnClick}
coordinateOnClick={coordinateOnClick}
Expand Down
37 changes: 27 additions & 10 deletions website/src/components/explorer/map.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,12 @@ import { Map } from "react-map-gl";
import DeckGL from "@deck.gl/react";
import { H3HexagonLayer } from "@deck.gl/geo-layers";
import { WebMercatorViewport, FlyToInterpolator, MapView } from "@deck.gl/core";
import { getRes0Cells, uncompactCells, cellToBoundary } from "h3-js";
import { cellToBoundary } from "h3-js";
import useDocusaurusContext from "@docusaurus/useDocusaurusContext";
import { MOBILE_CUTOFF_WINDOW_WIDTH } from "../common";
import { useHex } from "./useHex";
import { GeoJsonLayer } from "deck.gl";
import { PathStyleExtension } from "@deck.gl/extensions";

const INITIAL_VIEW_STATE = {
longitude: -74.012,
Expand All @@ -30,6 +32,7 @@ const MAP_STYLE = "mapbox://styles/mapbox/light-v11";

export function ExplorerMap({
userInput = [],
inputGeoJson = null,
userValidHex = false,
initialViewState = INITIAL_VIEW_STATE,
mapStyle = MAP_STYLE,
Expand All @@ -41,15 +44,6 @@ export function ExplorerMap({
useState(initialViewState);
const [deckLoaded, setDeckLoaded] = useState(false);
const deckRef = useRef();
const res0Cells = useMemo(() => getRes0Cells().map((hex) => ({ hex })), []);
const res1Cells = useMemo(
() => uncompactCells(getRes0Cells(), 1).map((hex) => ({ hex })),
[],
);
const res2Cells = useMemo(
() => uncompactCells(getRes0Cells(), 2).map((hex) => ({ hex })),
[],
);
const [windowWidth, setWindowWidth] = useState(null);

useEffect(() => {
Expand Down Expand Up @@ -132,6 +126,28 @@ export function ExplorerMap({
addSelectedHexes,
});

const inputGeoJsonLayers = inputGeoJson
? [
new GeoJsonLayer({
id: "userinput",
data: inputGeoJson,
getFillColor: [0, 0, 0],
getLineColor: [100, 100, 100],
getLineWidth: 1,
lineWidthMinPixels: 1,
lineWidthUnits: "pixels",
pickable: false,
stroked: true,
filled: false,
// @ts-expect-error
getDashArray: [5, 1],
dashJustified: true,
dashGapPickable: true,
extensions: [new PathStyleExtension({ dash: true })],
}),
]
: [];

const layers = userValidHex
? [
new H3HexagonLayer({
Expand All @@ -150,6 +166,7 @@ export function ExplorerMap({
filled: true,
getFillColor: [0, 0, 0, 30],
}),
...inputGeoJsonLayers,
]
: backgroundHexLayers;

Expand Down
25 changes: 21 additions & 4 deletions website/yarn.lock
Original file line number Diff line number Diff line change
Expand Up @@ -5274,6 +5274,13 @@ geojson-vt@^3.2.1:
resolved "https://registry.yarnpkg.com/geojson-vt/-/geojson-vt-3.2.1.tgz#f8adb614d2c1d3f6ee7c4265cad4bbf3ad60c8b7"
integrity sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==

geojson2h3@^1.2.0:
version "1.2.0"
resolved "https://registry.yarnpkg.com/geojson2h3/-/geojson2h3-1.2.0.tgz#4ce580f209d3131aacf3faf5927fc44c95ae0c1d"
integrity sha512-UF8JLT4mPHSSKFWibBrdRbEkN0nQVWawjgodwoKUjB8jTJ/AB9uTkvlVmSC/eE6Ysy0pJdL36ogEg8qCt27r5g==
dependencies:
h3-js "^3.6.1"

get-intrinsic@^1.0.2, get-intrinsic@^1.1.1:
version "1.1.2"
resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.1.2.tgz#336975123e05ad0b7ba41f152ee4aadbea6cf598"
Expand Down Expand Up @@ -5479,10 +5486,15 @@ gzip-size@^6.0.0:
dependencies:
duplexer "^0.1.2"

h3-js@4.2.1:
version "4.2.1"
resolved "https://registry.yarnpkg.com/h3-js/-/h3-js-4.2.1.tgz#dbd598c80a0b3aa1070a2c75d745855bf3c8ac4c"
integrity sha512-HYiUrq5qTRFqMuQu3jEHqxXLk1zsSJiby9Lja/k42wHjabZG7tN9rOuzT/PEFf+Wa7rsnHLMHRWIu0mgcJ0ewQ==
h3-js@4.4.0:
version "4.4.0"
resolved "https://registry.yarnpkg.com/h3-js/-/h3-js-4.4.0.tgz#858586205d49fc2b164df8e2d1ab855565ee9e81"
integrity sha512-DvJh07MhGgY2KcC4OeZc8SSyA+ZXpdvoh6uCzGpoKvWtZxJB+g6VXXC1+eWYkaMIsLz7J/ErhOalHCpcs1KYog==

h3-js@^3.6.1:
version "3.7.2"
resolved "https://registry.yarnpkg.com/h3-js/-/h3-js-3.7.2.tgz#61d4feb7bb42868ca9cdb2d5cf9d9dda94f9e5a3"
integrity sha512-LPjlHSwB9zQZrMqKloCZmmmt3yZzIK7nqPcXqwU93zT3TtYG6jP4tZBzAPouxut7lLjdFbMQ75wRBiKfpsnY7w==
Comment on lines +5489 to +5497
Copy link
Collaborator

Choose a reason for hiding this comment

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

Not sure how significant this is, but is it worth waiting on an update to geojson2h3 so that we only need to pull in one version of the h3-js library?


h3-js@^4.1.0:
version "4.1.0"
Expand Down Expand Up @@ -9617,6 +9629,11 @@ wildcard@^2.0.0:
resolved "https://registry.yarnpkg.com/wildcard/-/wildcard-2.0.0.tgz#a77d20e5200c6faaac979e4b3aadc7b3dd7f8fec"
integrity sha512-JcKqAHLPxcdb9KM49dufGXn2x3ssnfjbcaQdLlfZsL9rH9wgDQjUtDxbo8NE0F6SFvydeu1VhZe7hZuHsB2/pw==

wkt@^0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/wkt/-/wkt-0.1.1.tgz#8d3280cb0d7664343d8987a30c85806554618bf8"
integrity sha512-2vtzYZOqN0VZdtDTMDUgbpXpE+MXRdsFTiCpS08FZ4yktT9pPylVMZaLxcIqT9pRkBp5FIAGVQyJ/kJa9b8uGg==

wrap-ansi@^7.0.0:
version "7.0.0"
resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43"
Expand Down