在用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.总结
以上就是我总结的计算距离和面积的三种方法。