Skip to content

Point in Polygon is not working as intended #150

@guppykang

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
}

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