1. 程式人生 > >ArcGIS For JS 距離與面積量算的三種方法

ArcGIS For JS 距離與面積量算的三種方法

在用ArcGIS For JS開發地圖過程中,距離與面積的量算功能是比較常用的,下面我們來看看實現量算功能的三種方法。

1.GeometryService

GeometryService是ArcGIS For JS提供的一種服務,需要依賴ArcGIS釋出的幾何服務

 (1)定義geometryService

                    var geometryService = new GeometryService("https://utility.arcgisonline.com/ArcGIS/rest/services/Geometry/GeometryServer");
             dojo.connect(geometryService, "onLengthsComplete", this.lengthsCompleteHandler);
             dojo.connect(geometryService, "onSimplifyComplete",this.geometryService_simplifyCompleteHandler);

(2)在drawTool的draw-end事件中新增程式碼

距離量算

              var drawLine = new esri.geometry.Polyline(event.geometry);
               var lengthParams = new esri.tasks.LengthsParameters();
              lengthParams.polylines = [drawLine];
              lengthParams.lengthUnit = esri.tasks.GeometryService.UNIT_METER;
              lengthParams.geodesic = true;
              lengthParams.polylines[0].spatialReference = new esri.SpatialReference(4490);
              geometryService.lengths(lengthParams);
                     latestEndpoint = drawLine.paths[0][0];

              //把線新增到地圖
              var g = new Graphic(event.geometry, lengthLine);
              myGraphicsLayer2.add(g);

面積量算
                    addPolygonToMap(event.geometry);
               projectPolygon(event.geometry);

(3)結果處理

距離

            lengthsCompleteHandler: function (event) {
                var dist = event.lengths[0];
                var myAttributes = {};
                var lengthSymbol = new TextSymbol().setColor(myUtity.GetColorUint("00ff00", 1)).setAlign(Font.ALIGN_START).setFont(new Font("14px").setWeight(Font.WEIGHT_BOLD));
                if (dist < 3000) {
                    lengthSymbol.setText("長度為:" + dist.toFixed(2) + "米");
                } else {
                    lengthSymbol.setText("長度為:" + parseFloat(dist / 1000).toFixed(2) + "千米");
                }
                var CurX = latestEndpoint[0];
                var CurY = latestEndpoint[1];
                var CurPos = new Point(CurX, CurY, map.spatialReference);
                var g = new Graphic(CurPos, lengthSymbol, myAttributes);
                myGraphicsLayer2.add(g);
            },

面積
//向地圖新增多邊形   面積測量
            addPolygonToMap: function (polygon) {
                if (V == "mj") {
                    var newGraphic = new Graphic(polygon, myfind);
                    myGraphicsLayer2.add(newGraphic);
                }
            },
            geometryService_simplifyCompleteHandler: function (event) {
                if (event) {
                    var polygon = event[0];
                    this.addPolygonToMap(polygon);
                    this.projectPolygon(polygon);
                }
            },
            //面積測量
            projectPolygon: function (polygon) {
                var projectParameters = new ProjectParameters();
                projectParameters.geometries = [polygon];
                projectParameters.outSR = new SpatialReference(54034);
                geometryService.project(projectParameters, this.project_resultHandler, this.project_faultHandler);
            },
            project_resultHandler: function (result) {

                if (result) {
                    var polygon = result[0];
                    var areasAndLengthsParameters = new AreasAndLengthsParameters();
                    areasAndLengthsParameters.areaUnit = GeometryService.UNIT_SQUARE_KILOMETERS; //單位
                    areasAndLengthsParameters.lengthUnit = GeometryService.UNIT_KILOMETER; //單位
                    areasAndLengthsParameters.polygons = [polygon];
                    geometryService.areasAndLengths(areasAndLengthsParameters, areasAndLengths_resultHandler, areasAndLengths_faultHandler);
                }
            },
            project_faultHandler: function (fault) {
                alert("project_faultHandler:" + fault);
            },
            areasAndLengths_resultHandler: function (event) {
                var areaTextSymbol = new TextSymbol().setColor(GetColorUint("41423A", 1)).setAlign(Font.ALIGN_START).setFont(new Font("14px").setWeight(Font.WEIGHT_BOLD));
                var area = event.areas[0];
                if (parseInt(area) < 10) {
                    areaTextSymbol.setText(parseInt((parseFloat(area) * 1500)).toFixed(2) + "畝");
                }
                else {
                    areaTextSymbol.setText(parseFloat(area).toFixed(2) + "平方千米");
                }
                var CurPos = measuregeometry.getCentroid();
                var x = "", y = "";
                for (var i = 0; i < measuregeometry.rings[0].length; i++) {
                    x = x + measuregeometry.rings[0][i][0] + ",";
                    y = y + measuregeometry.rings[0][i][1] + ",";

                }
                var g = new Graphic(CurPos);
                g.setSymbol(areaTextSymbol);
                var pmsTextBg = new PictureMarkerSymbol(myConfig.ServerUrl + 'images/normal_btn_bg.png', 120, 18);
                pmsTextBg.setWidth(parseFloat(area).toFixed(2).length * 10 + (areaTextSymbol.text.length - parseFloat(area).toFixed(2).length) * 14);
                pmsTextBg.setOffset(0, 5);
                pmsTextBg.setColor(myUtity.GetColorUint("ffffff", 0.1));
                var bgGraphic = new Graphic(CurPos, pmsTextBg);
                myGraphicsLayer2.add(bgGraphic);
                myGraphicsLayer2.add(g);
            },
            areasAndLengths_faultHandler: function (fault) {
                alert("areasAndLengths_faultHandler:" + fault);
            }

