index.ts 44 KB

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