amcharts / amcharts5

The newest, fastest, and most advanced amCharts charting library for JavaScript and TypeScript apps.
Other
359 stars 96 forks source link

Check if longitude and latitude inside map polygon #925

Closed ng-druid closed 1 year ago

ng-druid commented 1 year ago

We are using Chat GPT to fill api gaps. One of the things we need to do is tell whether a longitude, latitude is inside a map polygon. Asking this question on Chat GPT yielded great info. However, the function "containsPoint" doesn't seem to exist on the MapPolygon. Is there a way to in the library to tell whether a lat,long is inside a MapPolygon?

Screen Shot 2023-05-17 at 1 48 38 PM
zeroin commented 1 year ago

It looks like Chat GPT has it's own branch of our software and secretly developing without telling us. In the official version, there is no such method (I even did a search)

Here is some undocumented experimental method we made for some side project which returns polygon if the point is within it's bounds. Can't promise it will work properly in all cases.

  function getCountry(point) {
    const renderer = root.container._display._renderer;

    const displayObject = renderer._getHitTarget(point, renderer.view.getBoundingClientRect());

    if (displayObject) {
      let country;
      polygonSeries.mapPolygons.each(function(polygon) {
        if (polygon._display == displayObject) {
          country = polygon;
        }
      });

      return country;
    }
  }
ng-druid commented 1 year ago

@zeroin Thank you for the quick response and possible solution. I have also encountered several ghost apis provided by chat gpt for am charts. It seems like most the time it gives me the wrong code or non-existent apis for this library. Works ok with others.

github-actions[bot] commented 1 year ago

This issue is stale because it has been open 30 days with no activity. It will be closed in 5 days unless a new comment is added.

ng-druid commented 1 year ago

@zeroin In the spirit of open source sharing a function we created to determine whether a map polygon or multi polygon contains a geo point.

interface GeoJSONPolygon {
  type: 'Polygon';
  coordinates: number[][][];
}

interface GeoJSONMultiPolygon {
  type: 'MultiPolygon';
  coordinates: number[][][][];
}

type GeoJSONGeometry = GeoJSONPolygon | GeoJSONMultiPolygon;

function isPointInsidePolygon(latitude: number, longitude: number, polygon: GeoJSONGeometry): boolean {
  const isCoordinateInsidePolygon = (x: number, y: number, polyCoords: number[][][]): boolean => {
    let isInside = false;

    for (const ring of polyCoords) {
      let intersectCount = 0;

      for (let i = 0, j = ring.length - 1; i < ring.length; j = i++) {
        const xi = ring[i][0];
        const yi = ring[i][1];
        const xj = ring[j][0];
        const yj = ring[j][1];

      const intersect =
        ((yi > y) !== (yj > y)) &&
        (x < ((xj - xi) * (y - yi)) / (yj - yi) + xi);

        if (intersect) {
          intersectCount++;
        }
      }

      if (intersectCount % 2 !== 0) {
        isInside = !isInside;
      }
    }

    return isInside;
  };

  if (polygon.type === 'Polygon') {
    return isCoordinateInsidePolygon(longitude, latitude, polygon.coordinates);
  } else if (polygon.type === 'MultiPolygon') {
    for (const subPolygon of polygon.coordinates) {
      if (isCoordinateInsidePolygon(longitude, latitude, subPolygon)) {
        return true;
      }
    }
  }

  return false;
}