index.ts 43 KB

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