Bläddra i källkod

Merge branch 'add_airline_width' into 'master'

增加线型空域宽度支持

See merge request BA/amap-shapes-generator!15
guohui.deng 7 år sedan
förälder
incheckning
c8c45ec2aa
1 ändrade filer med 128 tillägg och 17 borttagningar
  1. 128 17
      index.js

+ 128 - 17
index.js

@@ -177,7 +177,7 @@ function getLinesRouter(lineProps, lineAndMarkerStyle) {
         strokeColor = lineAndMarkerStyle.strokeColor
     }
 
-    let startPoint, passPoints, endPoint, pointTypeFix, dataType
+    let startPoint, passPoints, endPoint, pointTypeFix, dataType, airlineWidth
 
     if (lineProps.start_point) {
         dataType = 2 // 下划线模式
@@ -186,13 +186,15 @@ function getLinesRouter(lineProps, lineAndMarkerStyle) {
         passPoints = lineProps['passing_points']
         endPoint = lineProps['end_point']
         pointTypeFix = 'point_type';
+        airlineWidth = parseInt(lineProps['airline_width'], 10)
     } else {
         dataType = 1 // 驼峰模式
 
         startPoint = lineProps['dep']
         passPoints = lineProps['passPoints']
         endPoint = lineProps['arrive']
-        pointTypeFix = 'pointType'    
+        pointTypeFix = 'pointType'
+        airlineWidth = parseInt(lineProps['airlineWidth'], 10)
     }
 
     if (startPoint) {
@@ -236,16 +238,123 @@ function getLinesRouter(lineProps, lineAndMarkerStyle) {
     if (coordinates.length > 1) {
         lines.push({lineWidth, strokeColor, coordinates});
     }
+    lines = combineLines(lines)
+    if(airlineWidth > 0) {
+        // 有宽度的空域,需要线周围多画宽度的多边形
+        let polygons = processAirlineWidth(lines, airlineWidth)
+        return { lines, markers, polygons };
+    } else {
+        return { lines, markers, polygons: [] };
+    }
+}
+
+function combineLines(lines) {
+    // 合并线段,如果前后两个线段之间有交接,那就合并成一个
+    // 这样操作之后,lines 就只有不交接的线段了
+    let combinedLines = []
+    combinedLines.push(lines[0])
+    for(let i=1; i<lines.length; i++) {
+        let prevLine = lines[i-1]
+        let line = lines[i]
+        if(isLineConnect(prevLine, line)) {
+            let lastIdx = combinedLines.length-1
+            let lastLine = combinedLines[lastIdx]
+            let points = line.coordinates.slice()
+            points.splice(0, 1) //移除第一个点
+            combinedLines[lastIdx].coordinates = [... lastLine.coordinates, ...points]
+        } else {
+            combinedLines.push(line)
+        }
+    }
+    return combinedLines
+}
+
+function getFixedLatLng(point) {
+    let lat = point.latitude ? point.latitude : point.lat
+    let lng = point.longitude ? point.longitude : point.lng
+    return [lat, lng]
+}
+
+function processAirlineWidth(lines, airlineWidth) {
+    let polygons = []
+
+    for(let line of lines) {
+        let points = line.coordinates
+        let coordinates = []
+        let lastBearing = null
+        for(let i=0; i<points.length; i++) {
+            let [lat1, lng1] = getFixedLatLng(points[i])
+            let point = new LatLon(lat1, lng1)
+            let nextPoint = null
+            let bearing = lastBearing
+            if(i < points.length-1) {
+                let [lat2, lng2] = getFixedLatLng(points[i+1])
+                nextPoint = new LatLon(lat2, lng2)
+                bearing = point.bearingTo(nextPoint)
+            }
+
+            let [leftPoint, rightPoint] = getBearingPoint(point, lastBearing, bearing, airlineWidth)
+            coordinates.splice(0, 0, {lat: leftPoint.lat, lng: leftPoint.lon}) // add top
+            coordinates.push({lat: rightPoint.lat, lng: rightPoint.lon}) // add bottom
+            lastBearing = bearing
+        }
+
+        let {imageName, lineWidth, strokeColor, fillColor} = getDefaultStyle()
+        polygons.push({lineWidth, strokeColor, fillColor, coordinates});
+    }
+    return polygons
+}
+
+function getBearingPoint(point, lastBearing, bearing, airlineWidth) {
+    if(!lastBearing)
+        lastBearing = bearing
 
-    return { lines, markers };
+    let halfAngle = (180 - bearing + lastBearing)/2 // 两条线的夹角的一半
+    let rightBearing = bearing + halfAngle
+    let leftBearing = 180 + rightBearing
+
+    /* let fixAngle = Math.abs(halfAngle) > 180 ? Math.abs(halfAngle) : halfAngle
+     * let leftWidth = airlineWidth/Math.sin(fixAngle)
+     * let rightWidth = airlineWidth/Math.sin(fixAngle)
+     * console.log('width is', airlineWidth, leftWidth, rightWidth, fixAngle, halfAngle) */
+
+    let leftWidth = airlineWidth
+    let rightWidth = airlineWidth
+
+    let leftPoint = point.destinationPoint(leftWidth, leftBearing)
+    let rightPoint = point.destinationPoint(rightWidth, rightBearing)
+    return [leftPoint, rightPoint]
+}
 
+function myRound(num, digits) {
+    if(digits == null)
+        digits = 6 // 比较的精度,经纬度会被经过度分秒方式到浮点方式的转化
+
+    return Math.round(num * Math.pow(10, digits)) / Math.pow(10, digits)
+}
+
+function isLineConnect(line1, line2) {
+    // 判断 line1 的终点和 line2 的起点是否相同
+    let line1LastPoint = line1.coordinates[line1.coordinates.length -1]
+    let line2FirstPoint = line2.coordinates[0]
+
+    let [line1lat, line1lng] = getFixedLatLng(line1LastPoint)
+    let [line2lat, line2lng] = getFixedLatLng(line2FirstPoint)
+
+    if(myRound(line1lat) == myRound(line2lat)
+       && myRound(line1lng) == myRound(line2lng)) {
+        return true
+    } else {
+        return false
+    }
 }
 
-function getLinesAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
+function getLinesPolygonsAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
     let retLines = [];
     let retMarkers = [];
+    let retPolygons = [];
     if (!Array.isArray(airspaceInfos)) {
-        return { lines: retLines, markers: retMarkers };
+        return { lines: retLines, markers: retMarkers, polygons: retPolygons };
     }
     let lineStyle = setStyle('line');
     for (let i = 0; i < airspaceInfos.length; i++) {
@@ -256,22 +365,23 @@ function getLinesAndMarkers(airspaceInfos, setStyle, currentAirspaceIndex) {
         else
             airspaceTypeFix = 'airspace_type';
         if (tmpLine[airspaceTypeFix] == Global.airspaceType.line && currentAirspaceIndex != i) {
-            let { lines, markers } = getLinesRouter(tmpLine, lineStyle);
+            let { lines, markers, polygons } = getLinesRouter(tmpLine, lineStyle);
             retMarkers.push(...markers);
             retLines.push(...lines);
+            retPolygons.push(...polygons)
         }
     }
 
-    return { lines: retLines, markers: retMarkers };
+    return { lines: retLines, markers: retMarkers, polygons: retPolygons };
 }
 
 
-function getLineAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) {
+function getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle, currentAirspaceIndex) {
     return createSelector(
         airspaceInfos,
         () => setStyle,
         currentAirspaceIndex,
-        getLinesAndMarkers
+        getLinesPolygonsAndMarkers
     );
 }
 
@@ -404,13 +514,14 @@ function getLineSelector(lineAndMarker) {
     );
 }
 
