诺基亚此处地图计算多边形的质心(例如三角形)会产生错误的结果

时间:2014-04-14 15:04:11

标签: javascript here-api

正如主题所说,我有一个多边形,想要计算质心(质心)。我使用地理坐标,将它们转换为像素cooridinates,使用http://en.wikipedia.org/wiki/Centroid上的公式,并将计算的像素转换回地理坐标。

结果似乎错了(我无法发布图片)。相关的代码段是:

    this.drawPolygonCenter = function (mapService, coords) {
            var sumY = 0;
            var sumX = 0;
            var partialSum = 0;
            var sum = 0;
            var cm = mapService.getCurrentMapReference();
            var points = [];
            coords.forEach(function (c, idx) {
                points.push(cm.geoToPixel(c));
                console.log("x: " + points[idx].x + " y: " + points[idx].y);
            });
            var n = points.length;

            for (var i = 0; i < n - 1; i++) {
                partialSum = points[i].x * points[i + 1].y - points[i + 1].x * points[i].y;
                sum += partialSum;
                sumX += (points[i].x + points[i + 1].x) * partialSum;
                sumY += (points[i].y + points[i + 1].y) * partialSum;
            }

            var area = 0.5 * sum;
            var div = 6 * area;
            var x1 = sumX / div;
            var y1 = sumY / div;
            console.log("Centroid: x= " + x1 + " y= " + y1); // debug
            var pinLocation = cm.pixelToGeo(Math.ceil(x1), Math.ceil(y1));
            var pin = this.createCenterPin(pinLocation);

            cm.objects.add(new nokia.maps.map.StandardMarker(pinLocation)); // debug

1 个答案:

答案 0 :(得分:0)

我认为你的计算有一个舍入错误是由于像素和纬度/长度之间的切换 - 没有必要这样做 - 你可以直接使用lat / longs。

您可以向getCentroid()类添加Polygon方法,如下所示:

 nokia.maps.map.Polygon.prototype.getCentroid = function (arg) {
    var signedArea = 0,
      len = this.path.getLength(),
      centroidLongitude = 0,
      centroidLatitude = 0;


    for (i=0; i < len; i++){
      var a = this.path.get(i),
      b = this.path.get( i + 1 < len ? i + 1 : 0);

      signedArea +=
        ((a.longitude * b.latitude) -  (b.longitude * a.latitude));
      centroidLongitude += (a.longitude + b.longitude) *
        ((a.longitude * b.latitude) - (b.longitude * a.latitude));
      centroidLatitude += (a.latitude + b.latitude) *
        ((a.longitude * b.latitude) - (b.longitude * a.latitude));
    }

    signedArea = signedArea /2;

    centroidLongitude   = centroidLongitude/ (6 * signedArea);
    centroidLatitude   = centroidLatitude/ (6 * signedArea);

    return new  nokia.maps.geo.Coordinate(centroidLatitude, centroidLongitude);
  };

您可以按如下方式致电polygon.getCentroid()(例如添加标记):

 map.objects.add(new nokia.maps.map.Marker(polygon.getCentroid()));

注意,您可能仍会得到Polygon穿过第180个子午线的一些边缘效果。(使用isIDL()方法检查)。在这种情况下,您可能需要在进行计算之前向每个纬度添加360,并从最终结果中减去它。