Open syonfox opened 7 months ago
See this answer: https://github.com/uber/h3-js/issues/158#issuecomment-1244087555
The problem in the image is a rendering issue, not an H3-js issue. H3 always provides coordinates with normalized longitudes (in the range -180
to 180
) but this doesn't always render well on web maps.
The error you pasted to is a different issue - at some point you're sending resolution -1
to the polygonToCells
function, and this throws an error for bad input.
Anyway though id point it out if curious this is how im adding this to leaflet map
h3viewer.js
```js // let map, hexLayer, p; const GeoUtils = { EARTH_RADIUS_METERS: 6371000, radiansToDegrees: (r) => r * 180 / Math.PI, degreesToRadians: (d) => d * Math.PI / 180, getDistanceOnEarthInMeters: (lat1, lon1, lat2, lon2) => { const lat1Rad = GeoUtils.degreesToRadians(lat1); const lat2Rad = GeoUtils.degreesToRadians(lat2); const lonDelta = GeoUtils.degreesToRadians(lon2 - lon1); const x = Math.sin(lat1Rad) * Math.sin(lat2Rad) + Math.cos(lat1Rad) * Math.cos(lat2Rad) * Math.cos(lonDelta); return GeoUtils.EARTH_RADIUS_METERS * Math.acos(Math.max(Math.min(x, 1), -1)); } }; const ZOOM_TO_H3_RES_CORRESPONDENCE = { 5: 1, 6: 2, 7: 3, 8: 3, 9: 4, 10: 5, 11: 6, 12: 6, 13: 7, 14: 8, 15: 9, 16: 9, 17: 10, 18: 10, 19: 11, 20: 11, 21: 12, 22: 13, 23: 14, 24: 15, }; const H3_RES_TO_ZOOM_CORRESPONDENCE = {}; for (const [zoom, res] of Object.entries(ZOOM_TO_H3_RES_CORRESPONDENCE)) { H3_RES_TO_ZOOM_CORRESPONDENCE[res] = zoom; } const getH3ResForMapZoom = (mapZoom) => { return ZOOM_TO_H3_RES_CORRESPONDENCE[mapZoom] ?? Math.floor((mapZoom - 1) * 0.7); }; const h3BoundsToPolygon = (lngLatH3Bounds) => { lngLatH3Bounds.push(lngLatH3Bounds[0]); // "close" the polygon return lngLatH3Bounds; }; /** * Parse the current Query String and return its components as an object. */ const parseQueryString = () => { const queryString = window.location.search; const query = {}; const pairs = (queryString[0] === '?' ? queryString.substr(1) : queryString).split('&'); for (let i = 0; i < pairs.length; i++) { const pair = pairs[i].split('='); query[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1] || ''); } return query; }; const queryParams = parseQueryString(); const copyToClipboard = (text) => { const dummy = document.createElement("textarea"); document.body.appendChild(dummy); dummy.value = text; dummy.select(); document.execCommand("copy"); document.body.removeChild(dummy); }; function initH3LayerOnMap(h3code) { let self = { computeAverageEdgeLengthInMeters: function (vertexLocations) { let totalLength = 0; let edgeCount = 0; for (let i = 1; i < vertexLocations.length; i++) { const [fromLat, fromLng] = vertexLocations[i - 1]; const [toLat, toLng] = vertexLocations[i]; const edgeDistance = GeoUtils.getDistanceOnEarthInMeters(fromLat, fromLng, toLat, toLng); totalLength += edgeDistance; edgeCount++; } return totalLength / edgeCount; }, updateMapDisplay: function () { if (hexLayer) { hexLayer.remove(); } hexLayer = L.layerGroup().addTo(map); const zoom = map.getZoom(); self.currentH3Res = getH3ResForMapZoom(zoom); const {_southWest: sw, _northEast: ne} = map.getBounds(); const boundsPolygon = [ [sw.lat, sw.lng], [ne.lat, sw.lng], [ne.lat, ne.lng], [sw.lat, ne.lng], [sw.lat, sw.lng], ]; const h3s = h3.polygonToCells(boundsPolygon, self.currentH3Res); for (const h3id of h3s) { const polygonLayer = L.layerGroup() .addTo(hexLayer); const isSelected = h3id === self.searchH3Id; const style = isSelected ? {fillColor: "orange"} : {}; const h3Bounds = h3.cellToBoundary(h3id); const averageEdgeLength = self.computeAverageEdgeLengthInMeters(h3Bounds); const cellArea = h3.cellArea(h3id, "m2"); const tooltipText = ` Cell ID: ${h3id}Average edge length (m): ${averageEdgeLength.toLocaleString()}
Cell area (m^2): ${cellArea.toLocaleString()} `; const h3Polygon = L.polygon(h3BoundsToPolygon(h3Bounds), style) .on('click', () => copyToClipboard(h3id)) .bindTooltip(tooltipText) .addTo(polygonLayer); // less SVG, otherwise perf is bad if (Math.random() > 0.8 || isSelected) { var svgElement = document.createElementNS("http://www.w3.org/2000/svg", "svg"); svgElement.setAttribute('xmlns', "http://www.w3.org/2000/svg"); svgElement.setAttribute('viewBox', "0 0 200 200"); svgElement.innerHTML = `