ArcGIS测距测面(arcgis for js - vue3项目)

news2024/9/9 1:06:19

一、安装arcgis

命令行:

npm install @arcgis/core

二、引入所需依赖

import Draw from "@arcgis/core/views/draw/Draw";
import GraphicsLayer from "@arcgis/core/layers/GraphicsLayer";
import Graphic from "@arcgis/core/Graphic";
import Point from "@arcgis/core/geometry/Point";
import Polyline from "@arcgis/core/geometry/Polyline";
// Pro SDK中的一个关键组件,它提供了一系列用于处理几何图形(Point、Polyline、Polygon……)的方法和算法。例如计算距离、缓冲区分析、叠加分析和几何关系检查等。
import * as geometryEngine from "@arcgis/core/geometry/geometryEngine";
import Polygon from "@arcgis/core/geometry/Polygon";
// GeometryService几何服务模块
import * as geometryService from "@arcgis/core/rest/geometryService.js";
//操作设置长度单位和其他参数
import LengthsParameters from "@arcgis/core/rest/support/LengthsParameters";
// 操作设置面积、周长和其他参数
import AreasAndLengthsParameters from "@arcgis/core/rest/support/AreasAndLengthsParameters";

三、定义对象


let lineLayer = null;
let lineEditLayer = null;
let lineTxtLayer = null;
let areaLayer = null;
let areaEditLayer = null;
let areaTxtLayer = null;

let lineLayerId = "measurementLineLayer";
let lineEditLayerId = "lineEditLayer";
let lineTxtLayerId = "lineTxtLayer";
let areaLayerId = "measurementAreaLayer";
let areaEditLayerId = "areaEditLayer";
let areaTxtLayerId = "areaTxtLayer";

// 缓冲服务对象
const geometryServiceUrl = "http://localhost:6080/arcgis/rest/services/Utilities/Geometry/GeometryServer";

四、实现方法

1、初始化方法(测距测面都可以单独引用)

// 测量工具初始化
export const initMeasure = ((view, map) => {
	lineLayer = map.findLayerById(lineLayerId)
	if (lineLayer === null || lineLayer === undefined) {
		lineLayer = new GraphicsLayer({id: lineLayerId})
		map.add(lineLayer)
	}
	lineLayer.removeAll() //清空上次绘制的线

	lineTxtLayer = map.findLayerById(lineTxtLayerId)
	if (lineTxtLayer === null || lineTxtLayer === undefined) {
		lineTxtLayer = new GraphicsLayer({id: lineTxtLayerId})
		map.add(lineTxtLayer)
	}
	lineTxtLayer.removeAll() //清空上次绘制的标注

	lineEditLayer = map.findLayerById(lineEditLayerId)
	if (lineEditLayer === null || lineEditLayer === undefined) {
		lineEditLayer = new GraphicsLayer({id: lineEditLayerId})
		map.add(lineEditLayer)
	}
	lineEditLayer.removeAll() //清空上次绘制的编辑点

	areaLayer = map.findLayerById(areaLayerId)
	if (areaLayer === null || areaLayer === undefined) {
		areaLayer = new GraphicsLayer({id: areaLayerId})
		map.add(areaLayer)
	}
	areaLayer.removeAll() //清空上次绘制的标注

	areaEditLayer = map.findLayerById(areaEditLayerId)
	if (areaEditLayer === null || areaEditLayer === undefined) {
		areaEditLayer = new GraphicsLayer({id: areaEditLayerId})
		map.add(areaEditLayer)
	}
	areaEditLayer.removeAll() //清空上次绘制的编辑点

	areaTxtLayer = map.findLayerById(areaTxtLayerId)
	if (areaTxtLayer === null || areaTxtLayer === undefined) {
		areaTxtLayer = new GraphicsLayer({id: areaTxtLayerId})
		map.add(areaTxtLayer)
	}
	areaTxtLayer.removeAll() //清空上次绘制的编辑点
});

2、测距方法