-function getPolygons(polygonAndMarkers) {
-    return polygonAndMarkers.polygons;
+function getPolygons(polygonAndMarkers, linePolygonsAndMarkers) {
+    return [...polygonAndMarkers.polygons, ...linePolygonsAndMarkers.polygons];
 }
 
-function getPolygonSelector(polygonAndMarkers) {
+function getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers) {
     return createSelector(
         polygonAndMarkers,
+        linePolygonsAndMarkers,
         getPolygons
     );
 }
@@ -426,12 +537,12 @@ let setStyle = (style) => {
 export function getShapesSelector(airspaceInfos, style, currentAirspaceIndex) {
     currentAirspaceIndex = currentAirspaceIndex ? currentAirspaceIndex : () => -1;
     let circles = getCircleSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
-    let lineAndMarkers = getLineAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
-    let lines = getLineSelector(lineAndMarkers);
+    let linePolygonsAndMarkers = getLinePolygonsAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
+    let lines = getLineSelector(linePolygonsAndMarkers);
     let polygonAndMarkers = getPolygonAndMarkerSelector(airspaceInfos, setStyle(style), currentAirspaceIndex);
-    let polygons = getPolygonSelector(polygonAndMarkers);
-    let markers = getMarkerSelector(polygonAndMarkers, lineAndMarkers);
-    let regionPoints = getRegionPointsSelector(circles, lineAndMarkers, polygonAndMarkers);
+    let polygons = getPolygonSelector(polygonAndMarkers, linePolygonsAndMarkers);
+    let markers = getMarkerSelector(polygonAndMarkers, linePolygonsAndMarkers);
+    let regionPoints = getRegionPointsSelector(circles, linePolygonsAndMarkers, polygonAndMarkers);
     return {
         markers,
         circles,