@jcmap-sdk-web/navegador
Version:
甲虫室内定位导航引擎
1,000 lines (837 loc) • 38 kB
JavaScript
import _slicedToArray from '@babel/runtime/helpers/esm/slicedToArray';
import _toConsumableArray from '@babel/runtime/helpers/esm/toConsumableArray';
import _objectSpread from '@babel/runtime/helpers/esm/objectSpread2';
import _toArray from '@babel/runtime/helpers/esm/toArray';
import _classCallCheck from '@babel/runtime/helpers/esm/classCallCheck';
import _createClass from '@babel/runtime/helpers/esm/createClass';
import _inherits from '@babel/runtime/helpers/esm/inherits';
import _createSuper from '@babel/runtime/helpers/esm/createSuper';
import { EventEmitter } from 'events';
import { getCoord, getCoords } from '@turf/invariant';
import turfDistance from '@turf/distance';
import { propOr, pathOr, range } from 'ramda';
import turfAlong from '@turf/along';
import { lineString, convertLength, point, featureCollection } from '@turf/helpers';
import { JCMapNavigadorCoreNavigation } from '@jcmap-sdk-web/navegador-core';
var NavigationModes = {
Walking: 0,
Driving: 1
};
var NavigationDisplayModes = {
ARROW_UP: "视角",
FACE_NORTH: "正北",
LINE_UP: "线路"
};
var Directions = {
Keep: 0,
Left: 11,
Right: 12,
Straight: 13,
Arrive: 14,
LeftArrive: 15,
RightArrive: 16,
LeftForward: 17,
RightForward: 18,
LeftLeft: 21,
LeftRight: 22,
RightRight: 23,
RightLeft: 24,
LeftChangeFloor: 25,
RightChangeFloor: 26,
LeftChangeFloorLeft: 27,
LeftChangeFloorRight: 28,
LeftChangeFloorStraight: 29,
RightChangeFloorLeft: 30,
RightChangeFloorRight: 31,
RightChangeFloorStraight: 32,
StraightChangeFloorLeft: 33,
StraightChangeFloorRight: 34,
ChangeFloor: 35,
StraightChangeFloorStraight: 36
};
var WALK_SPEED_PER_MINUTE = 5000 / 60; // 约 5 km/h,参考 https://en.wikipedia.org/wiki/Preferred_walking_speed
/**
* 导航任务
*/
var NavegadorTask = /*#__PURE__*/function (_EventEmitter) {
_inherits(NavegadorTask, _EventEmitter);
var _super = _createSuper(NavegadorTask);
function NavegadorTask(options) {
var _this;
_classCallCheck(this, NavegadorTask);
_this = _super.call(this);
/**
* 动画时间,因为行走速度很慢
*/
_this.animaTime = 950;
var navegador = _this.navegador = options.navegador;
var navigationMode = _this.navigationMode = options.navigationMode;
var finishingPoint = _this.finishingPoint = options.finishingPoint;
var startingPoint = _this.startingPoint = options.startingPoint;
var routeOptions = _this.routeOptions = options.routeOptions;
_this.offRoadCountLimit = propOr(5, "offRoadCountLimit", options);
_this.backwardCountLimit = propOr(5, "backwardCountLimit", options);
_this.offRoadCount = 0;
_this.backwardCount = 0;
_this.timeDiffCountAdjust = propOr(1, "timeDiffCountAdjust", options);
_this.distanceCountAdjust = propOr(1, "distanceCountAdjust", options);
_this.cartogramDiffCountAdjust = propOr(1, "cartogramDiffCountAdjust", options);
_this.locationAccuracyAdjust = propOr(0.05, "locationAccuracyAdjust", options);
_this.offRoadMinDistance = {
bluetooth: pathOr(8, ["offRoadMinDistance", "bluetooth"], options),
satellite: pathOr(8, ["offRoadMinDistance", "satellite"], options)
};
navegador.setCurrentArrivalDistance(options.arrivalDistance || 8);
navegador.setCornerDistance(options.cornerDistance || 8);
var startingPointOnRoad = navegador.projectionPositionOnRoad(startingPoint);
if (!startingPointOnRoad) {
throw new Error("starting point can not be projected on road");
}
var fullNavigationPath = navegador.getNavigationChain(navigationMode, startingPoint, finishingPoint, routeOptions);
if (!fullNavigationPath) {
throw new Error("can not get navigation path");
}
_this.fullNavigationPath = fullNavigationPath;
var startingPointOnPath = navegador.projectionPositionOnChain(startingPointOnRoad);
if (!startingPointOnPath) {
throw new Error("starting point can not be projected on navigation path");
}
var restOfDistance = _this.lastDistToEnd = navegador.getDistanceToNavigationChainEnd(startingPointOnPath);
var navigationStatus = navegador.getNavigationStatus(startingPointOnRoad);
if (!navigationStatus) {
throw new Error("can not get navigation status");
}
_this.lastLocationTime = Date.now();
_this.animationDistance = 0;
_this.animationChain = fullNavigationPath;
_this.targetPositionOnPath = startingPointOnPath;
_this.currentPositionOnPath = startingPointOnPath;
_this.currentNavigationPath = fullNavigationPath;
_this.restOfDistance = Math.floor(restOfDistance);
_this.restOfTime = Math.ceil(restOfDistance / WALK_SPEED_PER_MINUTE);
_this.navigationHint = _this.getNavigationStatusText({
currentCartogramId: startingPointOnPath.properties["cartogram:id"],
navegador: navegador,
navigationStatus: navigationStatus
}) || "";
_this.nextDirection = navigationStatus.nextDirection;
return _this;
}
_createClass(NavegadorTask, [{
key: "sliceNavigationChain",
value: function sliceNavigationChain(nc, startPt) {
var lines = Array.from(nc.features);
if (!lines.length) {
return nc;
}
var _nc$features$filter = nc.features.filter(function (f) {
return f.properties.segment_index >= startPt.properties.segment_index;
}),
_nc$features$filter2 = _toArray(_nc$features$filter),
firstSegment = _nc$features$filter2[0],
restFeatures = _nc$features$filter2.slice(1);
return _objectSpread(_objectSpread({}, nc), {}, {
features: [lineString([getCoord(startPt), getCoords(firstSegment)[1]], firstSegment.properties)].concat(_toConsumableArray(restFeatures))
});
}
}, {
key: "segmentDistance",
value: function segmentDistance(segment) {
if (segment.properties["starting:cartogram:id"] === segment.properties["finishing:cartogram:id"]) {
var coords = getCoords(segment);
return turfDistance(coords[0], coords[1], {
units: "meters"
});
}
return segment.properties.distance;
}
}, {
key: "alongNavigationPath",
value: function alongNavigationPath(nc, distance, options) {
var lines = Array.from(nc.features);
var line = lines.shift();
if (!line) {
throw new Error("no segment in NavigationChain");
}
var units = propOr("kilometers", "units", options);
var ncDistanceUnit = "meters";
var remainDistance = convertLength(distance, units, ncDistanceUnit); // 如果距离小于等于0,那么返回导航链的起点
if (remainDistance <= 0) {
var _cartogramId = line.properties["starting:cartogram:id"];
var _startCartogram = this.navegador._cartograms[_cartogramId];
return point(line.geometry.coordinates[0], {
accuracy: 0,
"cartogram:id": _cartogramId,
"cartogram:name": _startCartogram.properties.name,
"cartogram:floor_number": _startCartogram.properties.floor_number,
"cartogram:floor_label": _startCartogram.properties.floor_label,
"building:id": _startCartogram.properties["building:id"],
"building:name": _startCartogram.properties["building:name"],
segment_index: line.properties.segment_index,
source: "pseudo",
timestamp: Date.now(),
road_index: line.properties["starting:road_index"]
});
}
var cartogramId = line.properties["starting:cartogram:id"];
var startCartogram = this.navegador._cartograms[cartogramId];
var point$1 = point(line.geometry.coordinates[0], {
accuracy: 0,
"cartogram:id": cartogramId,
"cartogram:name": startCartogram.properties.name,
"cartogram:floor_number": startCartogram.properties.floor_number,
"cartogram:floor_label": startCartogram.properties.floor_label,
"building:id": startCartogram.properties["building:id"],
"building:name": startCartogram.properties["building:name"],
segment_index: line.properties.segment_index,
source: "pseudo",
timestamp: Date.now(),
road_index: line.properties["starting:road_index"]
});
while (remainDistance && line) {
var lineDistance = this.segmentDistance(line);
if (remainDistance <= lineDistance) {
cartogramId = line.properties["starting:cartogram:id"];
startCartogram = this.navegador._cartograms[cartogramId];
point$1 = point(getCoord(turfAlong(line, remainDistance, {
units: ncDistanceUnit
})), {
accuracy: 0,
"cartogram:id": cartogramId,
"cartogram:name": startCartogram.properties.name,
"cartogram:floor_number": startCartogram.properties.floor_number,
"cartogram:floor_label": startCartogram.properties.floor_label,
"building:id": startCartogram.properties["building:id"],
"building:name": startCartogram.properties["building:name"],
segment_index: line.properties.segment_index,
source: "pseudo",
timestamp: Date.now(),
road_index: line.properties["starting:road_index"]
});
break;
}
remainDistance -= lineDistance;
line = lines.shift();
}
return point$1;
}
}, {
key: "sliceNavigationChainAlong",
value: function sliceNavigationChainAlong(nc, startDist, options) {
var lines = Array.from(nc.features);
if (!lines.length) {
return nc;
}
var _startPt = this.alongNavigationPath(nc, startDist, options);
var _nc$features$filter3 = nc.features.filter(function (f) {
return f.properties.segment_index >= _startPt.properties.segment_index;
}),
_nc$features$filter4 = _toArray(_nc$features$filter3),
firstSegment = _nc$features$filter4[0],
restFeatures = _nc$features$filter4.slice(1);
return _objectSpread(_objectSpread({}, nc), {}, {
features: [lineString([getCoord(_startPt), getCoords(firstSegment)[1]], firstSegment.properties)].concat(_toConsumableArray(restFeatures))
});
}
}, {
key: "getInfo",
value: function getInfo() {
var startTime = this.lastLocationTime;
var animaTime = this.animaTime;
var now = Date.now();
var diff = now - startTime;
var ratio = diff >= animaTime ? 1 : diff / animaTime;
var moveDistance = this.animationDistance * ratio;
var nextPositionOnPath = ratio === 1 ? this.targetPositionOnPath : this.alongNavigationPath(this.animationChain, moveDistance, {
units: "meters"
});
var currentNavigationChain = this.sliceNavigationChainAlong(this.animationChain, moveDistance, {
units: "meters"
});
var navigationStatus = this.navegador.getNavigationStatus(nextPositionOnPath);
if (navigationStatus) {
this.currentPositionOnPath = nextPositionOnPath;
this.currentNavigationPath = currentNavigationChain;
this.navigationHint = this.getNavigationStatusText({
currentCartogramId: nextPositionOnPath.properties["cartogram:id"],
navegador: this.navegador,
navigationStatus: navigationStatus
}) || "";
this.nextDirection = navigationStatus.nextDirection;
var restOfDistance = this.restOfDistance = Math.floor(navigationStatus.distanceToEnd);
this.restOfTime = Math.ceil(restOfDistance / WALK_SPEED_PER_MINUTE);
}
return {
navigationMode: this.navigationMode,
finishingPoint: this.finishingPoint,
startingPoint: this.startingPoint,
fullNavigationPath: this.fullNavigationPath,
targetPositionOnPath: this.targetPositionOnPath,
currentPositionOnPath: this.currentPositionOnPath,
currentNavigationPath: this.currentNavigationPath,
restOfDistance: this.restOfDistance,
restOfTime: this.restOfTime,
navigationHint: this.navigationHint,
nextDirection: this.nextDirection
};
}
}, {
key: "setCurrentLocation",
value: function setCurrentLocation(currentLocation) {
var _this2 = this;
var navegador = this.navegador,
lastLocationTime = this.lastLocationTime,
timeDiffCountAdjust = this.timeDiffCountAdjust,
distanceCountAdjust = this.distanceCountAdjust,
cartogramDiffCountAdjust = this.cartogramDiffCountAdjust,
targetPositionOnPath = this.targetPositionOnPath,
locationAccuracyAdjust = this.locationAccuracyAdjust;
var now = Date.now();
var currentLocationOnRoad = navegador.projectionPositionOnRoad(currentLocation);
if (!currentLocationOnRoad) {
return;
}
var currentLocationOnPath = navegador.projectionPositionOnChain(currentLocationOnRoad); // 无法投影到导航路径上时,比如刚开始导航时就朝反方向移动的时候,此时会投影到导航路径延长线而不是导航路径上
if (!currentLocationOnPath) {
this.offRoadCount += 1 * timeDiffCountAdjust * ((now - lastLocationTime) / 1000);
this.needReroute(currentLocation);
return;
}
var isCrossRoad = currentLocationOnRoad.properties.road_index !== currentLocationOnPath.properties.road_index; // 当映射到道路上的道路编号不同于映射到导航路径上的道路编号时,典型情况是处于路口时
// 或者是跨楼层时
if (isCrossRoad) {
var dist = turfDistance(currentLocationOnRoad, currentLocationOnPath) * 1000;
var isSameCartogram = targetPositionOnPath.properties["cartogram:id"] === currentLocationOnPath.properties["cartogram:id"];
var minDistance = currentLocationOnPath.properties.source === "satellite" ? this.offRoadMinDistance.satellite : this.offRoadMinDistance.bluetooth; // 增加偏离计数时考虑以下因素
// 1. 与上一次定位之间的时间差
// 2. 与上一次定位之间的距离
// 3. 本次定位的精度
this.offRoadCount += 1 * ((now - lastLocationTime) / 1000) * timeDiffCountAdjust * (currentLocation.properties.accuracy * locationAccuracyAdjust) * (isSameCartogram ? dist >= minDistance ? (dist - 4) / 4 * distanceCountAdjust : 0 : cartogramDiffCountAdjust);
if (dist > minDistance) {
this.needReroute(currentLocation);
}
return;
} // 检测倒退的情况
var distToEnd = navegador.getDistanceToNavigationChainEnd(currentLocationOnPath);
var distDiff = distToEnd - this.lastDistToEnd;
if (distDiff > 8) {
var _isSameCartogram = this.targetPositionOnPath.properties["cartogram:id"] === currentLocationOnPath.properties["cartogram:id"];
var _minDistance = currentLocationOnPath.properties.source === "satellite" ? this.offRoadMinDistance.satellite : this.offRoadMinDistance.bluetooth; // 增加后退计数时考虑以下因素
// 1. 与上一次定位之间的时间差
// 2. 与上一次定位之间的距离
// 3. 本次定位的精度
this.backwardCount += 1 * ((now - lastLocationTime) / 1000) * timeDiffCountAdjust * (currentLocation.properties.accuracy * locationAccuracyAdjust) * (_isSameCartogram ? distDiff >= _minDistance ? (distDiff - 4) / 4 * distanceCountAdjust : 0 : cartogramDiffCountAdjust);
this.needReroute(currentLocation);
}
if (distDiff > 0) {
return;
}
this.targetPositionOnPath = currentLocationOnPath;
this.lastDistToEnd = distToEnd; // 如果执行到此处,说明一切正常, 说明没有发生倒退也没有定位到其他道路上的情况
// 表示用户在沿着导航路径前进,此时重置 count,缩短导航路径
this.offRoadCount = 0;
this.backwardCount = 0;
this.lastLocationTime = now; // 计算需要移动的距离
var sSegmentIndex = this.currentPositionOnPath.properties.segment_index;
var tSegmentIndex = currentLocationOnPath.properties.segment_index;
this.animationDistance = sSegmentIndex === tSegmentIndex ? turfDistance(this.currentPositionOnPath, currentLocationOnPath, {
units: "meters"
}) : this.fullNavigationPath.features.reduce(function (d, f) {
var fSegmentIndex = f.properties.segment_index;
if (fSegmentIndex === sSegmentIndex) {
var sp = _this2.currentPositionOnPath;
var tp = point(getCoords(f)[1]);
var ld = turfDistance(sp, tp, {
units: "meters"
});
return d + ld;
}
if (fSegmentIndex === tSegmentIndex) {
return d + turfDistance(point(getCoords(f)[0]), _this2.targetPositionOnPath, {
units: "meters"
});
}
if (fSegmentIndex > sSegmentIndex && fSegmentIndex < tSegmentIndex) {
return d + _this2.segmentDistance(f);
}
return d;
}, 0);
this.animationChain = this.sliceNavigationChain(this.fullNavigationPath, this.currentPositionOnPath);
this.emit("info");
}
}, {
key: "needReroute",
value: function needReroute(currentLocation) {
if (this.offRoadCount >= this.offRoadCountLimit || this.backwardCount >= this.backwardCountLimit) {
try {
this.reroute(currentLocation);
} catch (err) {
console.error(err);
}
}
}
}, {
key: "reroute",
value: function reroute(currentLocation) {
var navegador = this.navegador;
var navigationMode = this.navigationMode;
var finishingPoint = this.finishingPoint;
var startingPoint = currentLocation;
var routeOptions = this.routeOptions;
var startingPointOnRoad = navegador.projectionPositionOnRoad(startingPoint);
if (!startingPointOnRoad) {
throw new Error("starting point can not be projected on road");
}
var fullNavigationPath = navegador.getNavigationChain(navigationMode, startingPoint, finishingPoint, routeOptions);
if (!fullNavigationPath) {
throw new Error("can not get navigation path");
}
var startingPointOnPath = navegador.projectionPositionOnChain(startingPointOnRoad);
if (!startingPointOnPath) {
throw new Error("starting point can not be projected on navigation path");
}
var navigationStatus = navegador.getNavigationStatus(startingPointOnRoad);
if (!navigationStatus) {
throw new Error("can not get navigation status");
}
this.fullNavigationPath = fullNavigationPath;
this.lastLocationTime = Date.now();
this.animationDistance = 0;
this.animationChain = fullNavigationPath;
this.targetPositionOnPath = startingPointOnPath;
this.currentPositionOnPath = startingPointOnPath;
this.currentNavigationPath = fullNavigationPath;
this.offRoadCount = 0;
this.backwardCount = 0;
var restOfDistance = this.lastDistToEnd = navegador.getDistanceToNavigationChainEnd(startingPointOnPath);
this.restOfDistance = Math.floor(restOfDistance);
this.restOfTime = Math.ceil(restOfDistance / WALK_SPEED_PER_MINUTE);
this.navigationHint = this.getNavigationStatusText({
currentCartogramId: startingPointOnPath.properties["cartogram:id"],
navegador: this.navegador,
navigationStatus: navigationStatus
}) || "";
this.nextDirection = navigationStatus.nextDirection;
this.emit("info");
this.emit("reroute");
}
}, {
key: "getNavigationStatusText",
value: function getNavigationStatusText(params) {
var navegador = params.navegador,
currentCartogramId = params.currentCartogramId,
_params$navigationSta = params.navigationStatus,
nextCartogramId = _params$navigationSta.nextCartogramId,
nextDirection = _params$navigationSta.nextDirection,
text = _params$navigationSta.text;
var preActionText = "";
switch (nextDirection) {
case Directions.LeftChangeFloor:
case Directions.LeftChangeFloorLeft:
case Directions.LeftChangeFloorRight:
case Directions.LeftChangeFloorStraight:
preActionText = "左转";
break;
case Directions.RightChangeFloor:
case Directions.RightChangeFloorLeft:
case Directions.RightChangeFloorRight:
case Directions.RightChangeFloorStraight:
preActionText = "右转";
break;
case Directions.StraightChangeFloorLeft:
case Directions.StraightChangeFloorRight:
case Directions.StraightChangeFloorStraight:
default:
preActionText = "";
}
var postActionText = "";
switch (nextDirection) {
case Directions.LeftChangeFloorLeft:
case Directions.RightChangeFloorLeft:
case Directions.StraightChangeFloorLeft:
case Directions.LeftChangeFloorRight:
case Directions.RightChangeFloorRight:
case Directions.StraightChangeFloorRight:
case Directions.LeftChangeFloor:
case Directions.LeftChangeFloorStraight:
case Directions.RightChangeFloor:
case Directions.RightChangeFloorStraight:
case Directions.StraightChangeFloorStraight:
default:
postActionText = "";
break;
}
switch (nextDirection) {
case Directions.Left:
return "左转";
case Directions.Right:
return "右转";
case Directions.Straight:
return "直行";
case Directions.LeftArrive:
case Directions.RightArrive:
case Directions.Arrive:
return "目的地就在附近";
case Directions.LeftLeft:
return "连续左转";
case Directions.LeftRight:
return "左转后再右转";
case Directions.RightRight:
return "连续右转";
case Directions.RightLeft:
return "右转后再左转";
case Directions.ChangeFloor:
case Directions.LeftChangeFloor:
case Directions.LeftChangeFloorLeft:
case Directions.LeftChangeFloorRight:
case Directions.LeftChangeFloorStraight:
case Directions.RightChangeFloor:
case Directions.RightChangeFloorLeft:
case Directions.RightChangeFloorRight:
case Directions.RightChangeFloorStraight:
case Directions.StraightChangeFloorLeft:
case Directions.StraightChangeFloorRight:
case Directions.StraightChangeFloorStraight:
{
var currentFloor = navegador._cartograms[currentCartogramId];
var nextFloor = navegador._cartograms[nextCartogramId];
var currentFloorNumber = currentFloor.properties.floor_number;
var _nextFloor$properties = nextFloor.properties,
nextFloorNumber = _nextFloor$properties.floor_number,
floor_label = _nextFloor$properties.floor_label;
if (nextFloorNumber > currentFloorNumber) {
return "\u8BF7".concat(preActionText, "\u4E0A\u697C\u5230 ").concat(floor_label, " ").concat(postActionText).trim();
}
return "\u8BF7".concat(preActionText, "\u4E0B\u697C\u5230 ").concat(floor_label, " ").concat(postActionText).trim();
}
default:
return text;
}
}
}]);
return NavegadorTask;
}(EventEmitter);
/**
* 导航器
*/
var Navegador = /*#__PURE__*/function () {
/**
* 实例化一个导航器
* @param cartogramCollection 甲虫地图集
*/
function Navegador() {
_classCallCheck(this, Navegador);
this._cartograms = {}; // 初始化核心
this._core = JCMapNavigadorCoreNavigation();
this._world = this._core.core_world_new();
}
_createClass(Navegador, [{
key: "addBuilding",
value: function addBuilding(cartogramCollection) {
var _this3 = this;
var core = this._core;
var world = this._world;
core.core_world_add_building(world, this._createBuilding(cartogramCollection));
cartogramCollection.floors.forEach(function (cartogram) {
_this3._cartograms[cartogram.id] = cartogram;
});
return this;
}
}, {
key: "_createBuilding",
value: function _createBuilding(cartogramCollection) {
var jsonStr = JSON.stringify(cartogramCollection);
var bufferSize = this._core.lengthBytesUTF8(jsonStr);
var buffer = this._core._malloc(bufferSize + 1);
this._core.stringToUTF8(jsonStr, buffer, bufferSize + 1);
var buildingRef = this._core.core_building_new();
this._core.core_parseBuildingByData(buffer, bufferSize, buildingRef);
this._core._free(buffer);
return buildingRef;
}
}, {
key: "_createPoint",
value: function _createPoint(position) {
var core = this._core;
var _position$geometry$co = _slicedToArray(position.geometry.coordinates, 2),
lng = _position$geometry$co[0],
lat = _position$geometry$co[1];
var pointRef = this._core.core_point_new_by_wgs84(0, lng, lat);
core.core_point_set_floor_id(pointRef, position.properties["cartogram:id"]);
return pointRef;
}
}, {
key: "_getNavigationSegmentByIndex",
value: function _getNavigationSegmentByIndex(navigationChainRef, navigationSegmentIndex) {
var segmentRef = this._core.core_navichain_get_seg(navigationChainRef, navigationSegmentIndex);
var startingCartogramId = this._core.core_navichain_seg_get_start_floor_id(segmentRef);
var startingLongitude = this._core.core_navichain_seg_get_start_longitude(segmentRef);
var startingLatitude = this._core.core_navichain_seg_get_start_latitude(segmentRef);
var finishingCartogramId = this._core.core_navichain_seg_get_end_floor_id(segmentRef);
var finishingLongitude = this._core.core_navichain_seg_get_end_longitude(segmentRef);
var finishingLatitude = this._core.core_navichain_seg_get_end_latitude(segmentRef);
var distance = this._core.core_navichain_seg_get_distance(segmentRef);
var nextDirection = this._core.core_navichain_seg_next_direction(segmentRef);
var startingCartogram = this._cartograms[startingCartogramId];
var finishingCartogram = this._cartograms[finishingCartogramId];
var startingPointOnRoad = this.projectionPositionOnRoad(point([startingLongitude, startingLatitude], {
"cartogram:id": startingCartogramId,
"cartogram:name": startingCartogram.properties.name,
"cartogram:floor_number": startingCartogram.properties.floor_number,
"cartogram:floor_label": startingCartogram.properties.floor_label,
"building:id": startingCartogram.properties["building:id"],
"building:name": startingCartogram.properties["building:name"]
}));
var finishingPointOnRoad = this.projectionPositionOnRoad(point([finishingLongitude, finishingLatitude], {
"cartogram:id": finishingCartogramId,
"cartogram:name": finishingCartogram.properties.name,
"cartogram:floor_number": finishingCartogram.properties.floor_number,
"cartogram:floor_label": finishingCartogram.properties.floor_label,
"building:id": finishingCartogram.properties["building:id"],
"building:name": finishingCartogram.properties["building:name"]
}));
return lineString([[startingLongitude, startingLatitude], [finishingLongitude, finishingLatitude]], {
segment_index: navigationSegmentIndex,
"starting:cartogram:id": startingCartogramId,
"starting:cartogram:floor_number": startingCartogram.properties.floor_number,
"starting:cartogram:floor_label": startingCartogram.properties.floor_label,
"starting:building:id": startingCartogram.properties["building:id"],
"starting:building:name": startingCartogram.properties["building:name"],
"starting:road_index": startingPointOnRoad ? startingPointOnRoad.properties.road_index : -1,
"finishing:cartogram:id": finishingCartogramId,
"finishing:cartogram:floor_number": finishingCartogram.properties.floor_number,
"finishing:cartogram:floor_label": finishingCartogram.properties.floor_label,
"finishing:building:id": finishingCartogram.properties["building:id"],
"finishing:building:name": finishingCartogram.properties["building:name"],
"finishing:road_index": finishingPointOnRoad ? finishingPointOnRoad.properties.road_index : -1,
distance: distance,
next_direction: nextDirection
});
}
}, {
key: "_createNavigationChain",
value: function _createNavigationChain(worldRef, routePlanRef, mode) {
// 在创建新navigation chain时确保释放上一个navigation chain
if (this._lastNavigationChainRef) {
this._core.core_navichain_free(this._lastNavigationChainRef);
}
this._lastNavigationChainRef = this._core.core_navichain_new(worldRef, routePlanRef, mode);
return this._lastNavigationChainRef;
}
/**
* 计算起点到终点的步行导航链
* @param startingPoint 起点
* @param finishingPoint 终点
*/
}, {
key: "getWalkingNavigationChain",
value: function getWalkingNavigationChain(startingPoint, finishingPoint, options) {
var _this4 = this;
var worldRef = this._world;
var startingPointRef;
var finishingPointRef;
var routePlanRef;
try {
startingPointRef = this._createPoint(startingPoint);
finishingPointRef = this._createPoint(finishingPoint);
routePlanRef = this._core.core_world_route_plan_by_walk_with_condition(worldRef, startingPointRef, finishingPointRef, JSON.stringify(options));
if (!routePlanRef) {
return;
}
var navigationChainRef = this._createNavigationChain(worldRef, routePlanRef, NavigationModes.Walking);
var navigationChainLength = this._core.core_navichain_get_seg_count(navigationChainRef);
var navigationEdges = range(0, navigationChainLength).map(function (segmentIndex) {
return _this4._getNavigationSegmentByIndex(navigationChainRef, segmentIndex);
});
return featureCollection(navigationEdges);
} catch (err) {
console.error(err);
return;
} finally {
// routePlanRef && this._core.seq_free(routePlanRef)
startingPointRef && this._core.core_point_free(startingPointRef);
finishingPointRef && this._core.core_point_free(finishingPointRef);
}
}
}, {
key: "getNavigationChain",
value: function getNavigationChain() {
var navigationMode = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : NavigationModes.Walking;
var startingPoint = arguments.length > 1 ? arguments[1] : undefined;
var finishingPoint = arguments.length > 2 ? arguments[2] : undefined;
var routeOptions = arguments.length > 3 ? arguments[3] : undefined;
var navigationPath;
switch (navigationMode) {
case NavigationModes.Walking:
default:
// 起点和终点已经过线路预览确保可以导航,所以强制转换为 NavigationChain
navigationPath = this.getWalkingNavigationChain(startingPoint, finishingPoint, routeOptions);
}
return navigationPath;
}
/**
* 获取某个位置映射到导航链上后,所在的导航段的索引,在没有导航链或映射失败时返回undefined
* @param position 地图位置
*/
}, {
key: "getSegmentIndexOfPositionOnChain",
value: function getSegmentIndexOfPositionOnChain(position) {
if (!this._lastNavigationChainRef) {
return;
}
var _getCoord = getCoord(position),
_getCoord2 = _slicedToArray(_getCoord, 2),
lng = _getCoord2[0],
lat = _getCoord2[1];
return this._core.core_navigate_get_projection_segindex(this._lastNavigationChainRef, position.properties["cartogram:id"], lng, lat);
}
/**
* 映射某个位置到道路上
* @param position 地图位置
*/
}, {
key: "projectionPositionOnRoad",
value: function projectionPositionOnRoad(position) {
var projectedLngBuf = this._core._malloc(Float64Array.BYTES_PER_ELEMENT * 8);
var projectedLatBuf = this._core._malloc(Float64Array.BYTES_PER_ELEMENT * 8);
try {
var _position$geometry$co2 = _slicedToArray(position.geometry.coordinates, 2),
lng = _position$geometry$co2[0],
lat = _position$geometry$co2[1];
var roadIndex = this._core.core_world_get_near_road_point(this._world, position.properties["cartogram:id"], lng, lat, projectedLngBuf, projectedLatBuf); // 表示投影失败
if (roadIndex < 0) {
return;
}
return point([this._core.getValue(projectedLngBuf, "double"), this._core.getValue(projectedLatBuf, "double")], _objectSpread(_objectSpread({}, position.properties), {}, {
accuracy: 0,
road_index: roadIndex,
timestamp: Date.now(),
source: "pseudo"
}));
} catch (err) {
console.error(err);
return;
} finally {
this._core._free(projectedLngBuf);
this._core._free(projectedLatBuf);
}
}
/**
* 映射某个位置到当前导航链上,在还没有导航链或者映射失败时返回undefined
* @param position 地图位置
*/
}, {
key: "projectionPositionOnChain",
value: function projectionPositionOnChain(position) {
var projectedLocationRef = 0;
try {
if (!this._lastNavigationChainRef) {
return;
}
var _getCoord3 = getCoord(position),
_getCoord4 = _slicedToArray(_getCoord3, 2),
oLng = _getCoord4[0],
oLat = _getCoord4[1];
projectedLocationRef = this._core.core_navigate_get_projection(this._lastNavigationChainRef, position.properties["cartogram:id"], oLng, oLat); // 表示投影失败
if (!projectedLocationRef) {
return;
}
var lng = this._core.core_point_get_lon(projectedLocationRef);
var lat = this._core.core_point_get_lat(projectedLocationRef);
var segmentIndex = this.getSegmentIndexOfPositionOnChain(position);
if (segmentIndex === undefined) {
return;
}
var pointOnRoad = this.projectionPositionOnRoad(position);
if (!pointOnRoad) {
return;
}
var pointOnPath = point([lng, lat], _objectSpread(_objectSpread({}, position.properties), {}, {
segment_index: segmentIndex,
road_index: pointOnRoad.properties.road_index
}));
return pointOnPath;
} catch (err) {
console.error(err);
} finally {
if (projectedLocationRef) {
this._core.core_point_free(projectedLocationRef);
}
}
}
/**
* 获取某个位置在当前导航图中的状态
* @param position 某个位置
*/
}, {
key: "getNavigationStatus",
value: function getNavigationStatus(position) {
if (!this._lastNavigationChainRef) {
return;
}
var _getCoord5 = getCoord(position),
_getCoord6 = _slicedToArray(_getCoord5, 2),
lng = _getCoord6[0],
lat = _getCoord6[1];
var navigationStatusRef = this._core.core_navigate_get_status(this._lastNavigationChainRef, position.properties["cartogram:id"], lng, lat);
if (!navigationStatusRef) {
return;
}
var nextDirection = this._core.core_navigate_status_get_next_direction(navigationStatusRef);
var nextCartogramId = this._core.core_navigate_status_get_next_floor_id(navigationStatusRef);
var distanceToCorner = this._core.core_navigate_status_get_distance_2_corner(navigationStatusRef);
var distanceToEnd = this._core.core_navigate_status_get_distance_2_end(navigationStatusRef);
var cornerNum = this._core.core_navigate_status_get_corners(navigationStatusRef);
this._core.core_navigate_status_free(navigationStatusRef);
return {
nextDirection: nextDirection,
nextCartogramId: nextCartogramId,
distanceToCorner: distanceToCorner,
distanceToEnd: distanceToEnd,
cornerNum: cornerNum
};
}
/**
* 获取某个位置到当前导航图终点的距离
* @param position 某个位置
*/
}, {
key: "getDistanceToNavigationChainEnd",
value: function getDistanceToNavigationChainEnd(position) {
if (!this._lastNavigationChainRef) {
return;
}
var _getCoord7 = getCoord(position),
_getCoord8 = _slicedToArray(_getCoord7, 2),
lng = _getCoord8[0],
lat = _getCoord8[1];
return this._core.core_navigate_get_distance_to_end(this._lastNavigationChainRef, position.properties["cartogram:id"], lng, lat);
}
/**
* 设置当前导航链的到达判定距离
* @param distance 判定距离,默认值:人行模式 8 米,车行模式 22 米。
*/
}, {
key: "setCurrentArrivalDistance",
value: function setCurrentArrivalDistance(distance) {
if (!this._lastNavigationChainRef) {
return;
}
this._core.core_navigate_set_arrive_distance(this._lastNavigationChainRef, distance);
}
/**
* 设置上报转弯状态的判定距离
* @param distance 判定距离,默认值:人行模式 8 米,车行模式 22 米。
*/
}, {
key: "setCornerDistance",
value: function setCornerDistance(distance) {
if (!this._lastNavigationChainRef) {
return;
}
this._core.core_navigate_set_corner_distance(this._lastNavigationChainRef, distance);
}
}]);
return Navegador;
}();
export { Directions, Navegador, NavegadorTask, NavigationDisplayModes, NavigationModes };