/******* 测距 *******/ 
export const measureLine = ((view,map) => {
    // 测距/测面初始化
	initMeasure(view,map);


    let editGps = [];
	// 测距绘制
	let draw = new Draw({
		view: view
	});

    let action = draw.create("polyline");
    // 获取焦点
    view.focus();
    // 顶点添加事件
    action.on('vertex-add',function(evt){
        createPolyline(evt,view,map);
    });

    //顶点移除事件
	action.on('vertex-remove', function (evt) {
		createPolyline(evt,view,map);
	});

	// 鼠标移动事件
	action.on('cursor-update', function (evt) {
		createPolyline(evt, view, map);
	});

	// 绘制完成事件
	action.on('draw-complete', function (evt) {
		createPolyline(evt, view, map);
	})

    // 绘制测线路径
    function createPolyline(event,view,map){
        let vertices = event.vertices;
        lineLayer.removeAll() //清空上次绘制的线
        lineTxtLayer.removeAll() //清空上次绘制的标注
        lineEditLayer.removeAll() //清空上次绘制的编辑点

        let graphic = null;
        //开始绘制时只有一个点,鼠标移动的时候。
        if(vertices.length == 1) {
            addEditPt(lineLayer, event.vertices[0], 0)
        }
      
        //大于两个点,显示线
        if(vertices.length >= 2){
            // 线
            let line = new Polyline({
                paths:vertices,
                spatialReference:view.spatialReference
            });
            // 生成绘制的图形
            graphic = new Graphic({
                geometry:line,
                symbol:createLineSymbol()
            })
            // 线添加到绘制图形中
            lineLayer.add(graphic);
            // 测距单位文字添加
            calLength(line.paths,view);
        }

        // 每次单击添加顶点时添加一个可移动的编辑节点
        if(event.type == "vertex-add"){
            let addGp = addEditPt(lineEditLayer, vertices[event.vertexIndex], event.vertexIndex)
            editGps.push(addGp)
        }
        // 点击后鼠标移动
        if(event.type == "cursor-update") {
            //console.log("cursor-update");
        }
        // 绘制完成
        if(event.type == "draw-complete") {
            graphic.attributes = {
                "drawId": "drawLine"
            }
        }

    }


    // 添加可编辑点
    function addEditPt(layer,addVerties,index){
        let editaddpt = {
			type: "point",
			x: addVerties[0],
			y: addVerties[1],
			spatialReference: view.spatialReference
		}
		let addPtSym = createPointSymbol();
		let editAddGp = new Graphic({
			attributes: {
				"index": index
			},
			geometry: editaddpt,
			symbol: addPtSym
		})
		layer.add(editAddGp);
		return editAddGp;
    }

});



// 计算长度
/**
 * @param verties - 线段集合
 * @param view - MapView容器
 */
function calLength(verties, view){

    let polyline = new Polyline({
		paths: verties,
		spatialReference: view.spatialReference
	});


    let length = parseFloat(geometryEngine.geodesicLength(polyline, 'meters').toFixed(2)) //测距
	
	let content = "距离:" + length + "米";
    
	let txtPt = new Point({
		x: verties[0][0][0],
		y: verties[0][0][1],
		spatialReference: view.spatialReference
	})
	createLineTextGraphic(content, txtPt)
    
    // 使用几何服务计算距离
    // let params = new LengthsParameters({
    //     calculationType:"planar",// 平面
    //     polylines:[polyline]
    // });

    // geometryService.lengths(geometryServiceUrl,params).then(function(results){
       
    //     let length = results.lengths[0];
    //     // 测距的单位
    //     let content = "距离:"+length.toFixed(2) + "米";
    //     // 文字位置
    //     let txPt = new Point({
    //         x:verties[0][0][0],
    //         y:verties[0][0][1],
    //         spatialReference:view.spatialReference
    //     });

    //     createLineTextGraphic(content, txtPt);
    // });

}

//测距文字标注
function createLineTextGraphic(content, point){
    lineTxtLayer.removeAll();// 清除上一次文字内容
    let txtGp = new Graphic({
		geometry: point,
		symbol: createTextSymbol(content)
	});

	lineTxtLayer.add(txtGp);
}

3、测面方法

//******** 测面 **********/
export const measureArea = ((view,map) =>{
	// 测距/测面初始化
	initMeasure(view,map);

	let editGps = [];
	// 测距绘制
	let draw = new Draw({
		view: view
	})
	let action = draw.create("polygon", {
		mode: "click"
	})
	// 获取焦点
	view.focus();
	// 顶点添加事件
	action.on('vertex-add', function (evt) {
		createPolygon(evt, view, map);
	})
	//顶点移除事件
	action.on('vertex-remove', function (evt) {
		createPolygon(evt, view, map);
	})
	// 鼠标移动事件
	action.on('cursor-update', function (evt) {
		createPolygon(evt, view, map);
	})
	// 绘制完成事件
	action.on('draw-complete', function (evt) {
		createPolygon(evt, view, map);
	})

	//根据点坐标生成新的线
	function createPolygon(event, view, map) {
		//获取所有顶点
		let vertices = event.vertices;
		let graphic = null;
		//清除之前绘制
		areaLayer.removeAll();//清空上次绘制的面
		areaEditLayer.removeAll() //清空上次绘制的编辑点
		areaTxtLayer.removeAll() //清空上次绘制的编辑点
		//开始绘制时只有一个点,鼠标移动的时候。
		if(vertices.length == 1) {
			addEditPt(areaLayer, event.vertices[0], 0)
		}
		if(vertices.length == 2) {
			let polyline = new Polyline({
				paths:vertices,
				spatialReference:view.spatialReference
			})
			let polylineGp = new Graphic({
				geometry:polyline,
				symbol: createLineSymbol()
			})
			areaLayer.add(polylineGp)
		}
		if(vertices.length > 2) {
			let polygon = new Polygon({
				hasZ: false,
				hasM: false,
				rings: [vertices],
				spatialReference: view.spatialReference
			})
			// 生成绘制的图形
			graphic = new Graphic({
				geometry: polygon,
				symbol: createFillSymbol()
			});
			// 将绘制的图形添加到view
			areaLayer.add(graphic);
			calArea(polygon,view)
		}

		//每次单击添加顶点时添加一个可移动的编辑节点
		if(event.type == "vertex-add") {
			let addGp = addEditPt(areaEditLayer, vertices[event.vertexIndex], event.vertexIndex)
			editGps.push(addGp)
		}
		if(event.type == "cursor-update") {

		}
		if(event.type == "draw-complete") {
			graphic.attributes = {
				"drawId": "drawArea"
			}
		}
	}

	//添加可编辑点
	function addEditPt(layer, addVerties, index) {
		let editaddpt = {
			type: "point",
			x: addVerties[0],
			y: addVerties[1],
			spatialReference: view.spatialReference
		}
		let addPtSym = createPointSymbol();
		let editAddGp = new Graphic({
			attributes: {
				"index": index
			},
			geometry: editaddpt,
			symbol: addPtSym
		})

		layer.add(editAddGp);

		return editAddGp;
	}

});

//计算面积
function calArea(geom, view) {
	let area = geometryEngine.geodesicArea(geom, "square-meters");
	if(area < 0) {
		// simplify the polygon if needed and calculate the area again
		let simplifiedPolygon = geometryEngine.simplify(geom);
		if(simplifiedPolygon) {
			area = geometryEngine.geodesicArea(simplifiedPolygon, "square-meters");
		}
	}
	let content = "面积:" + area.toFixed(2) + "平方米";
	createAreaTextGraphic(content, geom.centroid);

	// 使用几何服务计算面积
	// let params = new AreasAndLengthsParameters({
	// 	areaUnit:"square-meters",
	// 	calculationType:"planar",
	// 	lengthUnit:"meters",
	// 	polygons:[geom]
	// })
	// geometryService.areasAndLengths(geometryServiceUrl, params).then(function (results) {
	// 	let area = results.areas[0];
	// 	let content = "面积:" + area.toFixed(2) + "平方米";
	// 	createAreaTextGraphic(content, geom.centroid);
	// });

}

//测面积文字标注
function createAreaTextGraphic(content, point) {
	areaTxtLayer.removeAll();
	let txtGp = new Graphic({
		geometry: point,
		symbol: createTextSymbol(content)
	})
	areaTxtLayer.add(txtGp);
}

4、公共方法

//测量清除
export const cleanMeasure = (() => {
	lineLayer.removeAll() //清空上次绘制的线
	lineTxtLayer.removeAll() //清空上次绘制的标注
	lineEditLayer.removeAll() //清空上次绘制的编辑点
	areaLayer.removeAll() //清空上次绘制的标注
	areaEditLayer.removeAll() //清空上次绘制的编辑点
	areaTxtLayer.removeAll() //清空上次绘制的编辑点
});


// 点样式设置
function createPointSymbol(){
	return {  //点样式
		type: "simple-marker",
		color: [255,165,0,0.5],
		style: "circle",
		width: 1,
		size: 10,
		outline:{//点的边界线
			color: [255,255,255,0.5],
			width: 1
		}
	}
}

// 线段样式设置
function createLineSymbol(){
	return  {
		type: "simple-line", // autocasts as new SimpleFillSymbol
		color: "#ff5502",
		width: 2,
		cap: "round",
		join: "round"
	}
}

// 填充样式设置
function createFillSymbol(){
	return {
		type: "simple-fill", // autocasts as new SimpleFillSymbol()
		color: [255,85,2,0.5],
		style: "solid",
		outline: { // autocasts as new SimpleLineSymbol()
			color: "orange",
			width: 2
		}
	}
}

// 文字符号设置
function createTextSymbol(content){
	return {
		type: "text",
		text: content,
		color: 'green',
		font: {
			size: 15,
		}
	}
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1958872.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

灯具外贸公司用什么企业邮箱好

灯具外贸公司面对海外市场的推广、产品销售、客户沟通、市场信息收集等多重需求&#xff0c;选择一个合适的企业邮箱显得尤为重要。本文将介绍灯具外贸公司为什么应选择Zoho Mail企业邮箱&#xff0c;并详细探讨其优势和功能。 一、公司背景 广东省深圳市光明新区&#xff0c…

创建 Llama-3.1-70B-Japanese-Instruct-2407 的 Ollama 模型

创建 Llama-3.1-70B-Japanese-Instruct-2407 的 Ollama 模型 1. 下载 gguf 文件2. 创建 Modelfile3. 创建 Ollama 模型4. 运行 Ollama 模型5. &#xff08;可选&#xff09;其他 Modelfile 1. 下载 gguf 文件 使用浏览器打开 https://huggingface.co/mmnga/Llama-3.1-70B-Japa…

DELL服务器RAID配置详细教程

DELL服务器RAID配置教程 在启动电脑的时候按CTRLR 进入 RAID 设置见面如下图 名称解释&#xff1a; Disk Group&#xff1a;磁盘组&#xff0c;这里相当于是阵列&#xff0c;例如配置了一个RAID5&#xff0c;就是一个磁盘组 VD(Virtual Disk)&#xff1a; 虚拟磁盘&#xff…

FFmpeg模块详解:深入理解多媒体框架的构成

&#x1f60e; 作者介绍&#xff1a;欢迎来到我的主页&#x1f448;&#xff0c;我是程序员行者孙&#xff0c;一个热爱分享技术的制能工人。计算机本硕&#xff0c;人工制能研究生。公众号&#xff1a;AI Sun&#xff08;领取大厂面经等资料&#xff09;&#xff0c;欢迎加我的…

为了人才任正非一个月蹲守人家单位门口,刘备三顾茅庐算啥!

张一鸣说&#xff1a;"一名优秀的CEO首先应该是优秀的HR&#xff01;”这句话广为流传&#xff0c;此言差矣&#xff0c;一名卓越的创始人首先应该是最卓越的猎头&#xff0c;比如任正非&#xff01; 全球的创始人也没几个人能够做像任正非那样重视人才的&#xff0c;一旦…

成为git砖家(7): posh-git的安装和使用

文章目录 1. PowerShell 里的 git 默认使用体验不够好2. posh-git 介绍2.1 安装 posh-git2.2 PS1 显示的内容2.3 补全分支 1. PowerShell 里的 git 默认使用体验不够好 在 Windows 系统上&#xff0c;安装了 git for windows 后&#xff0c; git bash 里的体验确实不错。 但是…

【云原生】kubernetes弃用docker,containerd风华正茂,何以承载云原生?

✨✨ 欢迎大家来到景天科技苑✨✨ &#x1f388;&#x1f388; 养成好习惯&#xff0c;先赞后看哦~&#x1f388;&#x1f388; &#x1f3c6; 作者简介&#xff1a;景天科技苑 &#x1f3c6;《头衔》&#xff1a;大厂架构师&#xff0c;华为云开发者社区专家博主&#xff0c;…

JAVA基础 - 泛型

目录 一. 简介 二. 集合泛型 三. 自定义泛型 四. 自定义泛型类和普通类的区别 一. 简介 泛型是 Java 语言中一种强大的特性&#xff0c;它允许在定义类、接口和方法时使用类型参数&#xff0c;从而增加了代码的类型安全性和复用性。 类型安全性&#xff1a; 使用泛型可以…

leetcode日记(60)编辑距离

感觉这题不是按难度划分的而是按代码长度划分的…看了答案才知道怎么做&#xff0c;其实思路很简单&#xff0c;但是特别难想…… 意思是使用动态规划&#xff0c;依次计算由word1的前i个字母到word2的前j个字母要经历的最小变化数。 min D[i][j]min(D[i-1][j]1,D[i][j-1]1,D…

spring 中包自动扫描之 component-scan 解析

在 spring 中&#xff0c;为简化 bean 的配置&#xff0c;在 spring-context 模块下提供了包的自动扫描功能&#xff0c;将配置的包及其子包下的所有符合条件的类都注册到 BeanFactory 中。下面来看下具体是怎么实现的。 配置 <context:component-scan base-package"…

【MIT 6.5840(6.824)学习笔记】Raft

1 脑裂 许多容错系统使用一个单主节点来决定主副本。 MapReduce&#xff1a;由单主节点控制计算复制。GFS&#xff1a;主备复制数据&#xff0c;并由单主节点确定主拷贝的位置。VMware FT&#xff1a;主虚机和备份虚机之间复制指令&#xff0c;需要单点的Test-and-Set服务确认…

[0729] X-CMD 发布 v0.4.3:借助 fzf ,提升用户使用体验

目录 X-CMD 发布 v0.4.3&#x1f50e; ll&#x1f50e; jq&#x1f50e; yq&#x1f50e; man X-CMD 发布 v0.4.3 &#x1f50e; ll 新增 --fzf 子命令 该命令借助 fzf 为用户提供了一种高效查找文件和目录的相关信息的方法&#xff0c;类似于文件管理器。 # 使用 fzf 查找文…

AI智能名片O2O商城小程序源码在社区团购中的应用与红利深度探索

摘要&#xff1a;在数字化转型的浪潮中&#xff0c;社区团购以其独特的商业模式和强大的市场渗透力&#xff0c;成为新零售领域的一股不可忽视的力量。而AI智能名片O2O商城小程序源码&#xff0c;作为技术创新的集大成者&#xff0c;正逐步渗透并深刻改变着社区团购的运作模式和…

从零开始编写一个Chrome插件:详细教程

个人名片 🎓作者简介:java领域优质创作者 🌐个人主页:码农阿豪 📞工作室:新空间代码工作室(提供各种软件服务) 💌个人邮箱:[2435024119@qq.com] 📱个人微信:15279484656 🌐个人导航网站:www.forff.top 💡座右铭:总有人要赢。为什么不能是我呢? 专栏导…

科普文:抽屉合同/协议

抽屉协议是指一种在特定情境下&#xff0c;当事人之间私下签订的、不公开披露的协议。通常情况下&#xff0c;除了协议双方外&#xff0c;其他人并不知道这份协议的存在。这种协议在需要时会被拿出来&#xff0c;因为它已经过双方签字盖章&#xff0c;同样具有法律效应。 背景…

SN65MLVD080使用手册

8通道半双工M-LVDS线路收发器 特性 低压差分30欧姆至55欧姆线路驱动器和接收器&#xff0c;支持信号速率高达250 Mbps&#xff1b;时钟频率高达125 MHz 满足或超过M-LVDS标准TIA/EIA-899多点数据交换规范 受控驱动器输出电压转换时间&#xff0c;提高信号质量 -1V至3.4V共模…

【C++版本】protobuf与gRPC

文章目录 一、Protobuf二、安装以及使用protoc参考 一、Protobuf Google Protocol Buffers&#xff08;protobuf&#xff09;是一种语言中立、平台中立的序列化协议&#xff0c;旨在高效地将结构化数据进行序列化和反序列化。它主要用于通信协议、数据存储和其他需要高效编码和…

【CAN通讯系列5】CAN数据帧及其仲裁

在CAN通讯系列3-CAN通讯如何传递信号中&#xff0c;由于传递信号的分析需要&#xff0c;引出了CAN数据帧的ID&#xff0c;长度和数据段的概念&#xff0c;它们都与CAN协议帧相关。CAN协议帧有5种类型&#xff0c;如下表&#xff1a; 而我们当前使用到的是数据帧&#xff0c;故本…

【Qwen-Audio部署实战】Qwen-Audio-Chat模型之FastApi部署实战

系列篇章&#x1f4a5; No.文章1【Qwen部署实战】探索Qwen-7B-Chat&#xff1a;阿里云大型语言模型的对话实践2【Qwen2部署实战】Qwen2初体验&#xff1a;用Transformers打造智能聊天机器人3【Qwen2部署实战】探索Qwen2-7B&#xff1a;通过FastApi框架实现API的部署与调用4【Q…

10 BERT

目录 1 综述 1.1 BERT的核心思想 1.2 BERT的关键技术&#xff1a;预训练阶段 1.3 微调阶段 2 BERT的架构 2.1 输入处理 3. 特征选择/学习模块 BERT 的自注意力过程 4. 预训练任务&#xff1a;同时进行 4.1 Next Sentence Prediction (NSP) 4.2 Masked Language Model…