2.geodesicUtils

geodesicUtils也是ArcGIS For JS 提供的,但不依賴ArcGIS釋出的幾何服務

距離

             projectPolyline: function (polyline) {
                var length = this.getLength(polyline)[0];
                var lengthSymbol = new TextSymbol().setColor(getColorUint("00ff00", 1)).setAlign(Font.ALIGN_START).setFont(new Font("14px").setWeight(Font.WEIGHT_BOLD));
                if (length < 3000) {
                    lengthSymbol.setText("長度為:" + length.toFixed(2) + "米");
                } else {
                    lengthSymbol.setText("長度為:" + parseFloat(length / 1000).toFixed(2) + "千米");
                }
                var CurX = polyline.paths[0][0][0];
                var CurY = polyline.paths[0][0][1];
                var CurPos = new Point(CurX, CurY, map.spatialReference);
                var g = new Graphic(CurPos, lengthSymbol);
                myGraphicsLayer2.add(g);
            },
            getLength: function (polyline) {
                var length = geodesicUtils.geodesicLengths([polyline], units.METERS);
                return length;
            }

面積
  //面積測量
            projectPolygon: function (polygon) {
                var area = this.getArea(polygon);
                var areaTextSymbol = new TextSymbol().setColor(myUtity.getColorUint("41423A", 1)).setAlign(Font.ALIGN_START).setFont(new Font("14px").setWeight(Font.WEIGHT_BOLD));
                if (parseInt(area) < 10) {
                    areaTextSymbol.setText(parseInt((parseFloat(area) * 1500)).toFixed(2) + "畝");
                }
                else {
                    areaTextSymbol.setText(parseFloat(area).toFixed(2) + "平方千米");
                }
                var CurPos = measuregeometry.getCentroid();
                var x = "", y = "";
                for (var i = 0; i < measuregeometry.rings[0].length; i++) {
                    x = x + measuregeometry.rings[0][i][0] + ",";
                    y = y + measuregeometry.rings[0][i][1] + ",";

                }
                var g = new Graphic(CurPos);
                g.setSymbol(areaTextSymbol);
                var pmsTextBg = new PictureMarkerSymbol(myConfig.ServerUrl + 'images/normal_btn_bg.png', 120, 18);
                pmsTextBg.setWidth(parseFloat(area).toFixed(2).length * 10 + (areaTextSymbol.text.length - parseFloat(area).toFixed(2).length) * 14);
                pmsTextBg.setOffset(0, 5);
                pmsTextBg.setColor(myUtity.getColorUint("ffffff", 0.1));
                var bgGraphic = new Graphic(CurPos, pmsTextBg);
                myGraphicsLayer2.add(bgGraphic);
                myGraphicsLayer2.add(g);
            },
            getArea: function (polygon) {
                var area = geodesicUtils.geodesicAreas([polygon], units.SQUARE_KILOMETERS);
                return area;
            },

3.自定義函式

通過參考OpenLayer的原始碼,自定義距離與面積的量算函式

距離

           getLength: function (len) {
                var length = 0;
                for (var i = 0, ii = len.paths.length; i < ii; i++) {
                    length += getLength_(len.paths[i]);
                }
                return length;
            },
            getLength_: function (ring) {
                var length = 0;
                for (i = 0, ii = ring.length; i < ii - 1; ++i) {
                    length += getDistance_(ring[i], ring[i + 1]);
                }
                return length;
            },
            getDistance_: function (c1, c2) {
                var radius = 6371008.8;
                var lat1 =toRadians(c1[1]);
                var lat2 = toRadians(c2[1]);
                var deltaLatBy2 = (lat2 - lat1) / 2;
                var deltaLonBy2 = toRadians(c2[0] - c1[0]) / 2;
                var a = Math.sin(deltaLatBy2) * Math.sin(deltaLatBy2) + Math.sin(deltaLonBy2) * Math.sin(deltaLonBy2) * Math.cos(lat1) * Math.cos(lat2);
                return 2 * radius * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
            },
            toRadians: function (angleInDegrees) {
                return angleInDegrees * Math.PI / 180;
            }
面積
            getArea: function (polygon) {

                   var area = 0, len = polygon.rings[0].length, radius = 6371008.8;
                   var x1 = polygon.rings[0][len - 1][0];
                   var y1 = polygon.rings[0][len - 1][1];
                   for (var i = 0; i < len; i++) {
                         console.log(lonLatToMercator(new Point(polygon.rings[0][i][0], polygon.rings[0][i][1])));
                         var x2 = polygon.rings[0][i][0], y2 = polygon.rings[0][i][1];
                         area += toRadians(x2 - x1) * (2 + Math.sin(toRadians(y1)) + Math.sin(toRadians(y2)));
                         x1 = x2;
                         y1 = y2;
                   }
                    return area * radius * radius / 2.0;
             },

4.總結

以上就是我總結的計算距離和麵積的三種方法。