2014-04-30 33 views
1

我有一個包含許多文檔的mongodb集合。這些文檔的一個屬性是一個二維點雲集合,我目前正在查詢以找到任何點位於多邊形內的文檔等。這非常出色。Mongodb - 查找提供的多邊形的最近點

我現在想要做的是什麼,我不確定它實際上是否能夠在每個點雲集閤中找到最接近的點到提供的多邊形。

要給出一個可視化文件,想象一下這些文件包含一個代表道路隧道掃描的二維點雲。我希望能夠提供一個代表卡車的多邊形並找到最接近它的點。這將是一個文件基礎上,所以在英語中我們會問以下內容:

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

獎金 - 如果有可能,以能夠與某種方式連接這個結果返回的所有文件,這甚至會更好,雖然我懷疑這遠遠超出了Mongo設計使用的正常界限。

編輯:

根據要求,這裏是一個例子。考慮一下我們收集的文件如下所示。在這個例子中,我有很多文件都有一些座標集合,這些座標集合代表了碰巧受到保護的鳥巢的位置,並附有關於公司有多接近地面工程的法律等。

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

如果我提供一個多邊形,我想知道的是,座標集合中的最近點是該多邊形。注意:這應該是它的任何表面,如。這將允許人們提供代表擬議工作地點的多邊形,並讓Mongo報告哪個巢位置最接近站點參數。

enter image description here

這將一個文件的基礎上要求初步所以我們會要求文件1234,什麼是集合中最接近座標到此提供的多邊形。

請注意所有使用的例子都是純虛構的。

+0

你可以添加一些數據和例子,你想要達到什麼? – aks

+0

@aks根據要求更新。 –

+0

鑑於上面的圖片,左邊的綠點似乎不是最接近我的點......只要確保我正確理解了您的問題,對於給定多邊形邊上的所有點座標,您想要找到最接近綠點? (在你的照片中,它似乎是左上角的那個) –

回答

3

我不認爲mongo支持將一個多邊形傳遞給$near運算符。所以我的第一個猜測是嘗試找到位於多邊形邊上的每個點的最接近的文檔。不幸的是,你將無法比較每個結果之間的距離,因爲mongo不會返回這些信息。 (也許你可以自己計算過濾所有由mongo返回的候選人嗎?)

因此,給定一個位於多邊形邊緣的點,可以找到最接近的文檔。

但是在你的情況下,從多邊形的右邊返回最接近的文檔而不是從多邊形的左邊找到最接近的文檔?

或者您可以計算多邊形的重心並使用該點找到最接近的文檔。

enter image description here

+0

謝謝。這也是我自己的結論,通過$ near函數是不可能的,但是想看看那些具有更多mongo經驗的人是否知道更好。我們目前有一個應用程序端解決方案來做到這一點,但我正在調查是否有一種「更好」的方式來作爲查詢。回到我認爲的繪圖板。 –

0

我還需要找到的最近點到面,但我使用少量的在全球範圍內的點,和我的多邊形建築。

由於我點之間的距離比我的多邊形的尺寸要大得多,我剛剛發現使用技巧多邊形的幾何中心這裏找到了類似的情況

Center of gravity of a polygon

對於任何人,這裏是尋找幾何中心的JS代碼:

//// 
// 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]; 
};