mongodb check if point is in polygon
Asked Answered
C

3

30

mongo 2.6

I have some amount of stored polygons. And I have a point. I what to know if this point fits any of stored polygons

document example

{ ..., "polygons" : [ [ 17.60083012593064, 78.18557739257812 ], [ 17.16834652544664, 78.19381713867188 ], [ 17.17490690610013, 78.739013671875 ], [ 17.613919673106714, 78.73489379882812 ] ], ... }

There is nearly the same question already Mongodb : Check if a point is inside a stored polygon. But it is not working for me - this query has to give at least one result(the one in example) - but it does not.

db.areas.find( { polygons : { $geoIntersects : { $geometry : {type:"Point",coordinates:[17.3734, 78.4738]} } } } )

Actually if I chose a point on a border of any polygon - it does.

$geoWithin method has to do the work as mondodb documentation says.

but any of these queries do not work

db.areas.find( { polygons : { $geoWithin : { $geometry : {type:"Point",coordinates:[17.3734, 78.4738]} } } } ) - not supported with provided geometry

db.tradeareas.find( { polygons : { $geoWithin : { $geometry : {type:"Polygon",coordinates: inside_polygon} } } } ) - BadValue bad geo query

It seems I miss something but cant understand what and where.

I would be grateful for help.

Counterproof answered 4/7, 2014 at 16:45 Comment(2)
Are you using a 2d or a 2dsphere index?Fortier
I have posted a solution. Seems that order matters for point/polygon intersects queries.Fortier
F
50

It seems to be to do with the order. If you are using $geoWithin and you are trying to find points inside a polygon, the thing that is within is the field you are searching on. However, $geoIntersects works in either direction, so you can search for points inside polygons, or polygons containing points, eg:

db.geom.insert({
  "polygons": {
    "type":"Polygon",
    "coordinates": [[
      [ 17.60083012593064, 78.18557739257812],
      [ 17.16834652544664, 78.19381713867188],
      [ 17.17490690610013, 78.739013671875],
      [ 17.613919673106714, 78.73489379882812],
      [ 17.60083012593064, 78.18557739257812]
    ]]
  }
});

db.geom.find({
  polygons: {
    $geoIntersects: {
      $geometry: {
        "type": "Point",
        "coordinates": [17.3734, 78.4738]
      }
    }
  }
});

Also, note that, you need to repeat the first point of the polygon at the end. If you remove the final pair, you will get a $err:

Can't canonicalize query: BadValue bad geo query" error.

It seems that MongoDB allows you to insert invalid geometries and only complains when you try and add a 2dsphere index or do an intersects/within/near query, which, I suppose is reasonable, as GeoJSON can be valid JSON without being a valid geometry.

Fortier answered 7/7, 2014 at 8:6 Comment(7)
Thank you for reply. I made such tests as you suggest - it does work correctly - just like in mongo documentation example. But I dont have polygons. I have just a point as parameter. To get a polygon I need to make a request to DB. So with a million records - i need a 2 million requests to find all polygons that contains my pointCounterproof
@user3806072. I have updated my answer, it works as expected now, it will find all polygons that contain a point.Fortier
thank you very much - it does work. As you mentioned - The mistake was in incorrect GEOJSON structure of saved polygon.Counterproof
@Counterproof I am having the same issue you were having. I do think it's the GEOJSON structure of the saved polygon. What did you change the structure to? What does your schema look like? Thanks much!Reductive
What do you mean by "It seems to be to do with the order"?Cispadane
Would it be possible to achieve the same thing if we have a multiple of polygons and points within our database? Could we have point-in-polygon analysis in MongoDB implicity?Kwangchow
@banbar. Sorry, I don't really work with MongoDB any more. I am sure you can achieve that, but I think you might want to ask that as a separate question.Fortier
S
1

Thanks for John Powell here is C# driver version of the same query.

 var geometry = new BsonDocument
                            {
                                     { "type", "Point" },
                                     { "coordinates",
                                        new BsonArray(new double[]{ Longitude,
                                        Latitude} ) }
                            };
                    var geometryOperator = new BsonDocument { { "$geometry", geometry } };
                    var geoIntersectsOperator = new BsonDocument { { "$geoIntersects", geometryOperator } };

                    var findField = new BsonDocument { { "geometry", geoIntersectsOperator } };


                    var results = MyCollection.Find(findField).ToList();
Stereotaxis answered 14/9, 2020 at 15:44 Comment(0)
T
0

In Java it Can be done this way

@Autowired
private MongoOperations mongoOpertions;
    
public void pointIntersect(GeoJsonPoint gp){
    Query query = new Query();
    query.addCriteria(Criteria.where("geometry").intersects(gp));
    List<ResultDtoType> result = mongoOpertions.find(query, ResultDtoType.class);
    //perform any action with result 
}
Theoretical answered 4/5, 2021 at 5:49 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.