"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); const reselect_1 = require("reselect"); const Common_1 = require("./Common"); const Utils_1 = require("./Utils"); exports.latLngDegreesToDecimal = Utils_1.latLngDegreesToDecimal; exports.latLngDecimalToDegrees = Utils_1.latLngDecimalToDegrees; let LatLon = require('geodesy').LatLonSpherical; function getCircleRegions(circle) { let latlon = new LatLon(circle.coordinate.latitude, circle.coordinate.longitude); let d1 = latlon.destinationPoint(circle.radius, 0); let d2 = latlon.destinationPoint(circle.radius, 90); let d3 = latlon.destinationPoint(circle.radius, 180); let d4 = latlon.destinationPoint(circle.radius, 270); return [{ lat: d1.lat, lng: d1.lon }, { lat: d2.lat, lng: d2.lon }, { lat: d3.lat, lng: d3.lon }, { lat: d4.lat, lng: d4.lon }]; } function getDefaultStyle() { let imageName = 'BA_oval'; let lineWidth = Common_1.default.amapLineWidth; let strokeColor = Common_1.default.amapStrokeColor; let fillColor = Common_1.default.amapFillColor; return { imageName, lineWidth, strokeColor, fillColor }; } function getCirclesAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) { let circles = []; let markers = []; if (!Array.isArray(airspaceInfos)) { return { circles, markers }; } let { imageName, lineWidth, strokeColor, fillColor } = getDefaultStyle(); //通过该方法获取样式 let circleStyle = setStyle('circle'); if (circleStyle) { lineWidth = circleStyle.lineWidth; strokeColor = circleStyle.strokeColor; fillColor = circleStyle.fillColor; imageName = circleStyle.imageName; } for (let i = 0; i < airspaceInfos.length; i++) { let tmpCircle = airspaceInfos[i]; let airspaceTypeFix, radiusFix, dataType; if (tmpCircle.airspaceType) { airspaceTypeFix = 'airspaceType'; radiusFix = 'radius'; dataType = 1; } else { airspaceTypeFix = 'airspace_type'; radiusFix = 'radius_of_flying'; dataType = 2; } if (tmpCircle[airspaceTypeFix] == Common_1.default.airspaceType.circle && currentAirspaceIndex != i) { let coordinate = {}; if (tmpCircle.center_point_of_flying) { coordinate.latitude = tmpCircle.center_point_of_flying.lat; coordinate.longitude = tmpCircle.center_point_of_flying.lng; } else { coordinate.latitude = Utils_1.latLngDegreesToDecimal(tmpCircle.lat); coordinate.longitude = Utils_1.latLngDegreesToDecimal(tmpCircle.lng); } let radius = tmpCircle[radiusFix]; if (radius) { let circle = { lineWidth, strokeColor, fillColor, radius, coordinate }; circles.push(circle); } else { markers.push(addOvalPointConfig(coordinate.latitude, coordinate.longitude, imageName, dataType)); } } } return { circles, markers }; } function getCircleAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) { return reselect_1.createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getCirclesAndMarkers); } function getLatLng(latlng, dataType) { if (dataType == 1) { // 驼峰模式,新建计划的时候的格式 return Utils_1.latLngDegreesToDecimal(latlng); } else { return latlng; } } function drawLineConfig(lat, lng, dataType) { return { latitude: getLatLng(lat, dataType), longitude: getLatLng(lng, dataType) }; } function addOvalPointConfig(lat, lng, imageName, dataType) { return { coordinate: { latitude: getLatLng(lat, dataType), longitude: getLatLng(lng, dataType) }, imageName: imageName }; } function pointCompare(point1, point2) { const pointId1 = point1.point_id || point1.pointId; const pointId2 = point2.point_id || point2.pointId; if (pointId1 == pointId2) { return true; } let [point1Lat, point1lng] = getFixedLatLng(point1); let [point2lat, point2lng] = getFixedLatLng(point2); if (myRound(point1Lat) == myRound(point2lat) && myRound(point1lng) == myRound(point2lng)) { return true; } else { return false; } } function getCrossPoint(points1, points2) { for (let point1 of points1) { for (let point2 of points2) { if (pointCompare(point1, point2)) return point1; } } } function getAirwayPoints(airway, pointBefore, pointAfter) { let found = 0; let points = []; let pointTypeFix, pointsFix; if ('points' in airway) { pointTypeFix = 'point_type'; pointsFix = 'points'; } else { pointTypeFix = 'pointType'; pointsFix = 'airlines'; } // 如果前后是其他航线,那么找到交叉点作为前后的点 if (pointBefore[pointTypeFix] == Common_1.default.pointTypes.line) { pointBefore = getCrossPoint(airway[pointsFix], pointBefore[pointsFix]); } if (pointAfter[pointTypeFix] == Common_1.default.pointTypes.line) { pointAfter = getCrossPoint(airway[pointsFix], pointAfter[pointsFix]); } for (let point of airway[pointsFix]) { if (pointCompare(pointBefore, point) || pointCompare(pointAfter, point)) { found++; points.push(Object.assign({}, point)); continue; } if (found == 1) { points.push(Object.assign({}, point)); } } if (!(points.length > 0 && found == 2)) { // 如果两个点不全在航线上面,那么画全部航线 points = airway[pointsFix]; } return points; } function getLinesRouter(lineProps, lineAndMarkerStyle) { let coordinates = new Array(); let markers = new Array(); let lines = []; let { imageName, lineWidth, strokeColor } = getDefaultStyle(); if (lineAndMarkerStyle) { imageName = lineAndMarkerStyle.imageName; lineWidth = lineAndMarkerStyle.lineWidth; strokeColor = lineAndMarkerStyle.strokeColor; } let startPoint, passPoints, endPoint, pointTypeFix, dataType, airlineWidth; if (lineProps.start_point) { dataType = 2; // 下划线模式 startPoint = lineProps['start_point']; passPoints = lineProps['passing_points']; endPoint = lineProps['end_point']; pointTypeFix = 'point_type'; airlineWidth = parseInt(lineProps['airline_width'], 10); } else { dataType = 1; // 驼峰模式 startPoint = lineProps['dep']; passPoints = lineProps['passPoints']; endPoint = lineProps['arrive']; pointTypeFix = 'pointType'; airlineWidth = parseInt(lineProps['airlineWidth'], 10); } if (startPoint) { coordinates.push(drawLineConfig(startPoint.lat, startPoint.lng, dataType)); markers.push(addOvalPointConfig(startPoint.lat, startPoint.lng, imageName, dataType)); } if (Array.isArray(passPoints)) { for (let i = 0; i < passPoints.length; i++) { let obj = passPoints[i]; if (!Utils_1.isObject(obj)) { // 所有的 points/airway 都必须是 obj continue; } let pointType = obj[pointTypeFix]; if (pointType == Common_1.default.pointTypes.point || pointType == Common_1.default.pointTypes.nav) { coordinates.push(drawLineConfig(obj.lat, obj.lng, dataType)); markers.push(addOvalPointConfig(obj.lat, obj.lng, imageName, dataType)); } else { // 遇到一个航线,不需要和前前面的点连起来 if (coordinates.length > 1) { lines.push({ lineWidth, strokeColor, coordinates }); } coordinates = []; const pointBefore = i == 0 ? startPoint : passPoints[i - 1]; const pointAfter = i == passPoints.length - 1 ? (endPoint ? endPoint : passPoints[passPoints.length - 1]) : passPoints[i + 1]; lines.push({ lineWidth, strokeColor, coordinates: getAirwayPoints(obj, pointBefore, pointAfter) }); } } } if (endPoint) { coordinates.push(drawLineConfig(endPoint.lat, endPoint.lng, dataType)); markers.push(addOvalPointConfig(endPoint.lat, endPoint.lng, imageName, dataType)); } if (coordinates.length > 1) { lines.push({ lineWidth, strokeColor, coordinates }); } if (airlineWidth > 0) { // 有宽度的空域,需要线周围多画宽度的多边形 let polygons = processAirlineWidth(lines, airlineWidth); return { lines, markers, polygons }; } else { return { lines, markers, polygons: [] }; } } function getFixedLatLng(point) { let lat = point.latitude ? point.latitude : point.lat; let lng = point.longitude ? point.longitude : point.lng; // 复制计划的数据,有的点是度数模式如 38°35′17″ if (Utils_1.isSafeString(lat)) { lat = Utils_1.latLngDegreesToDecimal(lat); lng = Utils_1.latLngDegreesToDecimal(lng); } return [lat, lng]; } function processAirlineWidth(lines, airlineWidth) { let polygons = []; let { strokeColor, fillColor } = getDefaultStyle(); for (let line of lines) { let points = line.coordinates; for (let i = 0; i < points.length - 1; i++) { let [lat1, lng1] = getFixedLatLng(points[i]); let [lat2, lng2] = getFixedLatLng(points[i + 1]); let point1 = new LatLon(lat1, lng1); let point2 = new LatLon(lat2, lng2); let coordinates = getCirclePoints(point1, point2, airlineWidth); polygons.push({ lineWidth: 1, strokeColor, fillColor, coordinates }); } } return polygons; } function getCirclePoints(point1, point2, width) { let percision = 10; // 半圆处理为多边形的时候,半圆上取几个点 let step = 180 / percision; let bearing = (360 + point1.bearingTo(point2) - 90) % 360; // 取正值 let points = []; for (let diff = 0; diff <= 180; diff += step) { let point = point2.destinationPoint(width, bearing + diff); points.push({ lat: point.lat, lng: point.lon }); } for (let diff = 180; diff <= 360; diff += step) { let point = point1.destinationPoint(width, bearing + diff); points.push({ lat: point.lat, lng: point.lon }); } return points; } function myRound(num, digits) { if (digits == null) digits = 6; // 比较的精度,经纬度会被经过度分秒方式到浮点方式的转化 return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits); } function getLinesPolygonsAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) { let retLines = []; let retMarkers = []; let retPolygons = []; if (!Array.isArray(airspaceInfos)) { return { lines: retLines, markers: retMarkers, polygons: retPolygons }; } let lineStyle = setStyle('line'); for (let i = 0; i < airspaceInfos.length; i++) { let tmpLine = airspaceInfos[i]; let airspaceTypeFix; if (tmpLine.airspaceType) airspaceTypeFix = 'airspaceType'; else airspaceTypeFix = 'airspace_type'; if (tmpLine[airspaceTypeFix] == Common_1.default.airspaceType.line && currentAirspaceIndex != i) { let { lines, markers, polygons } = getLinesRouter(tmpLine, lineStyle); retMarkers.push(...markers); retLines.push(...lines); retPolygons.push(...polygons); } } return { lines: retLines, markers: retMarkers, polygons: retPolygons }; } function getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) { return reselect_1.createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getLinesPolygonsAndMarkers); } function getPolygon(polygonProps, polygonAndMarkerStyle) { let coordinates = new Array(); let markers = new Array(); let { imageName, lineWidth, strokeColor, fillColor } = getDefaultStyle(); if (polygonAndMarkerStyle) { imageName = polygonAndMarkerStyle.imageName; lineWidth = polygonAndMarkerStyle.lineWidth; strokeColor = polygonAndMarkerStyle.strokeColor; fillColor = polygonAndMarkerStyle.fillColor; } let pointsFix, dataType; if (polygonProps.points) { pointsFix = 'points'; dataType = 2; } else { pointsFix = 'polygonPoints'; dataType = 1; // 驼峰模式 } if (Array.isArray(polygonProps[pointsFix])) { for (let obj of polygonProps[pointsFix]) { if (!obj) { continue; } coordinates.push(drawLineConfig(obj.lat, obj.lng, dataType)); markers.push(addOvalPointConfig(obj.lat, obj.lng, imageName, dataType)); } } let polygon = { lineWidth, strokeColor, fillColor, coordinates }; return { markers, polygon }; } function getPolygonsAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) { let markers = []; let polygons = []; if (!Array.isArray(airspaceInfos)) { return { markers, polygons }; } let polygonAndMarkerStyle = setStyle('polygon'); for (let i = 0; i < airspaceInfos.length; i++) { let polygon = airspaceInfos[i]; let airspaceTypeFix; if (polygon.airspaceType) airspaceTypeFix = 'airspaceType'; else airspaceTypeFix = 'airspace_type'; if (polygon[airspaceTypeFix] == Common_1.default.airspaceType.polygon && currentAirspaceIndex != i) { let retObj = getPolygon(polygon, polygonAndMarkerStyle); markers.push(...retObj.markers); polygons.push(retObj.polygon); } } return { markers, polygons }; } function getPolygonAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) { return reselect_1.createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getPolygonsAndMarkers); } function getMarkers(circlesAndMarkers, polygonAndMarkers, lineAndMarkers) { let markers = []; if (circlesAndMarkers) { markers = [...circlesAndMarkers.markers]; } if (polygonAndMarkers) { markers = [...markers, ...polygonAndMarkers.markers]; } if (lineAndMarkers) { markers = [...markers, ...lineAndMarkers.markers]; } return markers; } function getMarkerSelector(circlesAndMarkers, polygonAndMarkers, lineAndMarkers) { return reselect_1.createSelector(circlesAndMarkers, polygonAndMarkers, lineAndMarkers, getMarkers); } function getRegionPoints(circles, lineAndMarkers, polygonAndMarkers) { let regionPoints = new Array(); for (let i = 0; i < circles.length; i++) { regionPoints.push(...getCircleRegions(circles[i])); } let lines = lineAndMarkers.lines; for (let i = 0; i < lines.length; i++) { regionPoints.push(...lines[i].coordinates); } let polygons = polygonAndMarkers.polygons; for (let i = 0; i < polygons.length; i++) { regionPoints.push(...polygons[i].coordinates); } return regionPoints; } function getRegionPointsSelector(circles, lineAndMarkers, polygonAndMarkers) { return reselect_1.createSelector(circles, lineAndMarkers, polygonAndMarkers, getRegionPoints); } function getCircles(circleAndMarker) { return circleAndMarker.circles; } function getCircleSelector(circleAndMarker) { return reselect_1.createSelector(circleAndMarker, getCircles); } function getLines(lineAndMarker) { return lineAndMarker.lines; } function getLineSelector(lineAndMarker) { return reselect_1.createSelector(lineAndMarker, getLines); } function getPolygons(polygonAndMarkers, linePolygonsAndMarkers) { return [...polygonAndMarkers.polygons, ...linePolygonsAndMarkers.polygons]; } function getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers) { return reselect_1.createSelector(polygonAndMarkers, linePolygonsAndMarkers, getPolygons); } let setStyle = (style) => { if (!style) return () => { return null; }; else return (shapeName) => style[shapeName]; }; //获取selector function getShapesSelector(airspaceInfos, style, currentAirspaceIndex) { currentAirspaceIndex = currentAirspaceIndex ? currentAirspaceIndex : () => -1; let circlesAndMarkers = getCircleAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex); let circles = getCircleSelector(circlesAndMarkers); let linePolygonsAndMarkers = getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex); let lines = getLineSelector(linePolygonsAndMarkers); let polygonAndMarkers = getPolygonAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex); let polygons = getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers); let markers = getMarkerSelector(circlesAndMarkers, polygonAndMarkers, linePolygonsAndMarkers); let regionPoints = getRegionPointsSelector(circles, linePolygonsAndMarkers, polygonAndMarkers); return { markers, circles, lines, polygons, regionPoints }; } exports.getShapesSelector = getShapesSelector; //获取数组 function getShapes(airspaceInfos, style, currentAirspaceIndex) { let { markers, polygons, circles, lines, regionPoints } = getShapesSelector((airspaceInfos) => airspaceInfos, style, (currentAirspaceIndex) => currentAirspaceIndex); return { markers: markers(airspaceInfos), circles: circles(airspaceInfos), lines: lines(airspaceInfos), polygons: polygons(airspaceInfos), regionPoints: regionPoints(airspaceInfos) }; } exports.getShapes = getShapes; // 总共 5 种格式, http://git.corp.brilliantaero.com/BA/Coco/issues/99#note_6358 // 1. 全输出格式 // 2. 简化格式 // 3. 传真格式 // 4. 用户端用的简化格式 // 5. 极简格式 function getHeight(num, unit, type) { let shortNum; if (num >= 100) { shortNum = parseInt(num / 100).toString(); if (shortNum.length < 2) { shortNum = '0' + shortNum; } } let heightStandard = Common_1.default.heightStandardsById.get(unit); if (!heightStandard) { heightStandard = unit; } // 这里统一使用数字判断 let standardUnit = Common_1.default.heightStandards.get(heightStandard); let heightDesc; switch (standardUnit) { case 1: heightDesc = ['H*真', '真高*米']; break; case 2: heightDesc = ['H*标(含以下)', '标高*米(含以下)']; break; case 3: heightDesc = ['H*真(含以下)', '真高*米(含以下)']; break; default: heightDesc = ['H*标', '标高*米']; } if (shortNum && (type == 1 || type == 2)) { // H02真,H02真(含以下) return heightDesc[0].replace('*', shortNum); } else { // 真高200米,真高200米(含以下) return heightDesc[1].replace('*', num); } } function getAirspaceName(airspaceInfo) { if (airspaceInfo.airspace_name) { return airspaceInfo.airspace_name; } else { return airspaceInfo.name; } } function circleContent(airspaceInfo, type = 3) { if (type == 5) return getAirspaceName(airspaceInfo); if ('airspace_name' in airspaceInfo) { const lat = Utils_1.latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lat); const lng = Utils_1.latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lng); let content = []; let loc = `以${airspaceInfo.center_loc}`; if (type == 1 || type == 3) loc += `(E${lng}, N${lat})`; content.push(`${loc}为中心`); content.push(`半径${airspaceInfo.radius_of_flying}米`); content.push(getHeight(airspaceInfo.altitude, airspaceInfo.unit, type)); if (airspaceInfo.note) content.push(`备注:${airspaceInfo.note}`); let result = content = content.join(','); return result; } else { let content = []; let loc = `以${airspaceInfo.addr}`; if (type == 1 || type == 3) loc += `(E${airspaceInfo.lng}, N${airspaceInfo.lat})`; content.push(`${loc}为中心`); content.push(`半径${airspaceInfo.radius}米`); content.push(getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type)); if (airspaceInfo.note) content.push(`备注:${airspaceInfo.note}`); content = content.join(','); return content; } } exports.circleContent = circleContent; function flyingCenter(item = {}) { if (item == {}) { return; } else { return ("(E" + Utils_1.latLngDecimalToDegrees(item.lng) + ', ' + "N" + Utils_1.latLngDecimalToDegrees(item.lat) + ")"); } } function lineContent(airspaceInfo, type = 3) { if (type == 5) return getAirspaceName(airspaceInfo); if ('airspace_name' in airspaceInfo) { let content = []; content.push(`${airspaceInfo.start_loc}`); if (type == 1 || type == 3) content.push(`${flyingCenter(airspaceInfo.start_point)}`); content.push(` - `); content.push(getHeight(airspaceInfo.start_point.altitude, airspaceInfo.start_point.unit, type)); const passing_points = airspaceInfo.passing_points; if (Array.isArray(passing_points)) { for (let i = 0; i < passing_points.length; i++) { const obj = passing_points[i]; const lat = Utils_1.latLngDecimalToDegrees(obj.lat); const lng = Utils_1.latLngDecimalToDegrees(obj.lng); if (obj.point_type == Common_1.default.pointTypes.point) { content.push(` - ${obj.point_name}`); if (type == 1 || type == 3) content.push(`(E${lng}, N${lat})`); } else if (obj.point_type == Common_1.default.pointTypes.nav) { content.push(` - ${obj.point_code}`); if (type == 1 || type == 3) content.push(`(E${lng}, N${lat})`); } else { content.push(` - ${obj.air_route_code}`); } if (obj.altitude) { content.push(` - ${getHeight(obj.altitude, obj.unit, type)}`); } } } content.push(` - ${airspaceInfo.end_loc}`); if (type == 1 || type == 3) content.push(`${flyingCenter(airspaceInfo.end_point)}`); if (Utils_1.isSafeString(airspaceInfo.airline_width)) { content.push(`,宽度:${airspaceInfo.airline_width}米`); } if (Utils_1.isSafeString(airspaceInfo.note)) { content.push(`,备注: ${airspaceInfo.note}`); } let result = content.join(""); return result; } else { let content = []; content.push(`${airspaceInfo.dep.addr}`); if (type == 1 || type == 3) content.push(`(E${airspaceInfo.dep.lng}, N${airspaceInfo.dep.lat})`); content.push(` - ${getHeight(airspaceInfo.dep.height, airspaceInfo.dep.heightStandard, type)}`); if (Array.isArray(airspaceInfo.passPoints)) { let length = airspaceInfo.passPoints.length; for (let i = 0; i < length; i++) { let obj = airspaceInfo.passPoints[i]; if (obj.pointType == Common_1.default.pointTypes.point) { content.push(` - ${obj.addr}`); if (type == 1 || type == 3) content.push(`(E${obj.lng}, N${obj.lat})`); } else if (obj.pointType == Common_1.default.pointTypes.nav) { content.push(` - ${obj.pointCode}`); if (type == 1 || type == 3) content.push(`(E${obj.lng}, N${obj.lat})`); } else { content.push(` - ${obj.airlineCode}`); } if (obj.height) { content.push(` - ${getHeight(obj.height, obj.heightStandard, type)}`); } } } content.push(` - ${airspaceInfo.arrive.addr}`); if (type == 1 || type == 3) content.push(`(E${airspaceInfo.arrive.lng}, N${airspaceInfo.arrive.lat})`); if (airspaceInfo.airlineWidth) { content.push(`,宽度:${airspaceInfo.airlineWidth}米`); } if (airspaceInfo.note) content.push(`,备注:${airspaceInfo.note}`); content = content.join(''); return content; } } exports.lineContent = lineContent; function polygonContent(airspaceInfo, type = 3) { if (type == 5) return getAirspaceName(airspaceInfo); if ('airspace_name' in airspaceInfo) { let res = []; let points = airspaceInfo.points; for (let i = 0; i < points.length; i++) { let c = `${points[i].addr ? points[i].addr : ''}`; if (type == 1 || type == 3) c += `(E${Utils_1.latLngDecimalToDegrees(points[i].lng)}, N${Utils_1.latLngDecimalToDegrees(points[i].lat)})`; res.push(c); } let content = [res.join('、')]; content.push(`${airspaceInfo.points.length}点连线范围内`); content.push(`,${getHeight(airspaceInfo.altitude, airspaceInfo.unit, type)}`); if (Utils_1.isSafeString(airspaceInfo.note)) { content.push(`,备注:${airspaceInfo.note}`); } return content.join(''); } else { let content = []; let length = airspaceInfo.polygonPoints.length; for (let i = 0; i < length; i++) { let obj = airspaceInfo.polygonPoints[i]; let c = `${obj.addr ? obj.addr : ''}`; if (type == 1 || type == 3) c += `(E${obj.lng}, N${obj.lat})`; content.push(c); } content = content.join('、') + `${length}点连线范围内`; content += `,${getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type)}`; if (airspaceInfo.note) content = `${content},备注:${airspaceInfo.note}`; return content; } } exports.polygonContent = polygonContent;