Question

I have a mongodb collection that contains many documents. An attribute of these documents is a 2D point cloud collection that I currently query to find documents where any points sit inside a polygon etc. This works brilliantly.

What I am looking to do now, and I am not sure if its actually possible is to be able to find the closest point in each point cloud collection to a supplied polygon.

To give a visualization, Imagine the documents contain a 2D point cloud that represents a scan of a road tunnel. I want to be able to supply a polygon representing a lorry and find the closest point to it. This would be on a document basis so in English we would be asking the following:

result = nearest point to <Polygon> in document <Document X>.<CloudPoints>

Bonus - If it were possible to be able to return all documents with that result attached somehow, that would be even better though I suspect this is well outside the normal bounds of how Mongo is designed to be used.

EDIT:

By request, here is an example. Consider we have a collection of documents that look like the following. In this example I have many documents that have a collection of coordinates that represent the locations of birds nests that happen to be protected, with laws etc as to how close a company can do ground works.

BirdsNests >
        _id : 1234
        _Description : North town pipe replacement 2016
        _NestLocations >
                      [100, 150]
                      [140, 180]
                      [165. 134]
                      etc...

If I supply a polygon, what I want to know is that the closest point in the Coordinates collection is to that polygon. Note: this should be to any surface of it such as. This will allow people to supply a polygon representing a proposed work site and have Mongo report which nest sits closest to the site parameter.

enter image description here

This will be requested on a document basis initially so we would be asking for document 1234, what is the closest coordinate in the collection to this supplied polygon.

Please note all examples used are purely fictional.

Was it helpful?

Solution

I don't think mongo support passing a polygon to the $near operator. So my first guess would be to try to find the closest document for each points located on the edge of your polygon. Unfortunately you will not be able to compare the distance between each results since mongo do not return this information. (maybe you can compute that yourself to filter all candidates returned by mongo ?)

So given a point located on the edge of the polygon, you can find the closest document.

But in your case it might make sense to return the closest document from the point to the right side of the polygon rather than the one located from the left side of the polygon ?

Or you can compute the gravity center of your polygon and use that point to find the closest document.

enter image description here

OTHER TIPS

I also needed to find the closest point to a polygon, but I'm using a small number of points across the globe, and my polygons are buildings.

Since the distances between my points are much greater than the size of my polygons, I just found the geometric center of the polygon using the tips found here:

Center of gravity of a polygon

For anyone in a similar situation, here is the JS code for finding the geometric center:

////
// Get the geometric center (centroid) of a polygon
// coordinates: 3d array in the format of a geoJSON Polygon's coordinates
//      http://geojson.org/geojson-spec.html#polygon
//   only the exterior ring is used
//   the polygon should be closed (last point same as first)
exports.getPolygonCentroid = function(coordinates) {
    var secondFactor;
    var centroidX = 0;
    var centroidY = 0;
    var area = 0;
    var points = coordinates[0];  //only use the exterior ring

    for(var pt = 0; pt<points.length-1; pt++) {
        secondFactor = (points[pt][0] * points[pt+1][1]) - (points[pt+1][0] * points[pt][1]);
        centroidX += (points[pt][0] + points[pt+1][0]) * secondFactor;
        centroidY += (points[pt][1] + points[pt+1][1]) * secondFactor;
        area += secondFactor;
    }
    area = area / 2;

    centroidX = centroidX / 6 / area;
    centroidY = centroidY / 6 / area;

    return [centroidX, centroidY];
};
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top