| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330 |
- import { createSelector, OutputSelector } from 'reselect';
- import Global from './Common';
- import { Marker, Circle, Line, Polygon} from 'react-native-amap-kit';
- import {
- latLngDegreesToDecimal,
- latLngDecimalToDegrees,
- isObject,
- isSafeString,
- hasPoint,
- isNumber
- } from './Utils'
- export { Marker, Circle, Line, Polygon };
- let LatLon = require('geodesy').LatLonSpherical;
- declare namespace LatLon {
- export interface Spherical {
- lat: number;
- lon: number;
- bearingTo: (point: LatLon.Spherical) => number;
- destinationPoint: (distance: number, bearing: number, radius?: number) => LatLon.Spherical
- }
- }
- export interface CoordinateShort {
- lat: number;
- lng: number;
- }
- export interface CoordinateLong {
- latitude: number;
- longitude: number;
- }
- // Server
- export interface LatLngAddrServer extends CoordinateShort {
- addr: string;
- }
- export interface LatLngPointServer extends LatLngAddrServer {
- altitude: number;
- unit: 0 | 1 | 2 | 3;
- }
- export interface StartPointServer extends CoordinateShort {
- altitude: number;
- unit: 0 | 1 | 2 | 3;
- }
- export interface AirRoutePoint extends CoordinateShort {
- point_id: number;
- point_name: string;
- point_code: string;
- }
- // Passpoints
- export interface PassingPointNavServer extends CoordinateShort {
- point_type: 1;
- altitude: number;
- unit: 0 | 1 | 2 | 3;
- point_id: number;
- point_code: string;
- point_name: string;
- }
- export interface PassingPointAirlineServer {
- point_type: 2;
- altitude: number;
- unit: 0 | 1 | 2 | 3;
- airway?: number;
- air_route_code: string;
- points: Array<AirRoutePoint>;
- }
- export interface PassingPointNormalServer extends CoordinateShort{
- point_type: 3;
- altitude: number;
- unit: 0 | 1 | 2 | 3;
- point_name: string;
- }
- // Airspace
- export interface AirspaceInfoCircleServer {
- airspace_name: string;
- airspace_type: 1;
- airspace_id: string;
- note: string;
- center_loc: string;
- center_point_of_flying: CoordinateShort;
- radius_of_flying: number;
- altitude: number;
- unit: number;
- }
- export interface AirspaceInfoLineServer {
- airspace_name: string;
- airspace_type: 2;
- airspace_id: string;
- note: string;
- start_loc: string;
- start_point: StartPointServer;
- end_loc: string;
- end_point: CoordinateShort;
- passing_points: Array<PassingPointServer>;
- airline_width?: number;
- }
- export interface AirspaceInfoPolygonServer {
- airspace_name: string;
- airspace_type: 3;
- airspace_id: string;
- note: string;
- points: Array<LatLngAddrServer>;
- altitude: number;
- unit: number;
- }
- // Local
- export interface CoordinateShortString {
- lat: string;
- lng: string;
- }
- export interface LatLngAddrLocal extends CoordinateShortString {
- addr: string;
- }
- export interface LatLngPointLocal extends LatLngAddrLocal{
- height: string;
- heightStandard: string;
- }
- // Passpoint
- export interface PassingPointNavLocal extends CoordinateShortString {
- pointType: 1;
- height: string;
- heightStandard: string;
- pointId: number;
- pointCode: string;
- pointName: string;
- }
- export interface PassingPointAirlineLocal {
- pointType: 2;
- height: string;
- heightStandard: string;
- airRouteId: number;
- airlineCode: string;
- airlines: Array<AirRoutePoint>;
- }
- export interface PassingPointNormalLocal extends CoordinateShortString {
- pointType: 3;
- height: string;
- heightStandard: string;
- addr: string;
- }
- // Airspace
- export interface AirspaceInfoCircleLocal {
- airspaceType: 1;
- airspaceId: string;
- name: string;
- note: string;
- addr: string;
- lat: string;
- lng: string;
- radius: number;
- height: string;
- heightStandard: string;
- }
- export interface AirspaceInfoLineLocal {
- airspaceType: 2;
- airspaceId: string;
- name: string;
- note: string;
- dep: LatLngPointLocal;
- arrive: LatLngAddrLocal;
- passPoints: Array<PassingPointLocal>;
- airlineWidth?: number;
- }
- export interface AirspaceInfoPolygonLocal {
- airspaceType: 3;
- airspaceId: string;
- name: string;
- note: string;
- polygonPoints: Array<LatLngAddrLocal>;
- height: string;
- heightStandard: string;
- }
- declare type AirspaceInfoCircle = AirspaceInfoCircleLocal | AirspaceInfoCircleServer;
- declare type AirspaceInfoLine = AirspaceInfoLineLocal | AirspaceInfoLineServer;
- declare type AirspaceInfoPolygon = AirspaceInfoPolygonLocal | AirspaceInfoPolygonServer;
- declare type AirspaceInfoLocal = AirspaceInfoCircleLocal | AirspaceInfoLineLocal | AirspaceInfoPolygonLocal;
- declare type AirspaceInfoServer = AirspaceInfoCircleServer | AirspaceInfoLineServer | AirspaceInfoPolygonServer;
- declare type AirspaceInfo = AirspaceInfoLocal | AirspaceInfoServer
- declare type PassingPointNav = PassingPointNavLocal | PassingPointNavServer
- declare type PassingPointNormal = PassingPointNormalLocal | PassingPointNormalServer
- declare type PassingPointAirline = PassingPointAirlineLocal | PassingPointAirlineServer
- declare type PassingPointLocal = PassingPointNavLocal | PassingPointNormalLocal | PassingPointAirlineLocal
- declare type PassingPointServer = PassingPointNavServer | PassingPointNormalServer | PassingPointAirlineServer
- declare type PassingPoint = PassingPointLocal | PassingPointServer
- // shapes
- export type Coordinate = CoordinateLong | CoordinateShort
- export interface CirclesAndMarkers {
- circles: Circle[];
- markers: Marker[];
- }
- export interface LinesAndMarkes {
- lines: Line[];
- markers: Marker[];
- }
- export interface LinesPolygonsAndMarkers {
- polygons: Polygon[];
- markers: Marker[];
- lines: Line[];
- }
- export interface PolygonsAndMarkers {
- polygons: Polygon[];
- markers: Marker[];
- }
- export interface ShapeStyle {
- imageName: string;
- lineWidth: number;
- strokeColor: string;
- fillColor: string;
- }
- export interface ShapeStyles {
- [styleName: string]: ShapeStyle
- }
- export function convertAirspaceInfoServerToLocal(airspaceInfo
- : AirspaceInfoCircleServer | AirspaceInfoLineServer | AirspaceInfoPolygonServer)
- : AirspaceInfoCircleLocal | AirspaceInfoLineLocal | AirspaceInfoPolygonLocal | null {
- const airspaceType = airspaceInfo.airspace_type
- if (airspaceType == Global.airspaceType.circle) {
- const ai: AirspaceInfoCircleServer = <AirspaceInfoCircleServer> airspaceInfo
- return <AirspaceInfoCircleLocal>{
- airspaceType,
- airspaceId: ai.airspace_id,
- name: ai.airspace_name,
- note: ai.note,
- addr: ai.center_loc,
- lat: latLngDecimalToDegrees(ai.center_point_of_flying.lat),
- lng: latLngDecimalToDegrees(ai.center_point_of_flying.lng),
- radius: ai.radius_of_flying,
- height: ai.altitude + "",
- heightStandard: Global.heightStandardsById.get(ai.unit)
- };
- }
- if (airspaceType == Global.airspaceType.line) {
- const ai: AirspaceInfoLineServer = <AirspaceInfoLineServer> airspaceInfo
- let dep = {
- addr: ai.start_loc,
- lat: latLngDecimalToDegrees(ai.start_point.lat),
- lng: latLngDecimalToDegrees(ai.start_point.lng),
- height: ai.start_point.altitude + "",
- heightStandard: Global.heightStandardsById.get(ai.start_point.unit)
- }
- let arrive = {
- addr: ai.end_loc,
- lat: latLngDecimalToDegrees(ai.end_point.lat),
- lng: latLngDecimalToDegrees(ai.end_point.lng)
- }
- let passPoints: (PassingPointNavLocal | PassingPointAirlineLocal | PassingPointNormalLocal)[] = []
- if(Array.isArray(ai.passing_points)) {
- for(let obj of ai.passing_points) {
- let point: PassingPointNavLocal | PassingPointAirlineLocal | PassingPointNormalLocal;
- if (obj.point_type == Global.pointTypes.point) {
- const pp = <PassingPointNormalServer>obj;
- const lat = latLngDecimalToDegrees(pp.lat)
- const lng = latLngDecimalToDegrees(pp.lng)
- point = <PassingPointNormalLocal>{
- pointType: pp.point_type,
- addr: pp.point_name,
- lat, lng
- }
- } else if (obj.point_type == Global.pointTypes.nav) {
- const pp = <PassingPointNavServer>obj;
- const lat = latLngDecimalToDegrees(pp.lat)
- const lng = latLngDecimalToDegrees(pp.lng)
- point = <PassingPointNavLocal>{
- pointType: pp.point_type,
- pointId: pp.point_id,
- pointCode: pp.point_code,
- pointName: pp.point_name,
- lat, lng
- }
- } else {
- const pp = <PassingPointAirlineServer>obj;
- point = <PassingPointAirlineLocal>{
- pointType: pp.point_type,
- airRouteId: pp.airway,
- airlineCode: pp.air_route_code,
- airlines: pp.points
- }
- }
- if(isNumber(obj.altitude) && isNumber(obj.unit)) {
- point.height = obj.altitude + "";
- point.heightStandard = Global.heightStandardsById.get(obj.unit);
- } else {
- point.height = ""
- point.heightStandard = [...Global.heightStandards.keys()][0];
- }
- passPoints.push(point)
- }
- }
- return <AirspaceInfoLineLocal>{ ...{
- airspaceType,
- airspaceId: ai.airspace_id,
- name: ai.airspace_name,
- note: ai.note,
- dep,
- arrive,
- passPoints
- }, ...(ai.airline_width ? {airlineWidth: ai.airline_width} : {})}
- }
- if (airspaceType == Global.airspaceType.polygon) {
- const ai = <AirspaceInfoPolygonServer>airspaceInfo;
- if(Array.isArray(ai.points)) {
- let polygonPoints = new Array();
- let defaultPointName = 'A'
- for(let obj of ai.points) {
- let addr = obj.addr
- if(!addr) {
- addr = defaultPointName
- defaultPointName = String.fromCharCode(defaultPointName.charCodeAt(0) + 1)
- }
- polygonPoints.push({addr, lat: latLngDecimalToDegrees(obj.lat), lng: latLngDecimalToDegrees(obj.lng)})
- }
- return <AirspaceInfoPolygonLocal>{
- airspaceType,
- airspaceId: ai.airspace_id,
- name: ai.airspace_name,
- note: ai.note,
- height: ai.altitude + '',
- heightStandard: Global.heightStandardsById.get(ai.unit),
- polygonPoints
- };
- }
- }
- return null;
- }
- export function convertAirspaceInfoLocalToServer(airspace
- : AirspaceInfoCircleLocal | AirspaceInfoLineLocal | AirspaceInfoPolygonLocal)
- : AirspaceInfoCircleServer | AirspaceInfoLineServer | AirspaceInfoPolygonServer {
- if (airspace.airspaceType == Global.airspaceType.circle) {
- const ai = <AirspaceInfoCircleLocal> airspace;
- const circle = <AirspaceInfoCircleServer>{
- airspace_name: ai.name,
- airspace_id: ai.airspaceId,
- airspace_type: Global.airspaceType.circle,
- note: isSafeString(ai.note) ? ai.note : null,
- radius_of_flying: parseInt(ai.radius + ''),
- center_point_of_flying: {
- lng: latLngDegreesToDecimal(ai.lng),
- lat: latLngDegreesToDecimal(ai.lat)
- },
- center_loc: ai.addr,
- altitude: parseInt(ai.height),
- unit: Global.heightStandards.get(ai.heightStandard)
- };
- return circle
- } else if (airspace.airspaceType == Global.airspaceType.line) {
- const ai = <AirspaceInfoLineLocal> airspace;
- let line = <AirspaceInfoLineServer>{
- airspace_name: ai.name,
- airspace_id: ai.airspaceId,
- airspace_type: Global.airspaceType.line,
- note: ai.note,
- start_loc: ai.dep.addr,
- start_point: {
- lng: latLngDegreesToDecimal(ai.dep.lng),
- lat: latLngDegreesToDecimal(ai.dep.lat),
- altitude: parseInt(ai.dep.height),
- unit: Global.heightStandards.get(ai.dep.heightStandard)
- },
- end_loc: ai.arrive.addr,
- end_point: {
- lng: latLngDegreesToDecimal(ai.arrive.lng),
- lat: latLngDegreesToDecimal(ai.arrive.lat)
- }
- }
- if(ai.airlineWidth) {
- line['airline_width'] = ai.airlineWidth
- }
- if (Array.isArray(ai.passPoints) && ai.passPoints.length > 0) {
- let passing_points = [];
- for (let obj of ai.passPoints) {
- let retObj: PassingPointNormalServer | PassingPointNavServer | PassingPointAirlineServer;
- if (obj.pointType == Global.pointTypes.point && hasPoint(<PassingPointNormalLocal>obj)) {
- const pp = <PassingPointNormalLocal>obj;
- retObj = <PassingPointNormalServer>{
- point_type: Global.pointTypes.point,
- point_name: pp.addr,
- lat: latLngDegreesToDecimal(pp.lat),
- lng: latLngDegreesToDecimal(pp.lng)
- };
- } else if (obj.pointType == Global.pointTypes.nav) {
- const pp = <PassingPointNavLocal>obj;
- retObj = <PassingPointNavServer>{
- point_type: Global.pointTypes.nav,
- point_name: pp.pointName,
- point_id: pp.pointId,
- point_code: pp.pointCode,
- lat: latLngDegreesToDecimal(pp.lat),
- lng: latLngDegreesToDecimal(pp.lng)
- };
- } else {
- const pp = <PassingPointAirlineLocal>obj;
- retObj = <PassingPointAirlineServer>{
- point_type: Global.pointTypes.line,
- airway: pp.airRouteId,
- air_route_code: pp.airlineCode,
- points: pp.airlines
- };
- }
- if (isSafeString(obj.height) && isSafeString(obj.heightStandard)) {
- retObj.altitude = parseInt(obj.height);
- // @ts-ignore
- retObj.unit = Global.heightStandards.get(obj.heightStandard);
- }
- passing_points.push(retObj)
- }
- line.passing_points = passing_points;
- } else {
- line.passing_points = [];
- }
- return line;
- } else {
- const ai = <AirspaceInfoPolygonLocal> airspace;
- let points = [];
- for (let obj of ai.polygonPoints) {
- points.push({ addr: obj.addr, lat: latLngDegreesToDecimal(obj.lat), lng: latLngDegreesToDecimal(obj.lng) })
- }
- const polygon = <AirspaceInfoPolygonServer>{
- airspace_name: ai.name,
- airspace_id: ai.airspaceId,
- airspace_type: Global.airspaceType.polygon,
- note: ai.note,
- altitude: parseInt(ai.height),
- unit: Global.heightStandards.get(ai.heightStandard),
- points
- };
- return polygon;
- }
- }
- function getCircleRegions(circle: Circle): CoordinateShort[] {
- let lat, lng;
- if((circle.coordinate as any).latitude) {
- let coord = <CoordinateLong> circle.coordinate;
- lat = coord.latitude;
- lng = coord.longitude;
- } else {
- let coord = <CoordinateShort> circle.coordinate;
- lat = coord.lat;
- lng = coord.lng;
- }
- let latlon = new LatLon(lat, lng)
- let d1 = latlon.destinationPoint(circle.radius, 0)
- let d2 = latlon.destinationPoint(circle.radius, 90)
- let d3 = latlon.destinationPoint(circle.radius, 180)
- let d4 = latlon.destinationPoint(circle.radius, 270)
- return [{ lat: d1.lat, lng: d1.lon }, { lat: d2.lat, lng: d2.lon }, { lat: d3.lat, lng: d3.lon }, { lat: d4.lat, lng: d4.lon }]
- }
- function getDefaultStyle(): ShapeStyle {
- let imageName = 'BA_oval'
- let lineWidth = Global.amapLineWidth
- let strokeColor = Global.amapStrokeColor
- let fillColor = Global.amapFillColor
- return {imageName, lineWidth, strokeColor, fillColor}
- }
- function getCirclesAndMarkers(airspaceInfos: AirspaceInfo[], setStyle: (styleName: string) => ShapeStyle | null, currentAirspaceIndex: number | undefined): CirclesAndMarkers {
- let circles: Circle[] = [];
- let markers: Marker[] = [];
- if (!Array.isArray(airspaceInfos)) {
- return {circles, markers};
- }
- let {imageName, lineWidth, strokeColor, fillColor} = getDefaultStyle()
- //通过该方法获取样式
- let circleStyle = setStyle('circle');
- if(circleStyle) {
- lineWidth = circleStyle.lineWidth
- strokeColor = circleStyle.strokeColor
- fillColor = circleStyle.fillColor
- imageName = circleStyle.imageName
- }
- for (let i = 0; i < airspaceInfos.length; i++) {
- let tmpCircle = airspaceInfos[i]
- let airspaceTypeFix, radiusFix
- if ((tmpCircle as any).airspaceType) {
- airspaceTypeFix = 'airspaceType';
- radiusFix = 'radius'
- } else {
- airspaceTypeFix = 'airspace_type';
- radiusFix = 'radius_of_flying'
- }
- if ((tmpCircle as any)[airspaceTypeFix] == Global.airspaceType.circle && currentAirspaceIndex != i) {
- let coordinate = {latitude: 0, longitude: 0};
- if ((tmpCircle as any).center_point_of_flying) {
- let ai = <AirspaceInfoCircleServer>tmpCircle;
- coordinate.latitude = ai.center_point_of_flying.lat;
- coordinate.longitude = ai.center_point_of_flying.lng;
- } else {
- let ai = <AirspaceInfoCircleLocal>tmpCircle;
- coordinate.latitude = latLngDegreesToDecimal(ai.lat);
- coordinate.longitude = latLngDegreesToDecimal(ai.lng);
- }
- let radius = (tmpCircle as any)[radiusFix];
- if(radius) {
- let circle = <Circle>{lineWidth, strokeColor, fillColor, radius, coordinate}
- circles.push(circle);
- } else {
- // 这里的经纬度必定是数值, 所以最后一个参数是 2
- markers.push(addOvalPointConfig(coordinate.latitude, coordinate.longitude, imageName, 2));
- }
- }
- }
- return {circles, markers};
- }
- function getCircleAndMarkerSelector(airspaceInfos: () => AirspaceInfo[], setStyle: (styleName: string)=> ShapeStyle | null, currentAirspaceIndex: () => number | undefined) {
- return createSelector(
- airspaceInfos,
- () => setStyle,
- currentAirspaceIndex,
- getCirclesAndMarkers
- );
- }
- function getLatLng(latlng: number | string, dataType: number): number {
- if(dataType == 1) { // 驼峰模式,新建计划的时候的格式
- return latLngDegreesToDecimal(<string>latlng)
- } else {
- return <number>latlng
- }
- }
- function drawLineConfig(lat: number | string, lng: number | string, dataType: number) {
- return {
- latitude: getLatLng(lat, dataType),
- longitude: getLatLng(lng, dataType)
- };
- }
- function addOvalPointConfig(lat: number | string, lng: number | string, imageName: string, dataType: number) {
- return {
- coordinate: {
- latitude: getLatLng(lat, dataType),
- longitude: getLatLng(lng, dataType)
- },
- imageName: imageName
- };
- }
- function pointCompare(point1: AirRoutePoint | undefined, point2: AirRoutePoint | undefined) {
- if (!point1 || !point2) {
- return false
- }
- const pointId1 = point1.point_id;
- const pointId2 = point2.point_id;
- if(pointId1 == pointId2) {
- return true;
- }
- let [point1Lat, point1lng] = getFixedLatLng(point1)
- let [point2lat, point2lng] = getFixedLatLng(point2)
- if(myRound(point1Lat) == myRound(point2lat)
- && myRound(point1lng) == myRound(point2lng)) {
- return true
- } else {
- return false
- }
- }
- function getCrossPoint(points1: AirRoutePoint[], points2: AirRoutePoint[]) {
- for(let point1 of points1) {
- for(let point2 of points2) {
- if (pointCompare(point1, point2))
- return point1
- }
- }
- return undefined
- }
- function getAirwayPoints(airway: PassingPointAirline, pointBefore: PassingPoint, pointAfter: PassingPoint) {
- let found = 0
- let points = []
- let pointTypeFix, pointsFix, airRoutePoint
- if ('points' in airway) {
- pointTypeFix = 'point_type';
- pointsFix = 'points'
- airRoutePoint = airway['points']
- } else {
- pointTypeFix = 'pointType'
- pointsFix = 'airlines'
- airRoutePoint = airway['airlines']
- }
- let crossPointBefore, crossPointAfter;
- // 如果前后是其他航线,那么找到交叉点作为前后的点
- if ( (pointBefore as any)[pointTypeFix] == Global.pointTypes.line ) {
- crossPointBefore = getCrossPoint(airRoutePoint, <AirRoutePoint[]>(pointBefore as any)[pointsFix])
- }
- if((pointAfter as any)[pointTypeFix] == Global.pointTypes.line) {
- crossPointAfter = getCrossPoint(airRoutePoint, <AirRoutePoint[]>(pointAfter as any)[pointsFix])
- }
- for (let point of airRoutePoint) {
- if (pointCompare(crossPointBefore, point) || pointCompare(crossPointAfter, point)) {
- found++
- points.push(Object.assign({}, point))
- continue
- }
- if (found == 1) {
- points.push(Object.assign({}, point))
- }
- }
- if (!(points.length > 0 && found == 2)) {
- // 如果两个点不全在航线上面,那么画全部航线
- points = airRoutePoint
- }
- return points;
- }
- function getLinesRouter(lineProps: AirspaceInfoLine, lineAndMarkerStyle: ShapeStyle | null) {
- let coordinates: Coordinate[] = new Array();
- let markers: Marker[] = new Array();
- let lines: Line[] = []
- let {imageName, lineWidth, strokeColor} = getDefaultStyle()
- if (lineAndMarkerStyle) {
- imageName = lineAndMarkerStyle.imageName
- lineWidth = lineAndMarkerStyle.lineWidth
- strokeColor = lineAndMarkerStyle.strokeColor
- }
- let startPoint, passPoints, endPoint, pointTypeFix, dataType, airlineWidth
- if ((lineProps as any).start_point) {
- let ll = <AirspaceInfoLineServer>lineProps;
- dataType = 2 // 下划线模式
- startPoint = ll['start_point']
- passPoints = ll['passing_points']
- endPoint = ll['end_point']
- pointTypeFix = 'point_type';
- airlineWidth = parseInt(ll['airline_width'] + '', 10)
- } else {
- let ll = <AirspaceInfoLineLocal>lineProps;
- dataType = 1 // 驼峰模式
- startPoint = ll['dep']
- passPoints = ll['passPoints']
- endPoint = ll['arrive']
- pointTypeFix = 'pointType'
- airlineWidth = parseInt(ll['airlineWidth'] + '', 10)
- }
- if (startPoint) {
- coordinates.push(drawLineConfig(startPoint.lat, startPoint.lng, dataType));
- markers.push(addOvalPointConfig(startPoint.lat, startPoint.lng, imageName, dataType));
- }
- if (Array.isArray(passPoints)) {
- for (let i = 0; i < passPoints.length; i++) {
- let obj = passPoints[i]
- if (!isObject(obj)) { // 所有的 points/airway 都必须是 obj
- continue;
- }
- let pointType = (obj as any)[pointTypeFix]
- if ( pointType == Global.pointTypes.point
- || pointType == Global.pointTypes.nav) {
- let pp = <PassingPointNav | PassingPointNormal>obj
- coordinates.push(drawLineConfig(pp.lat, pp.lng, dataType));
- markers.push(addOvalPointConfig(pp.lat, pp.lng, imageName, dataType));
- } else {
- // 遇到一个航线,不需要和前前面的点连起来
- let pp = <PassingPointAirline>obj
- if (coordinates.length > 1) {
- lines.push({lineWidth, strokeColor, coordinates})
- }
- coordinates = []
- const pointBefore = i == 0 ? startPoint : passPoints[i - 1]
- const pointAfter = i == passPoints.length - 1 ? (endPoint ? endPoint : passPoints[passPoints.length - 1]) : passPoints[i + 1]
- lines.push({lineWidth, strokeColor, coordinates: getAirwayPoints(pp, <PassingPoint>pointBefore, <PassingPoint>pointAfter)})
- }
- }
- }
- if (endPoint) {
- coordinates.push(drawLineConfig(endPoint.lat, endPoint.lng, dataType));
- markers.push(addOvalPointConfig(endPoint.lat, endPoint.lng, imageName, dataType));
- }
- if (coordinates.length > 1) {
- lines.push({lineWidth, strokeColor, coordinates});
- }
- if(airlineWidth > 0) {
- // 有宽度的空域,需要线周围多画宽度的多边形
- let polygons = processAirlineWidth(lines, airlineWidth)
- return { lines, markers, polygons };
- } else {
- return { lines, markers, polygons: [] };
- }
- }
- function getFixedLatLng(point: {lat?: string | number, lng?: string | number, latitude?: string | number, longitude?: string | number}): [number, number] {
- let pp = <any> point;
- let lat = pp.latitude ? pp.latitude : pp.lat
- let lng = pp.longitude ? pp.longitude : pp.lng
- // 复制计划的数据,有的点是度数模式如 38°35′17″
- if(isSafeString(lat)) {
- lat = latLngDegreesToDecimal(<string>lat);
- lng = latLngDegreesToDecimal(<string>lng);
- }
- return [lat, lng]
- }
- function processAirlineWidth(lines: Line[], airlineWidth: number) {
- let polygons: Polygon[] = []
- let {strokeColor, fillColor} = getDefaultStyle()
- for(let line of lines) {
- let points = line.coordinates
- for(let i=0; i<points.length-1; i++) {
- let [lat1, lng1] = getFixedLatLng(points[i])
- let [lat2, lng2] = getFixedLatLng(points[i+1])
- let point1: LatLon.Spherical = new LatLon(lat1, lng1)
- let point2: LatLon.Spherical = new LatLon(lat2, lng2)
- let coordinates = getCirclePoints(point1, point2, airlineWidth)
- polygons.push({lineWidth: 1, strokeColor, fillColor, coordinates})
- }
- }
- return polygons
- }
- function getCirclePoints(point1: LatLon.Spherical, point2: LatLon.Spherical, width: number) {
- let percision = 10 // 半圆处理为多边形的时候,半圆上取几个点
- let step = 180/percision
- let bearing = (360 + point1.bearingTo(point2) - 90) % 360 // 取正值
- let points = []
- for(let diff = 0; diff <= 180; diff += step) {
- let point = point2.destinationPoint(width, bearing + diff)
- points.push({lat: point.lat, lng: point.lon})
- }
- for(let diff = 180; diff <= 360; diff += step) {
- let point = point1.destinationPoint(width, bearing + diff)
- points.push({lat: point.lat, lng: point.lon})
- }
- return points
- }
- function myRound(num: number, digits?: number) {
- if(digits == null)
- digits = 6 // 比较的精度,经纬度会被经过度分秒方式到浮点方式的转化
- return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits)
- }
- function getLinesPolygonsAndMarkers(airspaceInfos: AirspaceInfo[], setStyle: FnSetStyle, currentAirspaceIndex: number | undefined): LinesPolygonsAndMarkers {
- let retLines: Line[] = [];
- let retMarkers: Marker[] = [];
- let retPolygons: Polygon[] = [];
- if (!Array.isArray(airspaceInfos)) {
- return { lines: retLines, markers: retMarkers, polygons: retPolygons };
- }
- let lineStyle = setStyle('line');
- for (let i = 0; i < airspaceInfos.length; i++) {
- let tmpLine = airspaceInfos[i]
- let airspaceTypeFix;
- if ((tmpLine as any).airspaceType)
- airspaceTypeFix = 'airspaceType';
- else
- airspaceTypeFix = 'airspace_type';
- if ((tmpLine as any)[airspaceTypeFix] == Global.airspaceType.line && currentAirspaceIndex != i) {
- let lineProps = <AirspaceInfoLine>tmpLine;
- let { lines, markers, polygons } = getLinesRouter(lineProps, lineStyle);
- retMarkers.push(...markers);
- retLines.push(...lines);
- retPolygons.push(...polygons)
- }
- }
- return { lines: retLines, markers: retMarkers, polygons: retPolygons };
- }
- function getLinePolygonsAndMarkerSelector(airspaceInfos: () => AirspaceInfo[], setStyle: FnSetStyle, currentAirspaceIndex: () => number | undefined) {
- return createSelector(
- airspaceInfos,
- () => setStyle,
- currentAirspaceIndex,
- getLinesPolygonsAndMarkers
- );
- }
- function getPolygon(polygonProps: AirspaceInfoPolygon, polygonAndMarkerStyle: ShapeStyle | null) {
- let coordinates: Coordinate[] = new Array();
- let markers: Marker[] = new Array();
- let {imageName, lineWidth, strokeColor, fillColor} = getDefaultStyle()
- if (polygonAndMarkerStyle) {
- imageName = polygonAndMarkerStyle.imageName
- lineWidth = polygonAndMarkerStyle.lineWidth
- strokeColor = polygonAndMarkerStyle.strokeColor
- fillColor = polygonAndMarkerStyle.fillColor
- }
- let pointsFix, dataType;
- if ((polygonProps as any).points) {
- pointsFix = 'points';
- dataType = 2
- } else {
- pointsFix = 'polygonPoints';
- dataType = 1 // 驼峰模式
- }
- if (Array.isArray((polygonProps as any)[pointsFix])) {
- for (let obj of (polygonProps as any)[pointsFix]) {
- if (!obj) {
- continue
- }
- coordinates.push(drawLineConfig(obj.lat, obj.lng, dataType));
- markers.push(addOvalPointConfig(obj.lat, obj.lng, imageName, dataType));
- }
- }
- let polygon = <Polygon>{lineWidth, strokeColor, fillColor, coordinates};
- return { markers, polygon };
- }
- function getPolygonsAndMarkers(airspaceInfos: AirspaceInfo[], setStyle: FnSetStyle, currentAirspaceIndex: number | undefined): PolygonsAndMarkers {
- let markers: Marker[] = [];
- let polygons: Polygon[] = [];
- if (!Array.isArray(airspaceInfos)) {
- return { markers, polygons };
- }
- let polygonAndMarkerStyle = setStyle('polygon');
- for (let i = 0; i < airspaceInfos.length; i++) {
- let polygon = <AirspaceInfoPolygon>airspaceInfos[i]
- let airspaceTypeFix;
- if ((polygon as any).airspaceType)
- airspaceTypeFix = 'airspaceType';
- else
- airspaceTypeFix = 'airspace_type';
- if ((polygon as any)[airspaceTypeFix] == Global.airspaceType.polygon && currentAirspaceIndex != i) {
- let retObj = getPolygon(polygon, polygonAndMarkerStyle);
- markers.push(...retObj.markers);
- polygons.push(retObj.polygon);
- }
- }
- return { markers, polygons };
- }
- function getPolygonAndMarkerSelector(airspaceInfos: () => AirspaceInfo[], setStyle: FnSetStyle, currentAirspaceIndex: () => number | undefined) {
- return createSelector(
- airspaceInfos,
- () => setStyle,
- currentAirspaceIndex,
- getPolygonsAndMarkers
- );
- }
- function getMarkers(circlesAndMarkers: CirclesAndMarkers, polygonAndMarkers: PolygonsAndMarkers, lineAndMarkers: LinesAndMarkes) {
- let markers: Marker[] = [];
- if (circlesAndMarkers) {
- markers = [...circlesAndMarkers.markers]
- }
- if (polygonAndMarkers) {
- markers = [...markers, ...polygonAndMarkers.markers]
- }
- if (lineAndMarkers) {
- markers = [...markers, ...lineAndMarkers.markers]
- }
- return markers
- }
- function getMarkerSelector(
- circlesAndMarkers: OutputSelector<any, any, (...params: any[]) => CirclesAndMarkers>,
- polygonAndMarkers: OutputSelector<any, any, (...params: any[]) => PolygonsAndMarkers>,
- lineAndMarkers: OutputSelector<any, any, (...params: any[]) => LinesAndMarkes>) {
- return createSelector(
- circlesAndMarkers,
- polygonAndMarkers,
- lineAndMarkers,
- getMarkers
- )
- }
- function getRegionPoints(circles: Circle[], lineAndMarkers: LinesAndMarkes, polygonAndMarkers: PolygonsAndMarkers) {
- let regionPoints: Coordinate[] = new Array();
- for (let i = 0; i < circles.length; i++) {
- regionPoints.push(...getCircleRegions(circles[i]));
- }
- let lines = lineAndMarkers.lines;
- for (let i = 0; i < lines.length; i++) {
- regionPoints.push(...lines[i].coordinates);
- }
- let polygons = polygonAndMarkers.polygons;
- for (let i = 0; i < polygons.length; i++) {
- regionPoints.push(...polygons[i].coordinates);
- }
- return regionPoints;
- }
- function getRegionPointsSelector(
- circles: OutputSelector<any, any, (...params: any[])=>Circle[]>,
- lineAndMarkers: OutputSelector<any, any, (...params: any[])=>LinesAndMarkes>,
- polygonAndMarkers: OutputSelector<any, any, (...params: any[])=>PolygonsAndMarkers>) {
- return createSelector(
- circles,
- lineAndMarkers,
- polygonAndMarkers,
- getRegionPoints
- );
- }
- function getCircles(circlesAndMarkers: CirclesAndMarkers) {
- return circlesAndMarkers.circles;
- }
- function getCircleSelector(circlesAndMarkers: OutputSelector<any, any, (...params: any[])=> CirclesAndMarkers>) {
- return createSelector(
- circlesAndMarkers,
- getCircles
- );
- }
- function getLines(lineAndMarker: LinesAndMarkes) {
- return lineAndMarker.lines;
- }
- function getLineSelector(lineAndMarker: OutputSelector<any, any, (...params: any[])=>LinesAndMarkes>) {
- return createSelector(
- lineAndMarker,
- getLines
- );
- }
- function getPolygons(polygonAndMarkers: PolygonsAndMarkers, linePolygonsAndMarkers: LinesPolygonsAndMarkers) {
- return [...polygonAndMarkers.polygons, ...linePolygonsAndMarkers.polygons];
- }
- function getPolygonSelector(
- polygonAndMarkers: OutputSelector<any, any, (...params: any[]) => PolygonsAndMarkers>,
- linePolygonsAndMarkers: OutputSelector<any, any, (...params: any[]) => LinesPolygonsAndMarkers>) {
- return createSelector(
- polygonAndMarkers,
- linePolygonsAndMarkers,
- getPolygons
- );
- }
- export type FnSetStyle = (styleName: string) => null | ShapeStyle
- let setStyle: (style: undefined | ShapeStyles) => FnSetStyle = (styles) => {
- if (!styles)
- return () => null
- else
- return (shapeName: string): ShapeStyle => styles[shapeName]
- }
- //获取selector
- export function getShapesSelector(airspaceInfos: () => AirspaceInfo[], style?: ShapeStyles, currentAirspaceIndex?: () => number | undefined) {
- currentAirspaceIndex = currentAirspaceIndex ? currentAirspaceIndex : () => -1;
- let circlesAndMarkers = getCircleAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
- let circles = getCircleSelector(circlesAndMarkers);
- let linePolygonsAndMarkers = getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
- let lines = getLineSelector(linePolygonsAndMarkers);
- let polygonAndMarkers = getPolygonAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
- let polygons = getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers);
- let markers = getMarkerSelector(circlesAndMarkers, polygonAndMarkers, linePolygonsAndMarkers);
- let regionPoints = getRegionPointsSelector(circles, linePolygonsAndMarkers, polygonAndMarkers);
- return {
- markers,
- circles,
- lines,
- polygons,
- regionPoints
- }
- }
- //获取数组
- export function getShapes(airspaceInfos: AirspaceInfo[], style?: ShapeStyles, currentAirspaceIndex?: number) {
- let {markers, polygons, circles, lines, regionPoints} =
- getShapesSelector(()=>airspaceInfos, style, ()=>currentAirspaceIndex)
- return {
- markers: markers(airspaceInfos),
- circles: circles(airspaceInfos),
- lines: lines(airspaceInfos),
- polygons: polygons(airspaceInfos),
- regionPoints: regionPoints(airspaceInfos)
- }
- }
- // 总共 5 种格式, http://git.corp.brilliantaero.com/BA/Coco/issues/99#note_6358
- // 1. 全输出格式
- // 2. 简化格式
- // 3. 传真格式
- // 4. 用户端用的简化格式
- // 5. 极简格式
- function getHeight(height: number | string, unit: string | number, type: number) {
- let shortNum
- const num = +height; // to number
- if(num >= 100) {
- shortNum = parseInt(num/100 + '').toString()
- if(shortNum.length <2) {
- shortNum = '0' + shortNum
- }
- }
- let heightStandard = Global.heightStandardsById.get(unit)
- if(!heightStandard) {
- heightStandard = unit
- }
- // 这里统一使用数字判断
- let standardUnit = Global.heightStandards.get(heightStandard)
- let heightDesc
- switch(standardUnit) {
- case 1:
- heightDesc = ['H*真', '真高*米']
- break;
- case 2:
- heightDesc = ['H*标(含以下)', '标高*米(含以下)']
- break;
- case 3:
- heightDesc = ['H*真(含以下)', '真高*米(含以下)']
- break;
- default:
- heightDesc = ['H*标', '标高*米']
- }
- if(shortNum && (type == 1 || type == 2)) {
- // H02真,H02真(含以下)
- return heightDesc[0].replace('*', shortNum)
- } else {
- // 真高200米,真高200米(含以下)
- return heightDesc[1].replace('*', height + '')
- }
- }
- function getAirspaceName(airspaceInfo: AirspaceInfo) {
- if((airspaceInfo as any).airspace_name) {
- const ai = <AirspaceInfoServer> airspaceInfo;
- return ai.airspace_name
- } else {
- const ai = <AirspaceInfoLocal> airspaceInfo;
- return ai.name
- }
- }
- export function circleContent(airspaceInfo: AirspaceInfoCircle, type=3) {
- if(type == 5)
- return getAirspaceName(airspaceInfo)
- if('airspace_name' in airspaceInfo) {
- const lat = latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lat);
- const lng = latLngDecimalToDegrees(airspaceInfo.center_point_of_flying.lng);
- let content = [];
- let loc = `以${airspaceInfo.center_loc}`
- if(type == 1 || type == 3)
- loc += `(E${lng}, N${lat})`;
- content.push(`${loc}为中心`)
- content.push(`半径${airspaceInfo.radius_of_flying}米`);
- content.push(getHeight(airspaceInfo.altitude, airspaceInfo.unit, type))
- if (airspaceInfo.note)
- content.push(`备注:${airspaceInfo.note}`)
- return content.join(',');
- } else {
- let content = []
- let loc = `以${airspaceInfo.addr}`
- if(type == 1 || type == 3)
- loc += `(E${airspaceInfo.lng}, N${airspaceInfo.lat})`;
- content.push(`${loc}为中心`)
- content.push(`半径${airspaceInfo.radius}米`);
- content.push(getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type))
- if (airspaceInfo.note)
- content.push(`备注:${airspaceInfo.note}`)
- return content.join(',');
- }
- }
- function flyingCenter(item: CoordinateShort | {} = {}): string{
- if(item == {}){
- return "";
- }
- const pp = <CoordinateShort> item;
- return (
- "(E" + latLngDecimalToDegrees(pp.lng) +
- ', ' +
- "N" + latLngDecimalToDegrees(pp.lat) + ")"
- );
- }
- export function lineContent(airspaceInfo: AirspaceInfoLine, type=3): string {
- if(type == 5)
- return getAirspaceName(airspaceInfo)
- if('airspace_name' in airspaceInfo) {
- let content = [];
- content.push(`${airspaceInfo.start_loc}`)
- if(type == 1 || type == 3)
- content.push(`${flyingCenter(airspaceInfo.start_point)}`)
- content.push(` - `)
- content.push(getHeight(airspaceInfo.start_point.altitude, airspaceInfo.start_point.unit, type))
- const passing_points = airspaceInfo.passing_points;
- if(Array.isArray(passing_points)) {
- for(let i = 0; i < passing_points.length; i++) {
- const obj = passing_points[i];
- if (obj.point_type == Global.pointTypes.point) {
- let pp = <PassingPointNormalServer>obj;
- const lat = latLngDecimalToDegrees(pp.lat)
- const lng = latLngDecimalToDegrees(pp.lng)
- content.push(` - ${pp.point_name}`)
- if(type == 1 || type == 3)
- content.push(`(E${lng}, N${lat})`)
- } else if (obj.point_type == Global.pointTypes.nav) {
- let pp = <PassingPointNavServer>obj;
- const lat = latLngDecimalToDegrees(pp.lat)
- const lng = latLngDecimalToDegrees(pp.lng)
- content.push(` - ${pp.point_code}`)
- if(type == 1 || type == 3)
- content.push(`(E${lng}, N${lat})`)
- } else {
- let pp = <PassingPointAirlineServer>obj;
- content.push(` - ${pp.air_route_code}`)
- }
- if(obj.altitude) {
- content.push(` - ${getHeight(obj.altitude, obj.unit, type)}`)
- }
- }
- }
- content.push(` - ${airspaceInfo.end_loc}`)
- if(type == 1 || type == 3)
- content.push(`${flyingCenter(airspaceInfo.end_point)}`)
- if(isSafeString(airspaceInfo.airline_width)) {
- content.push(`,宽度:${airspaceInfo.airline_width}米`)
- }
- if(isSafeString(airspaceInfo.note)) {
- content.push(`,备注: ${airspaceInfo.note}`)
- }
- let result = content.join("")
- return result;
- } else {
- let content = [];
- content.push(`${airspaceInfo.dep.addr}`)
- if(type == 1 || type == 3)
- content.push(`(E${airspaceInfo.dep.lng}, N${airspaceInfo.dep.lat})`)
- content.push(` - ${getHeight(airspaceInfo.dep.height, airspaceInfo.dep.heightStandard, type)}`);
- if (Array.isArray(airspaceInfo.passPoints)) {
- let length = airspaceInfo.passPoints.length;
- for (let i = 0; i < length; i++) {
- let obj = airspaceInfo.passPoints[i];
- if (obj.pointType == Global.pointTypes.point) {
- let pp = <PassingPointNormalLocal>obj;
- content.push(` - ${pp.addr}`)
- if(type == 1 || type == 3)
- content.push(`(E${pp.lng}, N${pp.lat})`);
- } else if (obj.pointType == Global.pointTypes.nav) {
- let pp = <PassingPointNavLocal>obj;
- content.push(` - ${pp.pointCode}`)
- if(type == 1 || type == 3)
- content.push(`(E${pp.lng}, N${pp.lat})`);
- } else {
- let pp = <PassingPointAirlineLocal>obj;
- content.push(` - ${pp.airlineCode}`);
- }
- if(obj.height) {
- content.push(` - ${getHeight(obj.height, obj.heightStandard, type)}`)
- }
- }
- }
- content.push(` - ${airspaceInfo.arrive.addr}`)
- if(type == 1 || type == 3)
- content.push(`(E${airspaceInfo.arrive.lng}, N${airspaceInfo.arrive.lat})`);
- if(airspaceInfo.airlineWidth) {
- content.push(`,宽度:${airspaceInfo.airlineWidth}米`)
- }
- if (airspaceInfo.note)
- content.push(`,备注:${airspaceInfo.note}`)
- return content.join('');
- }
- }
- export function polygonContent(airspaceInfo: AirspaceInfoPolygon, type=3): string {
- if(type == 5)
- return getAirspaceName(airspaceInfo)
- if('airspace_name' in airspaceInfo) {
- let res = []
- let points = airspaceInfo.points
- for (let i = 0; i < points.length; i++) {
- let c = `${points[i].addr ? points[i].addr : ''}`
- if(type == 1 || type == 3)
- c += `(E${latLngDecimalToDegrees(points[i].lng)}, N${latLngDecimalToDegrees(points[i].lat)})`;
- res.push(c)
- }
- let content = [res.join('、')]
- content.push(`${airspaceInfo.points.length}点连线范围内`)
- content.push(`,${getHeight(airspaceInfo.altitude, airspaceInfo.unit, type)}`)
- if(isSafeString(airspaceInfo.note)) {
- content.push(`,备注:${airspaceInfo.note}`)
- }
- return content.join('');
- } else {
- let content = [];
- let length = airspaceInfo.polygonPoints.length;
- for (let i = 0; i < length; i++) {
- let obj = airspaceInfo.polygonPoints[i];
- let c = `${obj.addr ? obj.addr : ''}`
- if(type == 1 || type == 3)
- c += `(E${obj.lng}, N${obj.lat})`
- content.push(c)
- }
- let cc = content.join('、') + `${length}点连线范围内`
- cc += `,${getHeight(airspaceInfo.height, airspaceInfo.heightStandard, type)}`
- if (airspaceInfo.note)
- cc += `,备注:${airspaceInfo.note}`
- return cc;
- }
- }
- export {latLngDegreesToDecimal, latLngDecimalToDegrees}
|