ArcGIS For JS 距離與面積量算的三種方法
阿新 • • 發佈:2019-02-09
在用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.總結
以上就是我總結的計算距離和麵積的三種方法。