文章目录
前言
ArcGIS for JS广泛应用于需要在Web上展示和分析空间数据的各种场景中,包括教育、科研和商业领域。它特别适合GIS分析师、IT开发人员以及任何需要在Web上分享和利用地理信息的人员
一、三维测量,测距,高程是什么?
三维测量是指对物体进行全方位测量,确定其三维坐标测量数据。其测量原理包括测距、角位移、扫描和定向四个方面。根据三维技术原理研发的仪器主要有拍照式(结构光)三维扫描仪、激光三维扫描仪和三坐标测量机等
测距是三维测量中的一个重要组成部分,它通过测量物体与测量设备之间的距离来确定物体的位置。测距的方法有多种,包括激光测距、超声波测距、红外测距等。激光测距是最常见的一种,通过发射激光并测量其反射时间来计算距离。
高程指的是某点沿铅垂线方向到绝对基面的距离,称为绝对高程,简称高程。高程是地理测量中的一个重要概念,用于表示地面点的高低。高程系统采用不同的基准面表示地面点的高低,常见的系统包括正高、正常高、力高和大地高程等
高程测量主要有水准测量和三角高程测量等方法。水准测量是利用水平视线来测量两点间的高差,由于其精度较高,因此是高程测量中最主要的方法。三角高程测量则是通过测量两点间的水平距离或斜距和竖直角来计算高差,一般精度较低,仅在适当条件下采用
二、使用步骤
1.引入库
代码如下(示例):
c
import { Polyline } from '@arcgis/core/geometry';
import Graphic from '@arcgis/core/Graphic';
import Point from '@arcgis/core/geometry/Point';
import * as geometryEngine from '@arcgis/core/geometry/geometryEngine';
import Draw from '@arcgis/core/views/draw/Draw';
import GraphicsLayer from '@arcgis/core/layers/GraphicsLayer';
import Polygon from '@arcgis/core/geometry/Polygon';
import TextSymbol from '@arcgis/core/symbols/TextSymbol';
import ElevationLayer from '@arcgis/core/layers/ElevationLayer';
import SimpleMarkerSymbol from '@arcgis/core/symbols/SimpleMarkerSymbol';
2.初始化Draw
初始化的时候必须保证三维view初始化结束
c
drawBar = new Draw({ view: view3d });
3.初始化图层
必须初始化点线面的图层为的就是好管理地图操作
c
const newLineLayer = new GraphicsLayer({
id: 'LandQueryDrawLayer',
elevationInfo: {
mode: 'on-the-ground',
},
});
view3d.map.add(newLineLayer);
const newPolygonLayer = new GraphicsLayer({
id: 'LandQueryPolygonDrawLayer',
elevationInfo: {
mode: 'on-the-ground',
},
});
view3d.map.add(newPolygonLayer);
const newPointLayer = new GraphicsLayer({
id: 'LandQueryPointDrawLayer',
elevationInfo: {
mode: 'on-the-ground',
},
});
4.测量距离功能
绘制点成线,利用arcgis的计算模块进行
c
测量距离
const measureDistance = () => {
clearMeasureActionAndGraphics();
distanceMeasure = true; //激活距离测量
let action = drawBar.create('polyline'); //创建画线实例
view3d.focus();
action.on(
[
'vertex-add', // when a vertex is added 鼠标单击
'vertex-remove', // when a vertex is removed 移除
'cursor-update', // when the pointer moves 鼠标移动
'draw-complete', // when the drawing is completed 鼠标双击
],
function (evt) {
createLine(evt.vertices);
},
);
};
const createLine = (vertices) => {
view3d.map.findLayerById('LandQueryDrawLayer').removeAll(); //清空上次绘制的线
let symbol = {
//点样式
type: 'simple-marker',
color: [47, 79, 79],
width: 0.5,
size: 4,
outline: {
color: [0, 0, 0],
width: 1,
},
};
//将起点添加到地图
let startGraphics = new Graphic({
geometry: new Point({
type: 'point',
x: vertices[0][0], //当底图是投影坐标系时用x,地理坐标系用longitude
y: vertices[0][1], //当底图是投影坐标系时用y,地理坐标系用latitude
spatialReference: view3d.spatialReference, //和底图相同的坐标系
}),
symbol: symbol,
});
view3d.map.findLayerById('LandQueryDrawLayer').add(startGraphics);
//将线添加到地图
let lineGraphics = new Graphic({
geometry: new Polyline({
paths: vertices,
spatialReference: view.spatialReference,
}),
symbol: {
//线样式
type: 'simple-line', // autocasts as new SimpleFillSymbol
style: 'dash',
color: [176, 196, 222],
width: 2,
},
});
view3d.map.findLayerById('LandQueryDrawLayer').add(lineGraphics);
//测距
let linePath = []; //线段坐标集合
let pointStart = []; //起点
pointStart.push(vertices[0][0]);
pointStart.push(vertices[0][1]);
linePath.push(pointStart);
for (let i = 1; i < vertices.length; i++) {
//获得鼠标移动的坐标信息
let point = {
type: 'point',
x: vertices[i][0],
y: vertices[i][1],
spatialReference: view3d.spatialReference,
};
//鼠标位置
let mouseGraphics = new Graphic({
geometry: point,
symbol: symbol,
});
let xy = []; //鼠标当前经纬度
xy.push(vertices[i][0]);
xy.push(vertices[i][1]);
linePath.push(xy);
let line = new Polyline({
//起点到当前鼠标的线段
paths: linePath,
spatialReference: view3d.spatialReference,
});
let length = geometryEngine.geodesicLength(line, 'meters').toFixed(2); //测距
let lengthText = lengthFormat(length); //单位转换
let textSymbol = {
//距离标注
type: 'text',
color: 'white',
haloColor: 'black',
haloSize: '2px',
text: lengthText,
xoffset: '50px',
yoffset: '-5px',
font: {
size: 12,
family: 'sans-serif',
weight: 'bold',
},
};
let textGraphics = new Graphic({
//标注位置为鼠标位置
geometry: point,
symbol: textSymbol,
});
//将标注和鼠标位置添加到地图
view3d.map
.findLayerById('LandQueryDrawLayer')
.addMany([textGraphics, mouseGraphics]);
}
};
5.测量面积
c
/**
* 面积测量,对外暴露
*/
const measureArea = () => {
clearMeasureActionAndGraphics();
areaMeasure = true;
let action = drawBar.create('polygon'); //创建画线实例
view3d.focus();
action.on(
[
'vertex-add', // when a vertex is added 鼠标单击
'vertex-remove', // when a vertex is removed 移除
'cursor-update', // when the pointer moves 鼠标移动
'draw-complete', // when the drawing is completed 鼠标双击
],
function (evt) {
// 检查在绘制完成时,vertices 是否构成有效的多边形
let vertices = evt.vertices;
if (vertices.length < 3) {
console.error('至少需要三个点来形成有效的多边形!');
return;
}
// 确保多边形是封闭的:将第一个点添加到末尾
if (!isPolygonClosed(vertices)) {
vertices.push(vertices[0]); // 添加第一个点到末尾,封闭多边形
}
createPolygon(vertices); // 调用函数绘制多边形
},
);
};
//画面和测量面积
const createPolygon = (vertices) => {
view3d.map.findLayerById('LandQueryPolygonDrawLayer').removeAll();
let symbol = {
//点样式
type: 'simple-marker',
color: [47, 79, 79],
width: 0.5,
size: 4,
outline: {
color: [0, 0, 0],
width: 1,
},
};
let fillSymbol = {
//面样式
type: 'simple-fill', // autocasts as new SimpleFillSymbol()
color: [3, 255, 240, 0.1],
outline: {
// autocasts as new SimpleLineSymbol()
color: [255, 116, 3],
width: 2,
},
};
let polygon = new Polygon({
rings: vertices,
spatialReference: view3d.spatialReference,
});
let polygonGraphics = new Graphic({
geometry: polygon,
symbol: fillSymbol,
});
view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(polygonGraphics);
const area = Math.abs(
geometryEngine.geodesicArea(polygon, 'square-meters'),
);
let areaText = areaFormat(area);
let center = polygon.centroid;
let pointCenter = {
type: 'point',
longitude: center.longitude,
latitude: center.latitude,
};
let textSymbol = {
//面积标注
type: 'text',
color: 'white',
haloColor: 'black',
haloSize: '2px',
text: areaText,
//xoffset: '50px',
//yoffset: '-5px',
font: {
size: 12,
family: 'sans-serif',
weight: 'bold',
},
};
let textGraphics = new Graphic({
//标注为面中心位置
geometry: pointCenter,
symbol: textSymbol,
});
view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(textGraphics);
for (let i = 0; i < vertices.length; i++) {
let point = {
type: 'point',
x: vertices[i][0],
y: vertices[i][1],
spatialReference: view3d.spatialReference,
};
let pointGraphics = new Graphic({
geometry: point,
symbol: symbol,
});
view3d.map.findLayerById('LandQueryPolygonDrawLayer').add(pointGraphics);
}
};
5.测量高程
添加地图点击事件
c
view3d.on('click', (event) => {
const point = event.mapPoint;
if (heightMeasure) {
// 查询高程
getElevation(point);
}
});
//获取高程
const getElevation = (point) => {
console.log(5555555, point);
const pointGeometry = new Point({
longitude: point.longitude,
latitude: point.latitude,
});
displayElevationOnMap(pointGeometry, point.z);
elevationLayer
.queryElevation([pointGeometry])
.then(function (result) {
const elevation = result[0].z; // 获取返回的第一个样本的高程值
console.log('Elevation at clicked point:', elevation);
// 在地图上显示高程
displayElevationOnMap(pointGeometry, point.z);
})
.catch(function (error) {
console.error('Error fetching elevation:', error);
});
};
// 显示高程信息在地图上
const displayElevationOnMap = (point, elevation) => {
if (view3d.map.findLayerById('LandQueryPointDrawLayer')) {
view3d.map.findLayerById('LandQueryPointDrawLayer').removeAll();
}
// 创建文本符号
const textSymbol = new TextSymbol({
text: `高程值: ${elevation.toFixed(2)}米`,
color: 'white',
haloColor: 'black',
haloSize: '2px',
font: {
size: 12,
family: 'sans-serif',
weight: 'bold',
},
});
const markerSymbol = new SimpleMarkerSymbol({
color: [226, 119, 40], // 设置标记颜色
size: '10px', // 设置标记大小
outline: {
// 设置边框
color: [255, 0, 0],
width: 2,
},
});
// 创建图形
const graphicPoint = new Graphic({
geometry: point,
symbol: markerSymbol,
});
const graphicText = new Graphic({
geometry: point,
symbol: textSymbol,
});
// 将图形添加到视图中
view3d.map.findLayerById('LandQueryPointDrawLayer').add(graphicPoint);
view3d.map.findLayerById('LandQueryPointDrawLayer').add(graphicText);
};
const lengthFormat = (length) => {
if (length < 2000) {
return length + '米';
} else {
length = (length / 1000).toFixed(2);
return length + '千米';
}
};
const areaFormat = (area) => {
if (area < 2000) {
area = area.toFixed(2);
return area + '平方米';
} else {
area = (area / 10000).toFixed(2);
return area + '平方千米';
}
};
const clearMeasureActionAndGraphics = () => {
distanceMeasure = false;
areaMeasure = false;
heightMeasure = false;
drawBar.destroy();
};
清理地图图层
整个关于ARCGIS的测量功能就完美实现了
c
const clearMeasureActionAndGraphicsLine = () => {
if (view3d.map.findLayerById('LandQueryDrawLayer')) {
view3d.map.findLayerById('LandQueryDrawLayer').removeAll();
}
clearMeasureActionAndGraphics();
};
const clearMeasureActionAndGraphicsPolygon = () => {
if (view3d.map.findLayerById('LandQueryPolygonDrawLayer')) {
view3d.map.findLayerById('LandQueryPolygonDrawLayer').removeAll();
}
clearMeasureActionAndGraphics();
};
const clearMeasureActionAndGraphicsPoint = () => {
if (view3d.map.findLayerById('LandQueryPointDrawLayer')) {
view3d.map.findLayerById('LandQueryPointDrawLayer').removeAll();
}
clearMeasureActionAndGraphics();
};