Premshankar Tiwari
Premshankar Tiwari

Reputation: 3106

H3 - How to get center lat long of a multi polygon?

I have created Multi polygons using h3SetToMultiPolygon from the list of H3 cell ids as shown below:

enter image description here

Now I want to get the center (I know it's not a perfect shape to get the center, but a rough one should be fine) of the Multi Polygon which I am unable to get using any H3 or leaflet methods. I want to show a marker at the center of the boundary of the multi polygons as shown below roughly:

enter image description here

Any help would be appreciated. Here is my code:

const clusterBoundaryCoordinates = [];
clusters?.forEach((element) => {
  clusterBoundaryCoordinates.push(
    h3.h3SetToMultiPolygon(element.cellIdsArr, true)
  );
});

Upvotes: 0

Views: 836

Answers (2)

Premshankar Tiwari
Premshankar Tiwari

Reputation: 3106

I found the solution. I didn't notice earlier that to find the center, I can utilize the lat longs which I receive when I do h3SetToMultiPolygon (it returns the lat long in reverse order).

const clusterBoundaryCoordinates = [];
clusters?.forEach((element) => {
  clusterBoundaryCoordinates.push(
    h3.h3SetToMultiPolygon(element.cellIdsArr, true);       //it returns the latlong in reverse order, so need to reverse it
  );
});

const getCentroid = (arr) => {
  return arr.reduce(
    (x, y) => {
      return [x[0] + y[0] / arr.length, x[1] + y[1] / arr.length];
    },
    [0, 0]
  );
};
const centroid = getCentroid(clusterBoundaryCoordinates);

Upvotes: 0

nrabinowitz
nrabinowitz

Reputation: 55688

This isn't really specific to H3 - in general, you want an algorithm that can give you the centroid of a polygon, e.g. @turf/centroid. There are different centroid algorithms based on the use case - e.g. you may or may not require the centroid to be inside a concave polygon (think a C shape) or within one of many small polygons in a multipolygon (think an archipelago).

There's an interesting H3-based option here as well, though I don't know offhand how to make it performant. You can find the center cell by finding the cell whose mean distance to all other cells is lowest, e.g.

let min = Infinity;
let center = null;

for (const cell of cells) {
  let total = 0;
  for (const neighbor of cells) {
    total += h3.h3Distance(cell, neighbor);
  }
  if (total < min) {
    min = total;
    center = cell;
  }
}

This will always give you a cell in your set, so it will always be within your area, and should give a reasonable value even for pathological shapes. But, because the algorithm is O(n^2), it's going to be very slow for large sets of cells.

Upvotes: 1

Related Questions