路徑分析本人是基於高德來做的,調用百度的大致過程類似,只是修改座標轉換的方法,此處就不放出基於百度的路徑分析了;
先說下此功能的思路,由於高德的座標系是國測局的,而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];
-
}