const UniMap = require('uni-map-common');
const configCenter = require("uni-config-center");
var UniMapConfig = configCenter({ pluginId: 'uni-map' }).requireFile('config.js');
var LocalMapConfig = {
"default": "",
"key": {
"qqmap": "",
"amap": "",
}
}
const db = uniCloud.database();
const _ = db.command;
const $ = _.aggregate;
const opendbPoiDB = db.collection("opendb-poi");
class MyError extends Error {
constructor(errMsg, errCode = -1) {
super(errMsg);
this.err = {
errCode,
errMsg
}
}
}
module.exports = {
_before: function() {
if (!UniMapConfig) {
UniMapConfig = LocalMapConfig;
}
let defaultProvider = UniMapConfig.default || "qqmap";
let params = this.getParams();
let {
provider = defaultProvider,
needOriginalResult = false
} = params[0] || {};
const key = UniMapConfig.key[provider] || LocalMapConfig.key[provider];
if (!key) {
throw { errCode: -1, errMsg: `请在uni-config-center/uni-map/config.js中或LocalMapConfig中配置地图供应商${provider}对应的key` };
}
let uniMap = new UniMap({
provider: provider,
key: key,
needOriginalResult
});
this.uniMap = uniMap;
},
_after: function(err, res) {
if (err) {
if (err.err) {
return err.err;
}
if (err.errCode) {
return err;
}
throw err;
}
console.log("result", res.result);
return res;
},
async chooseLocation(parame = {}) {
let res = {};
let {
action,
data,
needOriginalResult
} = parame;
const uniMap = this.uniMap;
let result = await uniMap[action](data);
res.result = needOriginalResult ? result.originalResult : result;
return res;
},
async location2address(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.location2address(data);
res.result = result;
return res;
},
async address2location(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.address2location(data);
res.result = result;
return res;
},
async translate(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.translate(data);
res.result = result;
return res;
},
async ip2location(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.ip2location(data);
res.result = result;
return res;
},
async inputtips(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.inputtips(data);
res.result = result;
return res;
},
async search(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.search(data);
res.result = result;
return res;
},
async districtSearch(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.districtSearch(data);
res.result = result;
return res;
},
async route(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.route(data);
res.result = result;
return res;
},
async clearPoi(data = {}) {
let res = { errCode: 0 };
const db = uniCloud.database();
await db.collection("opendb-poi").where({
is_random: true
}).remove();
return res;
},
async initStatic001(data = {}) {
let res = { errCode: 0 };
const category = "static-001";
await opendbPoiDB.where({
category: category
}).remove();
let tiananmen = {
longitude: 116.39747,
latitude: 39.908823,
};
let time = Date.now();
let list = [];
for (let i = 1; i <= 6; i++) {
let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 10);
list.push({
category: category,
type: "门店",
title: `随机门店-${i}`,
location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
create_date: time,
visible: true,
is_random: true,
level: i
});
}
let randomCoordinate = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 1);
list.push({
category: category,
type: "总部",
title: `随机总部`,
location: new db.Geo.Point(randomCoordinate.longitude, randomCoordinate.latitude),
create_date: time,
visible: true,
is_random: true,
level: 7
});
await opendbPoiDB.add(list);
return res;
},
async initDynamics001(data = {}) {
let res = { errCode: 0 };
const category = "dynamics-001";
await opendbPoiDB.where({
category: category
}).remove();
let tiananmen = {
longitude: 116.39747,
latitude: 39.908823,
};
let time = Date.now();
let randomCoordinate1 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2);
let data1 = {
category: category,
type: "配送员",
title: "配送员",
location: new db.Geo.Point(randomCoordinate1.longitude, randomCoordinate1.latitude),
create_date: time,
visible: true,
is_random: true,
}
let randomCoordinate2 = getRandomCoordinateWithinRadius(tiananmen.longitude, tiananmen.latitude, 2);
let data2 = {
category: category,
type: "目的地",
title: "配送目的地",
location: new db.Geo.Point(randomCoordinate2.longitude, randomCoordinate2.latitude),
create_date: time,
visible: true,
is_random: true,
}
let list = [data1, data2];
await opendbPoiDB.add(list);
const uniMap = this.uniMap;
let result = await uniMap.route({
mode: "ebicycling",
from: `${randomCoordinate1.latitude},${randomCoordinate1.longitude}`,
to: `${randomCoordinate2.latitude},${randomCoordinate2.longitude}`,
alternative_route: 1
});
let route = result.result.routes[0];
let { steps = [] } = route;
let points = [];
steps.map((step) => {
let {
polyline = ""
} = step;
let arr = polyline.split(";");
arr.map((item) => {
let arr2 = item.split(",");
points.push({
latitude: arr2[0],
longitude: arr2[1],
});
});
});
let polyline = {
points,
color: "#19b411",
width: 6,
dottedLine: false,
arrowLine: true,
borderWidth: 1,
borderColor: "#000000",
};
res.polyline = [polyline];
return res;
},
async getPolyline(data = {}) {
let res = { errCode: 0 };
const category = "dynamics-001";
let getRes1 = await opendbPoiDB.where({
category: category,
type: "配送员",
visible: true
}).get();
let poi1 = getRes1.data[0];
let getRes2 = await opendbPoiDB.where({
category: category,
type: "目的地",
visible: true
}).get();
let poi2 = getRes2.data[0];
if (!poi2) {
return {
errCode: 0,
end: true
}
}
let coordinate1 = {
longitude: poi1.location.coordinates[0],
latitude: poi1.location.coordinates[1]
};
let coordinate2 = {
longitude: poi2.location.coordinates[0],
latitude: poi2.location.coordinates[1]
};
const uniMap = this.uniMap;
let result = await uniMap.route({
mode: "ebicycling",
from: `${coordinate1.latitude},${coordinate1.longitude}`,
to: `${coordinate2.latitude},${coordinate2.longitude}`,
alternative_route: 1
});
let route = result.result.routes[0];
let { steps = [], distance, duration } = route;
let points = [];
let dir_desc;
steps.map((step) => {
let {
polyline = ""
} = step;
if (!dir_desc) dir_desc = step.dir_desc;
if (polyline) {
let arr = polyline.split(";");
arr.map((item) => {
let arr2 = item.split(",");
if (!isNaN(arr2[0]) && !isNaN(arr2[1])) {
points.push({
latitude: Number(arr2[0]),
longitude: Number(arr2[1]),
});
}
});
}
});
let polyline = {
points,
color: "#19b411",
width: 6,
dottedLine: false,
arrowLine: true,
borderWidth: 1,
borderColor: "#000000",
};
res.polyline = [polyline];
if (distance <= 30 || duration <= 0) {
await opendbPoiDB.doc(poi1._id).update({
title: `配送员已到达目的地`,
location: new db.Geo.Point(Number(coordinate2.longitude), Number(coordinate2.latitude)),
rotate: 0
});
await opendbPoiDB.doc(poi2._id).update({
visible: false,
});
return {
errCode: 0,
end: true
}
} else {
let rotate = 0;
if (points && points.length >= 2) {
rotate = calculateDirectionAngle(points[0], points[1]);
}
await opendbPoiDB.doc(poi1._id).update({
title: `配送员正在配送\r\n还有 ${distance} 米\r\n预计 ${duration} 分钟送达`,
rotate: rotate,
});
}
return res;
},
async updateMyLocation(data = {}) {
let res = {};
const category = "dynamics-001";
let {
longitude,
latitude
} = data;
let getRes1 = await opendbPoiDB.where({
category: category,
type: "配送员",
visible: true
}).get();
let poi1 = getRes1.data[0];
await opendbPoiDB.doc(poi1._id).update({
location: new db.Geo.Point(Number(longitude), Number(latitude))
});
return res;
},
async test(data = {}) {
let res = {};
const uniMap = this.uniMap;
let result = await uniMap.location2address({
});
res.result = result;
return res;
}
}
* 生成在指定经纬度圆内的随机坐标
const latitude = 39.908823; // 指定纬度
const longitude = 116.39747; // 指定经度
const radiusInKm = 10; // 指定圆的半径(单位:千米)
const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
console.log(randomCoordinate);
*/
function getRandomCoordinateWithinRadius(longitude, latitude, radiusInKm) {
const earthRadius = 6371;
const radiusInRad = radiusInKm / earthRadius;
const randomAngleRad = Math.random() * 2 * Math.PI;
const randomDistanceRad = Math.acos(Math.random() * (Math.cos(radiusInRad) - 1) + 1);
const randomLatitudeRad = latitude * (Math.PI / 180) + randomDistanceRad * Math.cos(randomAngleRad);
const randomLongitudeRad = longitude * (Math.PI / 180) + randomDistanceRad * Math.sin(randomAngleRad) / Math.cos(latitude * (Math.PI / 180));
const randomLatitude = parseFloat((randomLatitudeRad * (180 / Math.PI)).toFixed(6));
const randomLongitude = parseFloat((randomLongitudeRad * (180 / Math.PI)).toFixed(6));
return { latitude: randomLatitude, longitude: randomLongitude };
}
* 计算坐标B在坐标A的方向,0代表正西方 90 代表正北方
const latitude = 39.908823; // 指定纬度
const longitude = 116.39747; // 指定经度
const radiusInKm = 10; // 指定圆的半径(单位:千米)
const randomCoordinate = getRandomCoordinateWithinRadius(latitude, longitude, radiusInKm);
console.log(randomCoordinate);
*/
function calculateDirectionAngle(coordA, coordB) {
const toRadians = (angle) => angle * (Math.PI / 180);
const toDegrees = (angle) => angle * (180 / Math.PI);
const lat1 = toRadians(coordA.latitude);
const lon1 = toRadians(coordA.longitude);
const lat2 = toRadians(coordB.latitude);
const lon2 = toRadians(coordB.longitude);
const dLon = lon2 - lon1;
const y = Math.sin(dLon) * Math.cos(lat2);
const x =
Math.cos(lat1) * Math.sin(lat2) -
Math.sin(lat1) * Math.cos(lat2) * Math.cos(dLon);
const angleRadians = Math.atan2(y, x);
let angleDegrees = toDegrees(angleRadians);
angleDegrees = (angleDegrees + 360) % 360;
angleDegrees = (angleDegrees > 180) ? angleDegrees - 180 : angleDegrees + 180;
angleDegrees -= 90;
return angleDegrees;
}