Skip to content

Point in Polygon is not working as intended #150

Description

@guppykang

i have a feature collection in the form of a geojson. i used vscode's geojson visualizer and it shows me exactly what i'm expecting as seen below.

Screenshot 2024-05-28 at 7 22 28 PM

i test the following cases to see if my code is working correctly. all features are polygons and multi polygons.

MontanaCoordinates = ValidateLocationParams{
		Latitude:  46.8797,
		Longitude: -110.3626,
	} // should not work

	SanDiegoCoordinates = ValidateLocationParams{
		Latitude:  32.7157,
		Longitude: 117.1611,
	} // should work

	NewYorkCoordinates = ValidateLocationParams{
		Latitude:  40.7128,
		Longitude: 74.0060,
	} // should work

	TorontoCoordinates = ValidateLocationParams{
		Latitude:  43.65107,
		Longitude: 79.347015,
	} // should not work

	LondonCoordinates = ValidateLocationParams{
		Latitude:  51.5074,
		Longitude: 0.1278,
	} // should work

	IrelandCoordinates = ValidateLocationParams{
		Latitude:  53.1424,
		Longitude: 7.6921,
	} // should not work

	AfricaCoordinates = ValidateLocationParams{
		Latitude:  8.7832,
		Longitude: 34.5085,
	} // should not work

	HawaiiCoordinates = ValidateLocationParams{
		Latitude:  19.8968,
		Longitude: 155.5828,
	} // should work

the code below is what i use to see if a single coordinate is inside any of the polygons. it gets all the coordinates it should not work for correctly, but it fails to verify correctly the coordinates that should be working. my geojson looks something like this:

{
    "type": "FeatureCollection",
    "features": [
        {
            "type": "Feature",
            "properties": {
                "GEO_ID": "0400000US25",
                "STATE": "25",
                "NAME": "Massachusetts",
                "LSAD": "",
                "CENSUSAREA": 7800.058
            },
            "geometry": {
                "type": "MultiPolygon",
                "coordinates": [XXX],
             },
       },
      ...
      ...
func (s *service) ValidateDepositLocation(params ValidateLocationParams) error {
	if DepositRegions == nil {
		collection, err := s.readGeoJSONFile("operatingRegions.geojson")
		if err != nil {
			ctx.Errorf("Failed to process operatingRegions.geojson: %v", err)
			return err
		}
		DepositRegions = collection
	}

	if s.isInCollection(ctx, params.Latitude, params.Longitude, DepositRegions) {
		return nil
	}
	return ErrLocationNotValid
}

func (s *service) readGeoJSONFile(filename string) (*orb.Collection, error) {
	file, err := os.ReadFile(filename)
	if err != nil {
		return nil, fmt.Errorf("failed to read %s: %v", filename, err)
	}

	collection := orb.Collection{}
	fc, err := geojson.UnmarshalFeatureCollection(file)
	if err != nil {
		return nil, fmt.Errorf("failed to unmarshal %s: %v", filename, err)
	}

	for _, feature := range fc.Features {
		if feature.Geometry != nil {
			collection = append(collection, feature.Geometry)
		} else {
			return nil, fmt.Errorf("feature has no geometry %v", feature.ID)
		}
	}

	return &collection, nil
}

func (s *service) isInCollection(lat float64, lon float64, collection *orb.Collection) bool {
	if collection == nil {
		ctx.Error("Collection is nil")
		return false
	}

	point := orb.Point{lon, lat}

	for _, g := range *collection {
		switch geo := g.(type) {
		case orb.Polygon:
			if planar.PolygonContains(geo, point) {
				return true
			}
		case orb.MultiPolygon:
			if planar.MultiPolygonContains(geo, point) {
				return true
			}
		default:
			ctx.Errorf("Unsupported geometry type: %v", g.GeoJSONType())
		}
	}

	return false
}

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions