Cesiumjs 高德路径规划

路径分析本人是基于高德来做的,调用百度的大致过程类似,只是修改坐标转换的方法,此处就不放出基于百度的路径分析了;
先说下此功能的思路,由于高德的坐标系是国测局的,而cesium的坐标系是wgs84的,故要对偏差进行处理,处理之后再进行模拟;
这里调用的是驾驶车辆的路径规划,高德支持步行、驾车等多种路径规划;
一般高德一次性会计算出多条线路,此处为了展示方便,取第一条线路来进行展示。此处计算的是两点之间的用时最少的路线。

高德计算两点之间的路径后,会提供多种选择,比如 用时最少、距离最短、躲避拥堵、避免收费等,多种结果的选择为项目的开发提供了极大的便利,并提供了丰富的效果展示;

大致步骤:

1、先在图上拾取两点坐标,对坐标进行偏差处理;

2、传入高德服务接口,获取路径结果。

3、对路径结果进行二次偏差处理。

4、展示路线,及模拟车辆运动,模拟沿此路径跑完全程。

其中车辆的模拟运动支持设置跑完全程的时间,及车辆移动的速度;
代码如下:如果你是个新手,可以好好感悟下我的代码,相信你会有所收获的!

 
  • function getCatesian3FromPX(px, viewer, entity) {

  • var pick = viewer.scene.pick(px);

  • var cartesian;

  • var drillPick = viewer.scene.drillPick(px);

  • var truePick = null;

  • if (entity) {

  • for (var i = 0; i < drillPick.length; i++) {

  • if (drillPick[i].id._id != entity.id) {

  • truePick = drillPick[i].id;

  • break;

  • }

  • }

  • } else {

  • truePick = pick;

  • }

  • if (viewer.scene.pickPositionSupported && Cesium.defined(truePick)) {

  • cartesian = viewer.scene.pickPosition(px);

  • } else {

  • var ray = viewer.camera.getPickRay(px);

  • if (!ray) return;

  • cartesian = viewer.scene.globe.pick(ray, viewer.scene);

  • }

  • return cartesian;

  • }

  •  
  • function cartesianToLnglat(cartesian, isToWgs84) {

  • if (!cartesian) return;

  • var ellipsoid = viewer.scene.globe.ellipsoid;

  • var lnglat = ellipsoid.cartesianToCartographic(cartesian);

  • //var cartographic = Cesium.Cartographic.fromCartesian(cartesian);

  • if (isToWgs84) {

  • var lat = Cesium.Math.toDegrees(lnglat.latitude);

  • var lng = Cesium.Math.toDegrees(lnglat.longitude);

  • var hei = lnglat.height;

  • return [lng, lat, hei];

  • } else {

  • return [lnglat.longitude, lnglat.latitude, lnglat.height];

  • }

  •  
  • }

  • function lnglatToCartesian(lnglat) { //经纬度转世界坐标 [101,40]

  • if (!lnglat) return null;

  • return Cesium.Cartesian3.fromDegrees(lnglat[0], lnglat[1], lnglat[2] || 0);

  • }

  •  
  • function lnglatArrToCartesianArr(lnglatArr) {

  • if (!lnglatArr) return [];

  • var arr = [];

  • for (var i = 0; i < lnglatArr.length; i++) {

  • arr.push(lnglatToCartesian(lnglatArr[i]));

  • }

  • return arr;

  • }

  •  
  •  
  • var viewer = new Cesium.Viewer('map', {

  • imageryProvider: new Cesium.ArcGisMapServerImageryProvider({

  • url: "https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer"

  • }),

  • terrainProvider: new Cesium.CesiumTerrainProvider({ //加载火星在线地形

  • url: "http://data.marsgis.cn/terrain"

  • })

  • });

  • class searchRoute {

  • constructor(start, end) {

  • this.startP = start;

  • this.endP = end;

  • }

  • start(opt) {

  • var startP = wgs2gcj(this.startP);

  • var endP = wgs2gcj(this.endP);

  • $.ajax({

  • url: "http://restapi.amap.com/v3/direction/driving",

  • type: "GET",

  • dataType: "jsonp",

  • timeout: "5000",

  • contentType: "application/json;utf-8",

  • data: {

  • "output": "json",

  • "extensions": "all",

  • "key": "你的key",

  • "origin": startP[0] + "," + startP[1],

  • "destination": endP[0] + "," + endP[1],

  • "strategy": opt.strategy || 10

  • },

  • success: function(json) {

  • // 由于线涉及坐标较多 此处返回的坐标 未转为wgs84

  • var data = "";

  • if (!json || !json.route || !json.route.paths) {

  • data = "";

  • } else {

  • data = json.route.paths;

  • }

  • opt.callback(data);

  • },

  • error: function(data) {}

  • });

  • }

  • }

  • var handler = new Cesium.ScreenSpaceEventHandler(viewer.scene.canvas);

  • var isClickAgain = false;

  • var start = null;

  • var entd = null;

  • handler.setInputAction(function(evt) { //单机开始绘制

  • var pick = viewer.scene.pick(evt.position);

  • var cartesian = getCatesian3FromPX(evt.position, viewer);

  • if (!isClickAgain) {

  • isClickAgain = true;

  • start = viewer.entities.add({

  • name: "图标点",

  • position: cartesian,

  • billboard: {

  • image: 'mark4.png',

  • scale: 1,

  • horizontalOrigin: Cesium.HorizontalOrigin.CENTER,

  • verticalOrigin: Cesium.VerticalOrigin.BOTTOM

  • }

  • });

  • return;

  • }

  • if (isClickAgain) {

  • end = viewer.entities.add({

  • name: "图标点",

  • position: cartesian,

  • billboard: {

  • image: 'mark2.png',

  • scale: 1,

  • horizontalOrigin: Cesium.HorizontalOrigin.CENTER,

  • verticalOrigin: Cesium.VerticalOrigin.BOTTOM

  • }

  • });

  • showRes(start.position.getValue(), end.position.getValue());

  • handler.destroy();

  • }

  • }, Cesium.ScreenSpaceEventType.LEFT_CLICK);

  •  
  • function showRes(start, end) {

  • if (!start || !end) return;

  • var startp = cartesianToLnglat(start, true);

  • var endP = cartesianToLnglat(end, true);

  • var search = new searchRoute([startp[0], startp[1]], [endP[0], endP[1]]);

  • search.start({

  • strategy: 11,

  • callback: function(data) {

  • addRouteLine(data[0]);

  • }

  • })

  • }

  •  
  • function addRouteLine(res) {

  • var arr = [];

  • var steps = res.steps;

  • for (var i = 0; i < steps.length; i++) {

  • var item = steps[i];

  • var positionStr = item.polyline;

  • var strArr = positionStr.split(";");

  • for (var z = 0; z < strArr.length; z++) {

  • var item2 = strArr[z];

  • var strArr2 = item2.split(",");

  • var p = gcj2wgs(strArr2);

  • arr.push(p);

  • }

  • }

  • var cartesians = lnglatArrToCartesianArr(arr);

  • var line = viewer.entities.add({

  • polyline: {

  • positions: cartesians,

  • clampToGround: true,

  • material: Cesium.Color.RED.withAlpha(1),

  • width: 3

  • }

  • });

  • moveOnRoute(line);

  • }

  • //汽车移动=========================

  • var qicheModel = null;

  • function moveOnRoute(lineEntity) {

  • if (!lineEntity) return;

  • var positions = lineEntity.polyline.positions.getValue();

  • if (!positions) return;

  • var allDis = 0;

  • for (var index = 0; index < positions.length - 1; index++) {

  • var dis = Cesium.Cartesian3.distance(positions[index], positions[index + 1]);

  • allDis += dis;

  • }

  • var playTime = 100;

  • var v = allDis / playTime;

  • var startTime = viewer.clock.currentTime;

  • var endTime = Cesium.JulianDate.addSeconds(startTime, playTime, new Cesium.JulianDate());

  • var property = new Cesium.SampledPositionProperty();

  • var t = 0;

  • for (var i = 1; i < positions.length; i++) {

  • if (i == 1) {

  • property.addSample(startTime, positions[0]);

  • }

  • var dis = Cesium.Cartesian3.distance(positions[i], positions[i - 1]);

  • var time = dis / v + t;

  • var julianDate = Cesium.JulianDate.addSeconds(startTime, time, new Cesium.JulianDate());

  • property.addSample(julianDate, positions[i]);

  • t += dis / v;

  • }

  • if (qicheModel) {

  • window.viewer.entities.remove(qicheModel);

  • qicheModel = null;

  • }

  • qicheModel = viewer.entities.add({

  • position: property,

  • orientation: new Cesium.VelocityOrientationProperty(property),

  • model: {

  • uri: "car.glb",

  • scale: 30

  • }

  • });

  • viewer.clock.currentTime = startTime;

  • viewer.clock.multiplier = 1;

  • viewer.clock.shouldAnimate = true;

  • viewer.clock.stopTime = endTime;

  • }

  •  
  • //坐标转换==================================

  • var x_PI = 3.14159265358979324 * 3000.0 / 180.0;

  • var PI = 3.1415926535897932384626;

  • var a = 6378245.0;

  • var ee = 0.00669342162296594323;

  • function transformWD(lng, lat) {

  • var ret = -100.0 + 2.0 * lng + 3.0 * lat + 0.2 * lat * lat + 0.1 * lng * lat + 0.2 * Math.sqrt(Math.abs(lng));

  • ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;

  • ret += (20.0 * Math.sin(lat * PI) + 40.0 * Math.sin(lat / 3.0 * PI)) * 2.0 / 3.0;

  • ret += (160.0 * Math.sin(lat / 12.0 * PI) + 320 * Math.sin(lat * PI / 30.0)) * 2.0 / 3.0;

  • return ret;

  • }

  • function transformJD(lng, lat) {

  • var ret = 300.0 + lng + 2.0 * lat + 0.1 * lng * lng + 0.1 * lng * lat + 0.1 * Math.sqrt(Math.abs(lng));

  • ret += (20.0 * Math.sin(6.0 * lng * PI) + 20.0 * Math.sin(2.0 * lng * PI)) * 2.0 / 3.0;

  • ret += (20.0 * Math.sin(lng * PI) + 40.0 * Math.sin(lng / 3.0 * PI)) * 2.0 / 3.0;

  • ret += (150.0 * Math.sin(lng / 12.0 * PI) + 300.0 * Math.sin(lng / 30.0 * PI)) * 2.0 / 3.0;

  • return ret;

  • }

  • function wgs2gcj(arrdata) {

  • var lng = Number(arrdata[0]);

  • var lat = Number(arrdata[1]);

  • var dlat = transformWD(lng - 105.0, lat - 35.0);

  • var dlng = transformJD(lng - 105.0, lat - 35.0);

  • var radlat = lat / 180.0 * PI;

  • var magic = Math.sin(radlat);

  • magic = 1 - ee * magic * magic;

  • var sqrtmagic = Math.sqrt(magic);

  • dlat = dlat * 180.0 / (a * (1 - ee) / (magic * sqrtmagic) * PI);

  • dlng = dlng * 180.0 / (a / sqrtmagic * Math.cos(radlat) * PI);

  • var mglat = lat + dlat;

  • var mglng = lng + dlng;

  •  
  • mglng = Number(mglng.toFixed(6));

  • mglat = Number(mglat.toFixed(6));

  • return [mglng, mglat];

  •  
  • };

  •  
  • function gcj2wgs(arrdata) {

  • var lng = Number(arrdata[0]);

  • var lat = Number(arrdata[1]);

  • var dlat = transformWD(lng - 105.0, lat - 35.0);

  • var dlng = transformJD(lng - 105.0, lat - 35.0);

  • var radlat = lat / 180.0 * PI;

  • var magic = Math.sin(radlat);

  • magic = 1 - ee * magic * magic;

  • var sqrtmagic = Math.sqrt(magic);

  • dlat = dlat * 180.0 / (a * (1 - ee) / (magic * sqrtmagic) * PI);

  • dlng = dlng * 180.0 / (a / sqrtmagic * Math.cos(radlat) * PI);

  •  
  • var mglat = lat + dlat;

  • var mglng = lng + dlng;

  •  
  • var jd = lng * 2 - mglng;

  • var wd = lat * 2 - mglat;

  •  
  • jd = Number(jd.toFixed(6));

  • wd = Number(wd.toFixed(6));

  • return [jd, wd];

  •  
  • }

对于使用OpenLayers进行高德地图路径规划,你可以按照以下步骤进行操作: 1. 首先,确保已经引入OpenLayers和高德地图的API,可以使用以下代码引入: ```html <script src="https://cdn.bootcdn.net/ajax/libs/openlayers/6.5.0/ol.js"></script> <script src="https://webapi.amap.com/maps?v=2.0&key=YOUR_AMAP_API_KEY"></script> ``` 其中,将`YOUR_AMAP_API_KEY`替换为你自己的高德地图API密钥。 2. 创建一个地图容器,可以使用以下代码创建一个具有特定中心点和缩放级别的地图: ```javascript var map = new ol.Map({ target: 'map-container', // 替换为你的地图容器的ID layers: [ new ol.layer.Tile({ source: new ol.source.OSM(), }), ], view: new ol.View({ center: ol.proj.fromLonLat([YOUR_LONGITUDE, YOUR_LATITUDE]), // 替换为你的地理坐标 zoom: YOUR_ZOOM_LEVEL, // 替换为你的缩放级别 }), }); ``` 请将`YOUR_LONGITUDE`和`YOUR_LATITUDE`替换为你所需的地理坐标,将`YOUR_ZOOM_LEVEL`替换为你需要的缩放级别。 3. 创建路径规划服务对象,并调用路径规划接口进行路径规划。以下是一个简单的示例代码: ```javascript // 创建路径规划服务对象 var drivingService = new AMap.Driving({ map: map, // 将地图对象传入,用于展示规划结果 panel: 'result-panel', // 替换为你的结果面板的ID,用于展示文字结果 }); // 调用路径规划接口进行规划 drivingService.search([ { keyword: '起点地址' }, { keyword: '终点地址' }, ], function(status, result) { if (status === 'complete') { console.log('规划成功'); console.log(result); // 输出规划结果 } else { console.log('规划失败'); } }); ``` 请将`起点地址`和`终点地址`替换为你需要规划的起点和终点地址。你可以将规划结果展示在地图上,并在结果面板中展示文字结果。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

allenjiao

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值