UNPKG

@jcmap-sdk-web/navegador

Version:

甲虫室内定位导航引擎

1,000 lines (837 loc) 38 kB
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 };