【问题标题】:Google Maps Polygons self intersecting detection谷歌地图多边形自相交检测
【发布时间】:2014-09-20 22:51:09
【问题描述】:

我正在尝试从 Google Maps API V3 多边形实现多边形自相交算法
目标只是检测是或否,用户绘制的简单多边形是自交叉的。

我找到了this very interesting link,但它假定多边形顶点的坐标以geoJSON 格式给出。但是,这不是我的情况;我只能使用polygon.getPath() 将多边形坐标检索到polygoncomplete 事件中。

这就是我检索坐标的方式:

google.maps.event.addDomListener(drawingManager, 'polygoncomplete', function(polygon)
{
    var polygonBounds = polygon.getPath();
    var coordinates = [];

    for(var i = 0 ; i < polygonBounds.length ; i++)
    {            
        vertice = {
                      "Latitude" : polygonBounds.getAt(i).lat(),
                      "Longitude" : polygonBounds.getAt(i).lng()
                  }

        coordinates.push(vertice );
    }
}

如何将polygon.getpath() 给出的这些坐标转换为 geoJSON 格式?
有没有更好的方法来检测谷歌地图多边形是否自相交?如果是这样,您能否分享一些代码示例而不仅仅是数学解释?

PS : 我看过 this 链接,但没有任何代码示例,我有点迷茫。

【问题讨论】:

    标签: javascript google-maps-api-3 polygon shapes self-intersection


    【解决方案1】:

    您无需将它们转换为 GeoJSON 即可使用 jsts library,您需要将它们从 google.maps.LatLng 对象转换为 jsts.geom.Coordinates。而不是使用这个:

    var geoJSON2JTS = function(boundaries) {
      var coordinates = [];
      for (var i = 0; i < boundaries.length; i++) {
        coordinates.push(new jsts.geom.Coordinate(
            boundaries[i][1], boundaries[i][0]));
      }
      return coordinates;
    };
    

    使用它,它将 google.maps.Polygon 路径中的坐标转换为 JTS 格式:

    var googleMaps2JTS = function(boundaries) {
      var coordinates = [];
      for (var i = 0; i < boundaries.getLength(); i++) {
        coordinates.push(new jsts.geom.Coordinate(
            boundaries.getAt(i).lat(), boundaries.getAt(i).lng()));
      }
      return coordinates;
    };
    

    然后像这样更改“findSelfIntersects”:

    /**
     * findSelfIntersects
     *
     * Detect self-intersections in a polygon.
     *
     * @param {object} google.maps.Polygon path co-ordinates.
     * @return {array} array of points of intersections.
     */
    var findSelfIntersects = function(googlePolygonPath) {
      var coordinates = googleMaps2JTS(googlePolygonPath);
      var geometryFactory = new jsts.geom.GeometryFactory();
      var shell = geometryFactory.createLinearRing(coordinates);
      var jstsPolygon = geometryFactory.createPolygon(shell);
     
      // if the geometry is aleady a simple linear ring, do not
      // try to find self intersection points.
      var validator = new jsts.operation.IsSimpleOp(jstsPolygon);
      if (validator.isSimpleLinearGeometry(jstsPolygon)) {
        return;
      }
     
      var res = [];
      var graph = new jsts.geomgraph.GeometryGraph(0, jstsPolygon);
      var cat = new jsts.operation.valid.ConsistentAreaTester(graph);
      var r = cat.isNodeConsistentArea();
      if (!r) {
        var pt = cat.getInvalidPoint();
        res.push([pt.x, pt.y]);
      }
      return res;
    };
    

    proof of concept fiddle (credit to HoffZ)

    代码 sn-p:

    var mapOptions = {
      zoom: 16,
      center: new google.maps.LatLng(62.1482, 6.0696)
    };
    
    var drawingManager = new google.maps.drawing.DrawingManager({
      drawingControl: false,
      polygonOptions: {
        editable: true
      }
    });
    
    var googleMaps2JTS = function(boundaries) {
      var coordinates = [];
      for (var i = 0; i < boundaries.getLength(); i++) {
        coordinates.push(new jsts.geom.Coordinate(
          boundaries.getAt(i).lat(), boundaries.getAt(i).lng()));
      }
      coordinates.push(coordinates[0]);
      console.log(coordinates);
      return coordinates;
    };
    
    /**
     * findSelfIntersects
     *
     * Detect self-intersections in a polygon.
     *
     * @param {object} google.maps.Polygon path co-ordinates.
     * @return {array} array of points of intersections.
     */
    var findSelfIntersects = function(googlePolygonPath) {
      var coordinates = googleMaps2JTS(googlePolygonPath);
      var geometryFactory = new jsts.geom.GeometryFactory();
      var shell = geometryFactory.createLinearRing(coordinates);
      var jstsPolygon = geometryFactory.createPolygon(shell);
    
      // if the geometry is aleady a simple linear ring, do not
      // try to find self intersection points.
      var validator = new jsts.operation.IsSimpleOp(jstsPolygon);
      if (validator.isSimpleLinearGeometry(jstsPolygon)) {
        return;
      }
    
      var res = [];
      var graph = new jsts.geomgraph.GeometryGraph(0, jstsPolygon);
      var cat = new jsts.operation.valid.ConsistentAreaTester(graph);
      var r = cat.isNodeConsistentArea();
      if (!r) {
        var pt = cat.getInvalidPoint();
        res.push([pt.x, pt.y]);
      }
      return res;
    };
    
    
    var map = new google.maps.Map(document.getElementById("map"), mapOptions);
    drawingManager.setDrawingMode(google.maps.drawing.OverlayType.POLYGON);
    drawingManager.setMap(map);
    google.maps.event.addListener(drawingManager, 'polygoncomplete', function(polygon) {
      //var polyPath = event.overlay.getPath();
      var intersects = findSelfIntersects(polygon.getPath());
      console.log(intersects);
      if (intersects && intersects.length) {
        alert('Polygon intersects itself');
      } else {
        alert('Polygon does not intersect itself');
      }
    });
    #map {
      width: 500px;
      height: 400px;
    }
    <script src="https://maps.google.com/maps/api/js?libraries=drawing&key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk"></script>
    <script src="https://cdn.rawgit.com/bjornharrtell/jsts/gh-pages/1.4.0/jsts.min.js"></script>
    <p>
      Draw a polygon on the map
    </p>
    
    <div id="map">
    
    </div>

    【讨论】:

    • 我必须将第一个坐标包含到坐标数组的末尾以避免 JSTS 中的验证错误。在函数 googleMaps2JTS 在返回之前添加这一行:coordinates.push(coordinates[0]); 如果你有同样的问题
    猜你喜欢
    • 1970-01-01
    • 2012-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-03
    • 2012-06-15
    • 1970-01-01
    相关资源
    最近更新 更多