index.js 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889
  1. import { createSelector } from 'reselect';
  2. import Global from './Common';
  3. import { latLngDegreesToDecimal, latLngDecimalToDegrees, isObject, isSafeString, hasPoint, isNumber } from './Utils';
  4. let LatLon = require('geodesy').LatLonSpherical;
  5. export function convertAirspaceInfoServerToLocal(airspaceInfo) {
  6. const airspaceType = airspaceInfo.airspace_type;
  7. if (airspaceType == Global.airspaceType.circle) {
  8. const ai = airspaceInfo;
  9. return {
  10. airspaceType,
  11. airspaceId: ai.airspace_id,
  12. name: ai.airspace_name,
  13. note: ai.note,
  14. addr: ai.center_loc,
  15. lat: ai.center_point_of_flying.lat,
  16. lng: ai.center_point_of_flying.lng,
  17. radius: ai.radius_of_flying,
  18. height: ai.altitude + "",
  19. heightStandard: Global.heightStandardsById.get(ai.unit)
  20. };
  21. }
  22. if (airspaceType == Global.airspaceType.line) {
  23. const ai = airspaceInfo;
  24. let dep = {
  25. addr: ai.start_loc,
  26. lat: ai.start_point.lat,
  27. lng: ai.start_point.lng,
  28. height: ai.start_point.altitude + "",
  29. heightStandard: Global.heightStandardsById.get(ai.start_point.unit)
  30. };
  31. let arrive = {
  32. addr: ai.end_loc,
  33. lat: ai.end_point.lat,
  34. lng: ai.end_point.lng
  35. };
  36. let passPoints = [];
  37. if (Array.isArray(ai.passing_points)) {
  38. for (let obj of ai.passing_points) {
  39. let point;
  40. if (obj.point_type == Global.pointTypes.point) {
  41. const pp = obj;
  42. const lat = pp.lat;
  43. const lng = pp.lng;
  44. point = {
  45. pointType: pp.point_type,
  46. addr: pp.point_name,
  47. lat, lng
  48. };
  49. }
  50. else if (obj.point_type == Global.pointTypes.nav) {
  51. const pp = obj;
  52. const lat = pp.lat;
  53. const lng = pp.lng;
  54. point = {
  55. pointType: pp.point_type,
  56. pointId: pp.point_id,
  57. pointCode: pp.point_code,
  58. pointName: pp.point_name,
  59. lat, lng
  60. };
  61. }
  62. else {
  63. const pp = obj;
  64. point = {
  65. pointType: pp.point_type,
  66. airRouteId: pp.airway,
  67. airlineCode: pp.air_route_code,
  68. airlines: pp.points
  69. };
  70. }
  71. if (isNumber(obj.altitude) && isNumber(obj.unit)) {
  72. point.height = obj.altitude + "";
  73. point.heightStandard = Global.heightStandardsById.get(obj.unit);
  74. }
  75. else {
  76. point.height = "";
  77. point.heightStandard = [...Global.heightStandards.keys()][0];
  78. }
  79. passPoints.push(point);
  80. }
  81. }
  82. return Object.assign({
  83. airspaceType,
  84. airspaceId: ai.airspace_id,
  85. name: ai.airspace_name,
  86. note: ai.note,
  87. dep,
  88. arrive,
  89. passPoints
  90. }, (ai.airline_width ? { airlineWidth: ai.airline_width } : {}));
  91. }
  92. if (airspaceType == Global.airspaceType.polygon) {
  93. const ai = airspaceInfo;
  94. if (Array.isArray(ai.points)) {
  95. let polygonPoints = new Array();
  96. let defaultPointName = 'A';
  97. for (let obj of ai.points) {
  98. let addr = obj.addr;
  99. if (!addr) {
  100. addr = defaultPointName;
  101. defaultPointName = String.fromCharCode(defaultPointName.charCodeAt(0) + 1);
  102. }
  103. polygonPoints.push({ addr, lat: obj.lat, lng: obj.lng });
  104. }
  105. return {
  106. airspaceType,
  107. airspaceId: ai.airspace_id,
  108. name: ai.airspace_name,
  109. note: ai.note,
  110. height: ai.altitude + '',
  111. heightStandard: Global.heightStandardsById.get(ai.unit),
  112. polygonPoints
  113. };
  114. }
  115. }
  116. return null;
  117. }
  118. export function convertAirspaceInfoLocalToServer(airspace) {
  119. if (airspace.airspaceType == Global.airspaceType.circle) {
  120. const ai = airspace;
  121. const circle = {
  122. airspace_name: ai.name,
  123. airspace_id: ai.airspaceId,
  124. airspace_type: Global.airspaceType.circle,
  125. note: isSafeString(ai.note) ? ai.note : null,
  126. radius_of_flying: parseInt(ai.radius + ''),
  127. center_point_of_flying: {
  128. lng: ai.lng,
  129. lat: ai.lat
  130. },
  131. center_loc: ai.addr,
  132. altitude: parseInt(ai.height),
  133. unit: Global.heightStandards.get(ai.heightStandard)
  134. };
  135. return circle;
  136. }
  137. else if (airspace.airspaceType == Global.airspaceType.line) {
  138. const ai = airspace;
  139. let line = {
  140. airspace_name: ai.name,
  141. airspace_id: ai.airspaceId,
  142. airspace_type: Global.airspaceType.line,
  143. note: ai.note,
  144. start_loc: ai.dep.addr,
  145. start_point: {
  146. lng: ai.dep.lng,
  147. lat: ai.dep.lat,
  148. altitude: parseInt(ai.dep.height),
  149. unit: Global.heightStandards.get(ai.dep.heightStandard)
  150. },
  151. end_loc: ai.arrive.addr,
  152. end_point: {
  153. lng: ai.arrive.lng,
  154. lat: ai.arrive.lat
  155. }
  156. };
  157. if (ai.airlineWidth) {
  158. line['airline_width'] = ai.airlineWidth;
  159. }
  160. if (Array.isArray(ai.passPoints) && ai.passPoints.length > 0) {
  161. let passing_points = [];
  162. for (let obj of ai.passPoints) {
  163. let retObj;
  164. if (obj.pointType == Global.pointTypes.point && hasPoint(obj)) {
  165. const pp = obj;
  166. retObj = {
  167. point_type: Global.pointTypes.point,
  168. point_name: pp.addr,
  169. lat: pp.lat,
  170. lng: pp.lng
  171. };
  172. }
  173. else if (obj.pointType == Global.pointTypes.nav) {
  174. const pp = obj;
  175. retObj = {
  176. point_type: Global.pointTypes.nav,
  177. point_name: pp.pointName,
  178. point_id: pp.pointId,
  179. point_code: pp.pointCode,
  180. lat: pp.lat,
  181. lng: pp.lng
  182. };
  183. }
  184. else {
  185. const pp = obj;
  186. retObj = {
  187. point_type: Global.pointTypes.line,
  188. airway: pp.airRouteId,
  189. air_route_code: pp.airlineCode,
  190. points: pp.airlines
  191. };
  192. }
  193. if (isSafeString(obj.height) && isSafeString(obj.heightStandard)) {
  194. retObj.altitude = parseInt(obj.height);
  195. // @ts-ignore
  196. retObj.unit = Global.heightStandards.get(obj.heightStandard);
  197. }
  198. passing_points.push(retObj);
  199. }
  200. line.passing_points = passing_points;
  201. }
  202. else {
  203. line.passing_points = [];
  204. }
  205. return line;
  206. }
  207. else {
  208. const ai = airspace;
  209. const polygon = {
  210. airspace_name: ai.name,
  211. airspace_id: ai.airspaceId,
  212. airspace_type: Global.airspaceType.polygon,
  213. note: ai.note,
  214. altitude: parseInt(ai.height),
  215. unit: Global.heightStandards.get(ai.heightStandard),
  216. points: ai.polygonPoints
  217. };
  218. return polygon;
  219. }
  220. }
  221. function getCircleRegions(circle) {
  222. let lat, lng;
  223. if (circle.coordinate.latitude) {
  224. let coord = circle.coordinate;
  225. lat = coord.latitude;
  226. lng = coord.longitude;
  227. }
  228. else {
  229. let coord = circle.coordinate;
  230. lat = coord.lat;
  231. lng = coord.lng;
  232. }
  233. let latlon = new LatLon(lat, lng);
  234. let d1 = latlon.destinationPoint(circle.radius, 0);
  235. let d2 = latlon.destinationPoint(circle.radius, 90);
  236. let d3 = latlon.destinationPoint(circle.radius, 180);
  237. let d4 = latlon.destinationPoint(circle.radius, 270);
  238. 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 }];
  239. }
  240. function getDefaultStyle() {
  241. let imageName = 'BA_oval';
  242. let lineWidth = Global.amapLineWidth;
  243. let strokeColor = Global.amapStrokeColor;
  244. let fillColor = Global.amapFillColor;
  245. return { imageName, lineWidth, strokeColor, fillColor };
  246. }
  247. function getCirclesAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
  248. let circles = [];
  249. let markers = [];
  250. if (!Array.isArray(airspaceInfos)) {
  251. return { circles, markers };
  252. }
  253. let { imageName, lineWidth, strokeColor, fillColor } = getDefaultStyle();
  254. //通过该方法获取样式
  255. let circleStyle = setStyle('circle');
  256. if (circleStyle) {
  257. lineWidth = circleStyle.lineWidth;
  258. strokeColor = circleStyle.strokeColor;
  259. fillColor = circleStyle.fillColor;
  260. imageName = circleStyle.imageName;
  261. }
  262. for (let i = 0; i < airspaceInfos.length; i++) {
  263. let tmpCircle = airspaceInfos[i];
  264. let airspaceTypeFix, radiusFix;
  265. if (tmpCircle.airspaceType) {
  266. airspaceTypeFix = 'airspaceType';
  267. radiusFix = 'radius';
  268. }
  269. else {
  270. airspaceTypeFix = 'airspace_type';
  271. radiusFix = 'radius_of_flying';
  272. }
  273. if (tmpCircle[airspaceTypeFix] == Global.airspaceType.circle && currentAirspaceIndex != i) {
  274. let coordinate = { latitude: 0, longitude: 0 };
  275. if (tmpCircle.center_point_of_flying) {
  276. let ai = tmpCircle;
  277. coordinate.latitude = ai.center_point_of_flying.lat;
  278. coordinate.longitude = ai.center_point_of_flying.lng;
  279. }
  280. else {
  281. let ai = tmpCircle;
  282. coordinate.latitude = ai.lat;
  283. coordinate.longitude = ai.lng;
  284. }
  285. let radius = tmpCircle[radiusFix];
  286. if (radius) {
  287. let circle = { lineWidth, strokeColor, fillColor, radius, coordinate };
  288. circles.push(circle);
  289. }
  290. else {
  291. markers.push(addOvalPointConfig(coordinate.latitude, coordinate.longitude, imageName));
  292. }
  293. }
  294. }
  295. return { circles, markers };
  296. }
  297. function getCircleAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) {
  298. return createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getCirclesAndMarkers);
  299. }
  300. function drawLineConfig(lat, lng) {
  301. return {
  302. latitude: lat,
  303. longitude: lng
  304. };
  305. }
  306. function addOvalPointConfig(lat, lng, imageName) {
  307. return {
  308. coordinate: {
  309. latitude: lat,
  310. longitude: lng
  311. },
  312. imageName: imageName
  313. };
  314. }
  315. function pointCompare(point1, point2) {
  316. if (!point1 || !point2) {
  317. return false;
  318. }
  319. const pointId1 = point1.point_id;
  320. const pointId2 = point2.point_id;
  321. if (pointId1 == pointId2) {
  322. return true;
  323. }
  324. let [point1Lat, point1lng] = getFixedLatLng(point1);
  325. let [point2lat, point2lng] = getFixedLatLng(point2);
  326. if (myRound(point1Lat) == myRound(point2lat)
  327. && myRound(point1lng) == myRound(point2lng)) {
  328. return true;
  329. }
  330. else {
  331. return false;
  332. }
  333. }
  334. function getCrossPoint(points1, points2) {
  335. for (let point1 of points1) {
  336. for (let point2 of points2) {
  337. if (pointCompare(point1, point2))
  338. return point1;
  339. }
  340. }
  341. return undefined;
  342. }
  343. function getAirwayPoints(airway, pointBefore, pointAfter) {
  344. let found = 0;
  345. let points = [];
  346. let pointTypeFix, pointsFix, airRoutePoint;
  347. if ('points' in airway) {
  348. pointTypeFix = 'point_type';
  349. pointsFix = 'points';
  350. airRoutePoint = airway['points'];
  351. }
  352. else {
  353. pointTypeFix = 'pointType';
  354. pointsFix = 'airlines';
  355. airRoutePoint = airway['airlines'];
  356. }
  357. let crossPointBefore, crossPointAfter;
  358. // 如果前后是其他航线,那么找到交叉点作为前后的点
  359. if (pointBefore[pointTypeFix] == Global.pointTypes.line) {
  360. crossPointBefore = getCrossPoint(airRoutePoint, pointBefore[pointsFix]);
  361. }
  362. if (pointAfter[pointTypeFix] == Global.pointTypes.line) {
  363. crossPointAfter = getCrossPoint(airRoutePoint, pointAfter[pointsFix]);
  364. }
  365. for (let point of airRoutePoint) {
  366. if (pointCompare(crossPointBefore, point) || pointCompare(crossPointAfter, point)) {
  367. found++;
  368. points.push(Object.assign({}, point));
  369. continue;
  370. }
  371. if (found == 1) {
  372. points.push(Object.assign({}, point));
  373. }
  374. }
  375. if (!(points.length > 0 && found == 2)) {
  376. // 如果两个点不全在航线上面,那么画全部航线
  377. points = airRoutePoint;
  378. }
  379. return points;
  380. }
  381. function getLinesRouter(lineProps, lineAndMarkerStyle) {
  382. let coordinates = new Array();
  383. let markers = new Array();
  384. let lines = [];
  385. let { imageName, lineWidth, strokeColor } = getDefaultStyle();
  386. if (lineAndMarkerStyle) {
  387. imageName = lineAndMarkerStyle.imageName;
  388. lineWidth = lineAndMarkerStyle.lineWidth;
  389. strokeColor = lineAndMarkerStyle.strokeColor;
  390. }
  391. let startPoint, passPoints, endPoint, pointTypeFix, airlineWidth;
  392. if (lineProps.start_point) {
  393. let ll = lineProps;
  394. startPoint = ll['start_point'];
  395. passPoints = ll['passing_points'];
  396. endPoint = ll['end_point'];
  397. pointTypeFix = 'point_type';
  398. airlineWidth = parseInt(ll['airline_width'] + '', 10);
  399. }
  400. else {
  401. let ll = lineProps;
  402. startPoint = ll['dep'];
  403. passPoints = ll['passPoints'];
  404. endPoint = ll['arrive'];
  405. pointTypeFix = 'pointType';
  406. airlineWidth = parseInt(ll['airlineWidth'] + '', 10);
  407. }
  408. if (startPoint) {
  409. coordinates.push(drawLineConfig(startPoint.lat, startPoint.lng));
  410. markers.push(addOvalPointConfig(startPoint.lat, startPoint.lng, imageName));
  411. }
  412. if (Array.isArray(passPoints)) {
  413. for (let i = 0; i < passPoints.length; i++) {
  414. let obj = passPoints[i];
  415. if (!isObject(obj)) { // 所有的 points/airway 都必须是 obj
  416. continue;
  417. }
  418. let pointType = obj[pointTypeFix];
  419. if (pointType == Global.pointTypes.point
  420. || pointType == Global.pointTypes.nav) {
  421. let pp = obj;
  422. coordinates.push(drawLineConfig(pp.lat, pp.lng));
  423. markers.push(addOvalPointConfig(pp.lat, pp.lng, imageName));
  424. }
  425. else {
  426. // 遇到一个航线,不需要和前前面的点连起来
  427. let pp = obj;
  428. if (coordinates.length > 1) {
  429. lines.push({ lineWidth, strokeColor, coordinates });
  430. }
  431. coordinates = [];
  432. const pointBefore = i == 0 ? startPoint : passPoints[i - 1];
  433. const pointAfter = i == passPoints.length - 1 ? (endPoint ? endPoint : passPoints[passPoints.length - 1]) : passPoints[i + 1];
  434. lines.push({ lineWidth, strokeColor, coordinates: getAirwayPoints(pp, pointBefore, pointAfter) });
  435. }
  436. }
  437. }
  438. if (endPoint) {
  439. coordinates.push(drawLineConfig(endPoint.lat, endPoint.lng));
  440. markers.push(addOvalPointConfig(endPoint.lat, endPoint.lng, imageName));
  441. }
  442. if (coordinates.length > 1) {
  443. lines.push({ lineWidth, strokeColor, coordinates });
  444. }
  445. if (airlineWidth > 0) {
  446. // 有宽度的空域,需要线周围多画宽度的多边形
  447. let polygons = processAirlineWidth(lines, airlineWidth);
  448. return { lines, markers, polygons };
  449. }
  450. else {
  451. return { lines, markers, polygons: [] };
  452. }
  453. }
  454. function getFixedLatLng(point) {
  455. let pp = point;
  456. let lat = pp.latitude ? pp.latitude : pp.lat;
  457. let lng = pp.longitude ? pp.longitude : pp.lng;
  458. return [lat, lng];
  459. }
  460. function processAirlineWidth(lines, airlineWidth) {
  461. let polygons = [];
  462. let { strokeColor, fillColor } = getDefaultStyle();
  463. for (let line of lines) {
  464. let points = line.coordinates;
  465. for (let i = 0; i < points.length - 1; i++) {
  466. let [lat1, lng1] = getFixedLatLng(points[i]);
  467. let [lat2, lng2] = getFixedLatLng(points[i + 1]);
  468. let point1 = new LatLon(lat1, lng1);
  469. let point2 = new LatLon(lat2, lng2);
  470. let coordinates = getCirclePoints(point1, point2, airlineWidth);
  471. polygons.push({ lineWidth: 1, strokeColor, fillColor, coordinates });
  472. }
  473. }
  474. return polygons;
  475. }
  476. function getCirclePoints(point1, point2, width) {
  477. let percision = 10; // 半圆处理为多边形的时候,半圆上取几个点
  478. let step = 180 / percision;
  479. let bearing = (360 + point1.bearingTo(point2) - 90) % 360; // 取正值
  480. let points = [];
  481. for (let diff = 0; diff <= 180; diff += step) {
  482. let point = point2.destinationPoint(width, bearing + diff);
  483. points.push({ lat: point.lat, lng: point.lon });
  484. }
  485. for (let diff = 180; diff <= 360; diff += step) {
  486. let point = point1.destinationPoint(width, bearing + diff);
  487. points.push({ lat: point.lat, lng: point.lon });
  488. }
  489. return points;
  490. }
  491. function myRound(num, digits) {
  492. if (digits == null)
  493. digits = 6; // 比较的精度,经纬度会被经过度分秒方式到浮点方式的转化
  494. return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits);
  495. }
  496. function getLinesPolygonsAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
  497. let retLines = [];
  498. let retMarkers = [];
  499. let retPolygons = [];
  500. if (!Array.isArray(airspaceInfos)) {
  501. return { lines: retLines, markers: retMarkers, polygons: retPolygons };
  502. }
  503. let lineStyle = setStyle('line');
  504. for (let i = 0; i < airspaceInfos.length; i++) {
  505. let tmpLine = airspaceInfos[i];
  506. let airspaceTypeFix;
  507. if (tmpLine.airspaceType)
  508. airspaceTypeFix = 'airspaceType';
  509. else
  510. airspaceTypeFix = 'airspace_type';
  511. if (tmpLine[airspaceTypeFix] == Global.airspaceType.line && currentAirspaceIndex != i) {
  512. let lineProps = tmpLine;
  513. let { lines, markers, polygons } = getLinesRouter(lineProps, lineStyle);
  514. retMarkers.push(...markers);
  515. retLines.push(...lines);
  516. retPolygons.push(...polygons);
  517. }
  518. }
  519. return { lines: retLines, markers: retMarkers, polygons: retPolygons };
  520. }
  521. function getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) {
  522. return createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getLinesPolygonsAndMarkers);
  523. }
  524. function getPolygon(polygonProps, polygonAndMarkerStyle) {
  525. let coordinates = new Array();
  526. let markers = new Array();
  527. let { imageName, lineWidth, strokeColor, fillColor } = getDefaultStyle();
  528. if (polygonAndMarkerStyle) {
  529. imageName = polygonAndMarkerStyle.imageName;
  530. lineWidth = polygonAndMarkerStyle.lineWidth;
  531. strokeColor = polygonAndMarkerStyle.strokeColor;
  532. fillColor = polygonAndMarkerStyle.fillColor;
  533. }
  534. let pointsFix;
  535. if (polygonProps.points) {
  536. pointsFix = 'points';
  537. }
  538. else {
  539. pointsFix = 'polygonPoints';
  540. }
  541. if (Array.isArray(polygonProps[pointsFix])) {
  542. for (let obj of polygonProps[pointsFix]) {
  543. if (!obj) {
  544. continue;
  545. }
  546. coordinates.push(drawLineConfig(obj.lat, obj.lng));
  547. markers.push(addOvalPointConfig(obj.lat, obj.lng, imageName));
  548. }
  549. }
  550. let polygon = { lineWidth, strokeColor, fillColor, coordinates };
  551. return { markers, polygon };
  552. }
  553. function getPolygonsAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
  554. let markers = [];
  555. let polygons = [];
  556. if (!Array.isArray(airspaceInfos)) {
  557. return { markers, polygons };
  558. }
  559. let polygonAndMarkerStyle = setStyle('polygon');
  560. for (let i = 0; i < airspaceInfos.length; i++) {
  561. let polygon = airspaceInfos[i];
  562. let airspaceTypeFix;
  563. if (polygon.airspaceType)
  564. airspaceTypeFix = 'airspaceType';
  565. else
  566. airspaceTypeFix = 'airspace_type';
  567. if (polygon[airspaceTypeFix] == Global.airspaceType.polygon && currentAirspaceIndex != i) {
  568. let retObj = getPolygon(polygon, polygonAndMarkerStyle);
  569. markers.push(...retObj.markers);
  570. polygons.push(retObj.polygon);
  571. }
  572. }
  573. return { markers, polygons };
  574. }
  575. function getPolygonAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) {
  576. return createSelector(airspaceInfos, () => setStyle, currentAirspaceIndex, getPolygonsAndMarkers);
  577. }
  578. function getMarkers(circlesAndMarkers, polygonAndMarkers, lineAndMarkers) {
  579. let markers = [];
  580. if (circlesAndMarkers) {
  581. markers = [...circlesAndMarkers.markers];
  582. }
  583. if (polygonAndMarkers) {
  584. markers = [...markers, ...polygonAndMarkers.markers];
  585. }
  586. if (lineAndMarkers) {
  587. markers = [...markers, ...lineAndMarkers.markers];
  588. }
  589. return markers;
  590. }
  591. function getMarkerSelector(circlesAndMarkers, polygonAndMarkers, lineAndMarkers) {
  592. return createSelector(circlesAndMarkers, polygonAndMarkers, lineAndMarkers, getMarkers);
  593. }
  594. function getRegionPoints(circles, lineAndMarkers, polygonAndMarkers) {
  595. let regionPoints = new Array();
  596. for (let i = 0; i < circles.length; i++) {
  597. regionPoints.push(...getCircleRegions(circles[i]));
  598. }
  599. let lines = lineAndMarkers.lines;
  600. for (let i = 0; i < lines.length; i++) {
  601. regionPoints.push(...lines[i].coordinates);
  602. }
  603. let polygons = polygonAndMarkers.polygons;
  604. for (let i = 0; i < polygons.length; i++) {
  605. regionPoints.push(...polygons[i].coordinates);
  606. }
  607. return regionPoints;
  608. }
  609. function getRegionPointsSelector(circles, lineAndMarkers, polygonAndMarkers) {
  610. return createSelector(circles, lineAndMarkers, polygonAndMarkers, getRegionPoints);
  611. }
  612. function getCircles(circlesAndMarkers) {
  613. return circlesAndMarkers.circles;
  614. }
  615. function getCircleSelector(circlesAndMarkers) {
  616. return createSelector(circlesAndMarkers, getCircles);
  617. }
  618. function getLines(lineAndMarker) {
  619. return lineAndMarker.lines;
  620. }
  621. function getLineSelector(lineAndMarker) {
  622. return createSelector(lineAndMarker, getLines);
  623. }
  624. function getPolygons(polygonAndMarkers, linePolygonsAndMarkers) {
  625. return [...polygonAndMarkers.polygons, ...linePolygonsAndMarkers.polygons];
  626. }
  627. function getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers) {
  628. return createSelector(polygonAndMarkers, linePolygonsAndMarkers, getPolygons);
  629. }
  630. let setStyle = (styles) => {
  631. if (!styles)
  632. return () => null;
  633. else
  634. return (shapeName) => styles[shapeName];
  635. };
  636. //获取selector
  637. export function getShapesSelector(airspaceInfos, style, currentAirspaceIndex) {
  638. currentAirspaceIndex = currentAirspaceIndex ? currentAirspaceIndex : () => -1;
  639. let circlesAndMarkers = getCircleAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
  640. let circles = getCircleSelector(circlesAndMarkers);
  641. let linePolygonsAndMarkers = getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
  642. let lines = getLineSelector(linePolygonsAndMarkers);
  643. let polygonAndMarkers = getPolygonAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
  644. let polygons = getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers);
  645. let markers = getMarkerSelector(circlesAndMarkers, polygonAndMarkers, linePolygonsAndMarkers);
  646. let regionPoints = getRegionPointsSelector(circles, linePolygonsAndMarkers, polygonAndMarkers);
  647. return {
  648. markers,
  649. circles,
  650. lines,
  651. polygons,
  652. regionPoints
  653. };
  654. }
  655. //获取数组
  656. export function getShapes(airspaceInfos, style, currentAirspaceIndex) {
  657. let { markers, polygons, circles, lines, regionPoints } = getShapesSelector(() => airspaceInfos, style, () => currentAirspaceIndex);
  658. return {
  659. markers: markers(airspaceInfos),
  660. circles: circles(airspaceInfos),
  661. lines: lines(airspaceInfos),
  662. polygons: polygons(airspaceInfos),
  663. regionPoints: regionPoints(airspaceInfos)
  664. };
  665. }
  666. // 总共 5 种格式, http://git.corp.brilliantaero.com/BA/Coco/issues/99#note_6358
  667. // 1. 全输出格式
  668. // 2. 简化格式
  669. // 3. 传真格式
  670. // 4. 用户端用的简化格式
  671. // 5. 极简格式
  672. function getHeight(height, unit, type) {
  673. let shortNum;
  674. const num = +height; // to number
  675. if (num >= 100) {
  676. shortNum = parseInt(num / 100 + '').toString();
  677. if (shortNum.length < 2) {
  678. shortNum = '0' + shortNum;
  679. }
  680. }
  681. let heightStandard = Global.heightStandardsById.get(unit);
  682. if (!heightStandard) {
  683. heightStandard = unit;
  684. }
  685. // 这里统一使用数字判断
  686. let standardUnit = Global.heightStandards.get(heightStandard);
  687. let heightDesc;
  688. switch (standardUnit) {
  689. case 1:
  690. heightDesc = ['H*真', '真高*米'];
  691. break;
  692. case 2:
  693. heightDesc = ['H*标(含以下)', '标高*米(含以下)'];
  694. break;
  695. case 3:
  696. heightDesc = ['H*真(含以下)', '真高*米(含以下)'];
  697. break;
  698. default:
  699. heightDesc = ['H*标', '标高*米'];
  700. }
  701. if (shortNum && (type == 1 || type == 2)) {
  702. // H02真,H02真(含以下)
  703. return heightDesc[0].replace('*', shortNum);
  704. }
  705. else {
  706. // 真高200米,真高200米(含以下)
  707. return heightDesc[1].replace('*', height + '');
  708. }
  709. }
  710. function getAirspaceName(airspaceInfo) {
  711. if (airspaceInfo.airspace_name) {
  712. const ai = airspaceInfo;
  713. return ai.airspace_name;
  714. }
  715. else {
  716. const ai = airspaceInfo;
  717. return ai.name;
  718. }
  719. }
  720. export function circleContent(airspaceInfo, type = 3) {
  721. if (type == 5)
  722. return getAirspaceName(airspaceInfo);
  723. if ('airspace_name' in airspaceInfo) {
  724. const lat = latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lat);
  725. const lng = latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lng);
  726. let content = [];
  727. let loc = `以${airspaceInfo.center_loc}`;
  728. if (type == 1 || type == 3)
  729. loc += `(E${lng}, N${lat})`;
  730. content.push(`${loc}为中心`);
  731. content.push(`半径${airspaceInfo.radius_of_flying}米`);
  732. content.push(getHeight(airspaceInfo.altitude, airspaceInfo.unit, type));
  733. if (airspaceInfo.note)
  734. content.push(`备注:${airspaceInfo.note}`);
  735. return content.join(',');
  736. }
  737. else {
  738. let content = [];
  739. let loc = `以${airspaceInfo.addr}`;
  740. if (type == 1 || type == 3)
  741. loc += `(E${latLngDecimalToDegrees(airspaceInfo.lng)}, N${latLngDecimalToDegrees(airspaceInfo.lat)})`;
  742. content.push(`${loc}为中心`);
  743. content.push(`半径${airspaceInfo.radius}米`);
  744. content.push(getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type));
  745. if (airspaceInfo.note)
  746. content.push(`备注:${airspaceInfo.note}`);
  747. return content.join(',');
  748. }
  749. }
  750. function flyingCenter(item = {}) {
  751. if (item == {}) {
  752. return "";
  753. }
  754. const pp = item;
  755. return ("(E" + latLngDecimalToDegrees(pp.lng) +
  756. ', ' +
  757. "N" + latLngDecimalToDegrees(pp.lat) + ")");
  758. }
  759. export function lineContent(airspaceInfo, type = 3) {
  760. if (type == 5)
  761. return getAirspaceName(airspaceInfo);
  762. if ('airspace_name' in airspaceInfo) {
  763. let content = [];
  764. content.push(`${airspaceInfo.start_loc}`);
  765. if (type == 1 || type == 3)
  766. content.push(`${flyingCenter(airspaceInfo.start_point)}`);
  767. content.push(` - `);
  768. content.push(getHeight(airspaceInfo.start_point.altitude, airspaceInfo.start_point.unit, type));
  769. const passing_points = airspaceInfo.passing_points;
  770. if (Array.isArray(passing_points)) {
  771. for (let i = 0; i < passing_points.length; i++) {
  772. const obj = passing_points[i];
  773. if (obj.point_type == Global.pointTypes.point) {
  774. let pp = obj;
  775. const lat = latLngDecimalToDegrees(pp.lat);
  776. const lng = latLngDecimalToDegrees(pp.lng);
  777. content.push(` - ${pp.point_name}`);
  778. if (type == 1 || type == 3)
  779. content.push(`(E${lng}, N${lat})`);
  780. }
  781. else if (obj.point_type == Global.pointTypes.nav) {
  782. let pp = obj;
  783. const lat = latLngDecimalToDegrees(pp.lat);
  784. const lng = latLngDecimalToDegrees(pp.lng);
  785. content.push(` - ${pp.point_code}`);
  786. if (type == 1 || type == 3)
  787. content.push(`(E${lng}, N${lat})`);
  788. }
  789. else {
  790. let pp = obj;
  791. content.push(` - ${pp.air_route_code}`);
  792. }
  793. if (obj.altitude) {
  794. content.push(` - ${getHeight(obj.altitude, obj.unit, type)}`);
  795. }
  796. }
  797. }
  798. content.push(` - ${airspaceInfo.end_loc}`);
  799. if (type == 1 || type == 3)
  800. content.push(`${flyingCenter(airspaceInfo.end_point)}`);
  801. if (isSafeString(airspaceInfo.airline_width)) {
  802. content.push(`,宽度:${airspaceInfo.airline_width}米`);
  803. }
  804. if (isSafeString(airspaceInfo.note)) {
  805. content.push(`,备注: ${airspaceInfo.note}`);
  806. }
  807. let result = content.join("");
  808. return result;
  809. }
  810. else {
  811. let content = [];
  812. content.push(`${airspaceInfo.dep.addr}`);
  813. if (type == 1 || type == 3)
  814. content.push(`(E${latLngDecimalToDegrees(airspaceInfo.dep.lng)}, N${latLngDecimalToDegrees(airspaceInfo.dep.lat)})`);
  815. content.push(` - ${getHeight(airspaceInfo.dep.height, airspaceInfo.dep.heightStandard, type)}`);
  816. if (Array.isArray(airspaceInfo.passPoints)) {
  817. let length = airspaceInfo.passPoints.length;
  818. for (let i = 0; i < length; i++) {
  819. let obj = airspaceInfo.passPoints[i];
  820. if (obj.pointType == Global.pointTypes.point) {
  821. let pp = obj;
  822. content.push(` - ${pp.addr}`);
  823. if (type == 1 || type == 3)
  824. content.push(`(E${latLngDecimalToDegrees(pp.lng)}, N${latLngDecimalToDegrees(pp.lat)})`);
  825. }
  826. else if (obj.pointType == Global.pointTypes.nav) {
  827. let pp = obj;
  828. content.push(` - ${pp.pointCode}`);
  829. if (type == 1 || type == 3)
  830. content.push(`(E${latLngDecimalToDegrees(pp.lng)}, N${latLngDecimalToDegrees(pp.lat)})`);
  831. }
  832. else {
  833. let pp = obj;
  834. content.push(` - ${pp.airlineCode}`);
  835. }
  836. if (obj.height) {
  837. content.push(` - ${getHeight(obj.height, obj.heightStandard, type)}`);
  838. }
  839. }
  840. }
  841. content.push(` - ${airspaceInfo.arrive.addr}`);
  842. if (type == 1 || type == 3)
  843. content.push(`(E${latLngDecimalToDegrees(airspaceInfo.arrive.lng)}, N${latLngDecimalToDegrees(airspaceInfo.arrive.lat)})`);
  844. if (airspaceInfo.airlineWidth) {
  845. content.push(`,宽度:${airspaceInfo.airlineWidth}米`);
  846. }
  847. if (airspaceInfo.note)
  848. content.push(`,备注:${airspaceInfo.note}`);
  849. return content.join('');
  850. }
  851. }
  852. export function polygonContent(airspaceInfo, type = 3) {
  853. if (type == 5)
  854. return getAirspaceName(airspaceInfo);
  855. if ('airspace_name' in airspaceInfo) {
  856. let res = [];
  857. let points = airspaceInfo.points;
  858. for (let i = 0; i < points.length; i++) {
  859. let c = `${points[i].addr ? points[i].addr : ''}`;
  860. if (type == 1 || type == 3)
  861. c += `(E${latLngDecimalToDegrees(points[i].lng)}, N${latLngDecimalToDegrees(points[i].lat)})`;
  862. res.push(c);
  863. }
  864. let content = [res.join('、')];
  865. content.push(`${airspaceInfo.points.length}点连线范围内`);
  866. content.push(`,${getHeight(airspaceInfo.altitude, airspaceInfo.unit, type)}`);
  867. if (isSafeString(airspaceInfo.note)) {
  868. content.push(`,备注:${airspaceInfo.note}`);
  869. }
  870. return content.join('');
  871. }
  872. else {
  873. let content = [];
  874. let length = airspaceInfo.polygonPoints.length;
  875. for (let i = 0; i < length; i++) {
  876. let obj = airspaceInfo.polygonPoints[i];
  877. let c = `${obj.addr ? obj.addr : ''}`;
  878. if (type == 1 || type == 3)
  879. c += `(E${latLngDecimalToDegrees(obj.lng)}, N${latLngDecimalToDegrees(obj.lat)})`;
  880. content.push(c);
  881. }
  882. let cc = content.join('、') + `${length}点连线范围内`;
  883. cc += `,${getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type)}`;
  884. if (airspaceInfo.note)
  885. cc += `,备注:${airspaceInfo.note}`;
  886. return cc;
  887. }
  888. }
  889. export { latLngDegreesToDecimal, latLngDecimalToDegrees };