    import * as turf from '@turf/turf'
    import {
      Point,
      Polygon,
      LineString,
      MultiLineString,
      SpatialReference
    } from '../../base/geometry'
    import GeometryEngine from '../../base/geometry/GeometryEngine'
    import { Projection } from '../../base'
    import { defaultValue } from '../../util'
    /**
     * 草图捕捉工具类
     * @class SketchPolygonDrawTool
     * @moduleEX SketchEditorModule
     * @param {Object} options 构造参数
     * @param {Object}  [options.pixelTolerance]  容差（像素单位）
     * @param {Object}  [options.tolerance]  容差（米单位）
     * @param {Object}  [options.isSnapVertex]  是否自动捕捉顶点
     * @param {Object}  [options.isSnapVertexInLine]  是否自动捕捉线上的点
     * @param {Object}  [options.isSnapPerpendicular]  是否自动捕捉垂点
     * @param {Object}  [options.isSnapParallel]  是否自动捕捉水平交点
     */

    class SketchSnappingTool {
      constructor(options) {
        /**
         * 像素容差
         * @member {Number} SketchSnappingTool.prototype.pixelTolerance
         */
        this.pixelTolerance = 10
        /**
         * 容差（米单位）
         * @member {Number} SketchSnappingTool.prototype.tolerance
         */
        this.tolerance = 5
        /**
         *斜率容差
         * @member {Number} SketchSnappingTool.prototype.toleranceSlope
         */
        this.toleranceSlope = 0.02
        /**
         *是否自动捕捉顶点
         * @member {Boolean} SketchSnappingTool.prototype.isSnapVertex
         */
        this.isSnapVertex = false
        /**
         *是否自动捕捉顶点重合
         * @member {Boolean} SketchSnappingTool.prototype.isSnapVertexCoincident
         */
        this.isSnapVertexCoincident = defaultValue(
          options.isSnapVertexCoincident,
          false
        )
        /**
         *是否自动捕捉线上的点
         * @member {Boolean} SketchSnappingTool.prototype.isSnapVertexInLine
         */
        this.isSnapVertexInLine = defaultValue(options.isSnapVertexInLine, false)
        /**
         *是否自动捕捉垂线垂点
         * @member {Boolean} SketchSnappingTool.prototype.isSnapPerpendicular
         */
        this.isSnapPerpendicular = defaultValue(options.isSnapPerpendicular, false)
        /**
         *是否自动捕捉平行线
         * @member {Boolean} SketchSnappingTool.prototype.isSnapParallel
         */
        this.isSnapParallel = defaultValue(options.isSnapParallel, false)
        /**
         *是否捕捉正在绘制的图形的边界
         * @member {Boolean} SketchSnappingTool.prototype.snapSketchGeometry
         */
        this.snapSketchGeometry = defaultValue(options.snapSketchGeometry, false)

        this._view = defaultValue(options.view, null)
      }

      setSnapOption(snapOption) {
        this.isSnapVertexCoincident =
          snapOption.isSnapVertexCoincident !== undefined
            ? snapOption.isSnapVertexCoincident
            : this.isSnapVertexCoincident
        this.isSnapVertexInLine =
          snapOption.isSnapVertexInLine !== undefined
            ? snapOption.isSnapVertexInLine
            : this.isSnapVertexInLine
        this.isSnapParallel =
          snapOption.isSnapParallel !== undefined
            ? snapOption.isSnapParallel
            : this.isSnapParallel
        this.isSnapPerpendicular =
          snapOption.isSnapPerpendicular !== undefined
            ? snapOption.isSnapPerpendicular
            : this.isSnapPerpendicular
        this.snapSketchGeometry =
          snapOption.snapSketchGeometry !== undefined
            ? snapOption.snapSketchGeometry
            : this.snapSketchGeometry
      }

      /**
       * 绘制时捕捉
       * @param {Point} targetPoint 捕获结果
       * @param {LineString} targetLine 捕获结果
       * @param {Array} pointArray 被捕获的面端点数组
       * @param {Array} lineSlopes 被捕获的面线段斜率
       * @return {Object} 捕获结果
       */
      snapGeometries(targetPoint, moveLine, geometries, tolerance) {
        let coordinateArray
        const snapResult = {}
        const coincidentPoints = []
        let pointInLines = []
        let parallelLines = []
        let perpendicularLines = []
        geometries.forEach((geometry) => {
          if (geometry instanceof Polygon) {
            coordinateArray = geometry.coordinates[0]
          } else if (geometry instanceof LineString) {
            coordinateArray = geometry.coordinates
          } else if (geometry instanceof Point) {
            coordinateArray = [geometry.coordinates]
          }
          const result = this.drawingSnap(
            targetPoint,
            moveLine,
            coordinateArray,
            tolerance
          )
          if (result.coincidentPoint) {
            coincidentPoints.push(result.coincidentPoint)
          }
          if (result.pointInLines) {
            pointInLines = pointInLines.concat(result.pointInLines)
          }
          if (result.parallelLines) {
            parallelLines = parallelLines.concat(result.parallelLines)
          }
          if (result.perpendicularLines) {
            perpendicularLines = perpendicularLines.concat(
              result.perpendicularLines
            )
          }
        })
        snapResult.coincidentPoint = this._getBestResult(
          coincidentPoints,
          targetPoint
        )
        snapResult.pointInLine = this._getBestResult(pointInLines, targetPoint)
        snapResult.parallelLine = this._getBestResult(parallelLines, targetPoint)
        snapResult.perpendicularLine = this._getBestResult(
          perpendicularLines,
          targetPoint
        )
        // 同时满足点在线上和平行
        if (snapResult.pointInLine && snapResult.parallelLine) {
          let realPoint = this.getLineCrossPoint(
            snapResult.pointInLine.line,
            new LineString({
              coordinates: [
                moveLine.coordinates[0],
                snapResult.parallelLine.realPoint.coordinates
              ],
              spatialReference: targetPoint.spatialReference
            })
          )
          if (realPoint) {
            if (targetPoint.coordinates.length === 3) {
              const hight = this._getHight()
              realPoint = new Point({
                coordinates: [...realPoint.coordinates, hight],
                spatialReference: targetPoint.spatialReference
              })
            }
            snapResult.inLineAndParallel = {
              realPoint,
              lines: [snapResult.pointInLine.line, snapResult.parallelLine.line],
              symbolGeometry: snapResult.parallelLine.symbolGeometry
            }
          }
        }
        if (snapResult.pointInLine && snapResult.perpendicularLine) {
          let realPoint = this.getLineCrossPoint(
            snapResult.pointInLine.line,
            new LineString({
              coordinates: [
                moveLine.coordinates[0],
                snapResult.perpendicularLine.realPoint.coordinates
              ],
              spatialReference: targetPoint.spatialReference
            })
          )
          if (realPoint) {
            if (targetPoint.coordinates.length === 3) {
              const hight = this._getHight()
              realPoint = new Point({
                coordinates: [...realPoint.coordinates, hight],
                spatialReference: targetPoint.spatialReference
              })
            }
            snapResult.inLineAndPerpendicular = {
              realPoint,
              lines: [
                snapResult.pointInLine.line,
                snapResult.perpendicularLine.line
              ],
              symbolGeometry: snapResult.perpendicularLine.symbolGeometry
            }
          }
        }
        return snapResult
      }

      getLineCrossPoint(line1, line2) {
        const point1 = {
          x: line1.coordinates[0][0],
          y: line1.coordinates[0][1]
        }
        const point2 = {
          x: line1.coordinates[1][0],
          y: line1.coordinates[1][1]
        }
        const point3 = {
          x: line2.coordinates[0][0],
          y: line2.coordinates[0][1]
        }
        const point4 = {
          x: line2.coordinates[1][0],
          y: line2.coordinates[1][1]
        }
        const x =
          ((point3.x - point4.x) * (point2.x * point1.y - point1.x * point2.y) -
            (point1.x - point2.x) * (point4.x * point3.y - point3.x * point4.y)) /
          ((point3.x - point4.x) * (point1.y - point2.y) -
            (point1.x - point2.x) * (point3.y - point4.y))
        const y =
          ((point3.y - point4.y) * (point2.y * point1.x - point1.y * point2.x) -
            (point1.y - point2.y) * (point4.y * point3.x - point3.y * point4.x)) /
          ((point3.y - point4.y) * (point1.x - point2.x) -
            (point1.y - point2.y) * (point3.x - point4.x))
        let crossPoint = undefined
        if (
          !isNaN(x) &&
          !isNaN(y) &&
          x <= Math.max(point3.x, point4.x) &&
          x >= Math.min(point3.x, point4.x) &&
          y <= Math.max(point3.y, point4.y) &&
          y >= Math.min(point3.y, point4.y)
        ) {
          crossPoint = new Point({
            coordinates: [x, y],
            spatialReference: line1.spatialReference
          })
        }
        return crossPoint
      }

      drawingSnap(targetPoint, targetLine, pointArray, tolerance) {
        this.tolerance = tolerance
        const spatialReference = targetLine.spatialReference
        targetPoint = this._convertReference(targetPoint)
        targetLine = this._convertReference(targetLine)
        const snapGeometry = this.getSnapGeometryByPointArray(
          pointArray,
          spatialReference
        )
        const snapResult = {}
        if (this.isSnapVertexCoincident) {
          // 捕捉顶点重合
          snapResult.coincidentPoint = this.pointCoincident(
            targetPoint,
            snapGeometry.points,
            spatialReference
          )
        }
        if (this.isSnapVertexInLine) {
          // 捕捉点在线上
          if (!snapResult.coincidentPoint) {
            snapResult.pointInLines = this.getPointInLines(
              targetPoint,
              snapGeometry.lines,
              spatialReference
            )
          }
        }
        if (this.isSnapParallel) {
          // 捕捉平行线
          snapResult.parallelLines = this.getParallelLine(
            targetPoint,
            targetLine,
            snapGeometry.lines,
            spatialReference
          )
        }
        if (this.isSnapPerpendicular) {
          // 捕捉垂线垂点
          snapResult.perpendicularLines = this.getPerpendicularLine(
            targetPoint,
            targetLine,
            snapGeometry.lines,
            spatialReference
          )
        }
        return snapResult
      }

      _getBestResult(resultItem, targetPoint) {
        let bestItem = undefined
        let minDistance = 0
        resultItem.forEach((item, i) => {
          const distance = GeometryEngine.distance(item.realPoint, targetPoint)
          if (i === 0) {
            bestItem = item
            minDistance = distance
          } else {
            if (distance < minDistance) {
              minDistance = distance
              bestItem = item
            }
          }
        })
        return bestItem
      }

      getSnapGeometryByPointArray(pointArray, spatialReference) {
        const points = []
        const lines = []
        pointArray.forEach((coord, index) => {
          const point = this._convertReference(
            new Point({
              coordinates: coord,
              spatialReference
            })
          )
          points.push(point)
          if (index > 0) {
            const line = this._convertReference(
              new LineString({
                coordinates: [pointArray[index - 1], pointArray[index]],
                spatialReference
              })
            )
            lines.push(line)
          }
        })
        return { points, lines }
      }

      _convertReference(geometry) {
        if (!geometry.isWSG48) {
          let newGeometry = geometry.clone()
          newGeometry = Projection.project(
            newGeometry,
            new SpatialReference('EPSG:4326')
          )
          return newGeometry
        } else {
          return geometry
        }
      }

      getDistance(point1, point2) {
        const distance = turf.distance(turf.point(point1), turf.point(point2), {
          units: 'kilometers'
        })
        return distance * 1000
      }

      /**
       * 两点是否重合
       * @param {Point} targetPoint
       * @param {Array} points
       */
      pointCoincident(targetPoint, points) {
        let containPoint = undefined
        const targetScreenPoint = this._view.toScreen(targetPoint)
        for (let i = 0; i < points.length; i++) {
          const screenPoint = this._view.toScreen(points[i])
          if (
            Math.sqrt(
              Math.pow(targetScreenPoint.x - screenPoint.x, 2) +
                Math.pow(targetScreenPoint.y - screenPoint.y, 2)
            ) <= this.pixelTolerance
          ) {
            if (
              targetPoint.coordinates.length === 3 &&
              points[i].coordinates.length < 3
            ) {
              containPoint = new Point({
                coordinates: [...points[i].coordinates, this._getHight()],
                spatialReference: this._getHight().spatialReference
              })
            } else {
              containPoint = points[i]
            }
            break
          }
        }
        return containPoint ? { realPoint: containPoint } : undefined
      }

      /**
       *捕获目标点所在在多个被捕获的直线上，返回被捕获的的直线
       * @param {Point} targetPoint
       * @param {Array} lines
       * @return {Object} 被捕获的的直线对象
       */
      getPointInLines(targetPoint, lines, spatialReference) {
        const containLines = []
        lines.forEach((line) => {
          // 计算容差范围内点到线的垂点
          const inLineResult = this.getPerpendicularPoint(
            targetPoint,
            new Point({
              coordinates: line.coordinates[0],
              spatialReference
            }),
            new Point({
              coordinates: line.coordinates[1],
              spatialReference
            })
          )
          if (inLineResult) {
            line = Projection.project(line, spatialReference)
            containLines.push({
              line,
              realPoint: inLineResult.realPoint,
              deltaTolerance: inLineResult.deltaTolerance
            })
          }
        })
        return containLines
      }

      // 根据点坐标和直线，获取垂足坐标
      getPerpendicularPoint(targetPoint, targetLinePoint1, targetLinePoint2) {
        // const point = this._view.toScreen(targetPoint)
        // const linePoint1 = this._view.toScreen(targetLinePoint1)
        // const linePoint2 = this._view.toScreen(targetLinePoint2)
        const point = {
          x: targetPoint.coordinates[0],
          y: targetPoint.coordinates[1]
        }
        const linePoint1 = {
          x: targetLinePoint1.coordinates[0],
          y: targetLinePoint1.coordinates[1]
        }
        const linePoint2 = {
          x: targetLinePoint2.coordinates[0],
          y: targetLinePoint2.coordinates[1]
        }
        let perpendicularPoint
        let x
        let y
        if (linePoint2.x !== linePoint1.x) {
          const k = (linePoint2.y - linePoint1.y) / (linePoint2.x - linePoint1.x)
          x =
            (k * k * linePoint1.x + k * (point.y - linePoint1.y) + point.x) /
            (k * k + 1)
          y = k * (x - linePoint1.x) + linePoint1.y
        } else {
          x =
            (targetLinePoint1.coordinates[0] + targetLinePoint2.coordinates[0]) / 2
          y = targetPoint.coordinates[1]
        }
        if (targetPoint.coordinates.length === 3) {
          const hight = this._getHight()
          perpendicularPoint = new Point({
            coordinates: [x, y, hight],
            spatialReference: targetPoint.spatialReference
          })
        } else {
          perpendicularPoint = new Point({
            coordinates: [x, y],
            spatialReference: targetPoint.spatialReference
          })
        }
        const endScreenPoint = this._view.toScreen(perpendicularPoint)
        const startScreenPoint = this._view.toScreen(targetPoint)
        const deltaPixel = Math.sqrt(
          Math.pow(startScreenPoint.x - endScreenPoint.x, 2) +
            Math.pow(startScreenPoint.y - endScreenPoint.y, 2)
        )
        const valid = deltaPixel <= this.pixelTolerance
        return valid
          ? {
              realPoint: perpendicularPoint,
              deltaTolerance: deltaPixel
            }
          : null
      }

      /**
       * 获取目标直线的平行线捕获结果。判断目标直线与被捕获的直线是否平行，返回平行线结果
       * @private
       * @param {Point} targetPoint
       * @param {LineString} targetLine 目标直线
       * @param {Array} lines 被捕获的直线对象
       * @param {Array} lineSlopes 被捕获的直线斜率
       * @return {Object} 平行线捕获结果
       */
      getParallelLine(targetPoint, targetLine, lines, spatialReference) {
        const parallelLines = []
        if (lines && lines.length > 0) {
          lines.forEach((line) => {
            const linePoint1 = new Point({
              coordinates: line.coordinates[0],
              spatialReference
            })
            const linePoint2 = new Point({
              coordinates: line.coordinates[1],
              spatialReference
            })
            const parallelResult = this.getParallelPoint(
              targetPoint,
              new Point({
                coordinates: targetLine.coordinates[0],
                spatialReference
              }),
              linePoint1,
              linePoint2,
              'parallel'
            )
            if (parallelResult) {
              const realPoint = parallelResult.realPoint
              const symbolGeometry = this._getParallelSymbolGeometry(
                linePoint1,
                linePoint2
              )
              parallelLines.push({
                line,
                symbolGeometry,
                realPoint,
                deltaTolerance: parallelResult.deltaTolerance
              })
            }
          })
        }
        return parallelLines.length > 0 ? parallelLines : undefined
      }

      // 计算平行或垂直时的标准坐标
      getParallelPoint(
        targetPoint,
        targetLastPoint,
        targetLinePoint1,
        targetLinePoint2,
        type = 'parallel'
      ) {
        // const point = this._view.toScreen(targetPoint)
        // const lastPoint = this._view.toScreen(targetLastPoint)
        // const linePoint1 = this._view.toScreen(targetLinePoint1)
        // const linePoint2 = this._view.toScreen(targetLinePoint2)
        const point = {
          x: targetPoint.coordinates[0],
          y: targetPoint.coordinates[1]
        }
        const lastPoint = {
          x: targetLastPoint.coordinates[0],
          y: targetLastPoint.coordinates[1]
        }
        const linePoint1 = {
          x: targetLinePoint1.coordinates[0],
          y: targetLinePoint1.coordinates[1]
        }
        const linePoint2 = {
          x: targetLinePoint2.coordinates[0],
          y: targetLinePoint2.coordinates[1]
        }
        // 计算point,lastPoint的长度
        const distance = Math.sqrt(
          Math.pow(point.x - lastPoint.x, 2) + Math.pow(point.y - lastPoint.y, 2)
        )
        // 计算点（point）到直线（lineP1、lineP2）的距离
        const isTolerance = function (point, lineP1, lineP2, pixelTolerance) {
          const pointToLineD =
            Math.abs(
              (lineP2.x - lineP1.x) * (point.x - lineP1.x) +
                (lineP2.y - lineP1.y) * (point.y - lineP1.y)
            ) /
            Math.sqrt(
              Math.pow(lineP2.x - lineP1.x, 2) + Math.pow(lineP2.y - lineP1.y, 2)
            )
          return pointToLineD <= pixelTolerance
        }

        let k
        let kValid = true
        let x
        let y
        if (type === 'parallel') {
          if (linePoint2.x === linePoint1.x) {
            kValid = false
            x = lastPoint.x
            if (point.y > lastPoint.y) {
              y = lastPoint.y + distance
            } else {
              y = lastPoint.y - distance
            }
          } else {
            k = (linePoint2.y - linePoint1.y) / (linePoint2.x - linePoint1.x)
          }
        } else if (type === 'perpendicular') {
          if (linePoint2.y === linePoint1.y) {
            kValid = false
            y = lastPoint.y
            if (point.x > lastPoint.x) {
              x = lastPoint.x + distance
            } else {
              x = lastPoint.x - distance
            }
          } else {
            k = -(linePoint2.x - linePoint1.x) / (linePoint2.y - linePoint1.y)
          }
        }
        if (kValid) {
          const b = lastPoint.y - k * lastPoint.x
          // 第二步：求得在直线y=kx+b上，距离当前坐标距离为L的某点
          const H = Math.pow(k, 2) + 1 // A=k^2+1;
          const I = 2 * ((b - lastPoint.y) * k - lastPoint.x) // B=2[(b-y0)k-x0];
          const J =
            Math.pow(b - lastPoint.y, 2) +
            Math.pow(lastPoint.x, 2) -
            Math.pow(distance, 2)
          const Dx1 = (-I + Math.sqrt(Math.pow(I, 2) - 4 * H * J)) / (2 * H)
          const Dx2 = (-I - Math.sqrt(Math.pow(I, 2) - 4 * H * J)) / (2 * H)
          x = 0 // 最后确定是在已知两点之间的某点
          if ((point.x - lastPoint.x) * (Dx1 - lastPoint.x) > 0) {
            x = Dx1
          } else {
            x = Dx2
          }
          y = k * x + b
          // parallelPoint = this._view.toMap({ x, y })
        }
        // 临时
        if (isNaN(x) || isNaN(x)) {
          return null
        }
        let parallelPoint
        if (targetPoint.coordinates.length === 3) {
          const hight = this._getHight()
          parallelPoint = new Point({
            coordinates: [x, y, hight],
            spatialReference: point.spatialReference
          })
        } else {
          parallelPoint = new Point({
            coordinates: [x, y],
            spatialReference: point.spatialReference
          })
        }

        // const deltaPixel = Math.sqrt(
        //   Math.pow(point.x - x, 2) + Math.pow(point.y - y, 2)
        // )
        const endScreenPoint = this._view.toScreen(parallelPoint)
        const startScreenPoint = this._view.toScreen(targetPoint)
        const deltaPixel = Math.sqrt(
          Math.pow(startScreenPoint.x - endScreenPoint.x, 2) +
            Math.pow(startScreenPoint.y - endScreenPoint.y, 2)
        )
        const valid = deltaPixel <= this.pixelTolerance
        // isTolerance(point, lastPoint, { x, y }, this.pixelTolerance)
        return valid
          ? {
              realPoint: parallelPoint,
              deltaTolerance: deltaPixel
            }
          : null
      }

      /**
       * 获取地理点高度
       * @private
       * @param {Point} point
       * @return {Number} 高度
       */
      _getHight() {
        return 0
      }

      /**
       * 获取描述平行线的特殊符号
       * @private
       * @param {LineString} targetLine
       * @param {Array} lines 被捕获的直线对象
       * @return {Object} 平行线的特殊符号对象
       */
      _getParallelSymbolGeometry(linePoint1, linePoint2) {
        const scale = 1 / 4
        const panPixel = this.pixelTolerance / 2
        const linePointScreen1 = this._view.toScreen(linePoint1)
        const linePointScreen2 = this._view.toScreen(linePoint2)

        const lineScalePoint1 = {
          x:
            ((1 - scale) / 2) * (linePointScreen2.x - linePointScreen1.x) +
            linePointScreen1.x,
          y:
            ((1 - scale) / 2) * (linePointScreen2.y - linePointScreen1.y) +
            linePointScreen1.y
        }
        const lineScalePoint2 = {
          x:
            ((1 + scale) / 2) * (linePointScreen2.x - linePointScreen1.x) +
            linePointScreen1.x,
          y:
            ((1 + scale) / 2) * (linePointScreen2.y - linePointScreen1.y) +
            linePointScreen1.y
        }

        let symbol1ScreenPoint1
        let symbol1ScreenPoint2
        let symbol2ScreenPoint1
        let symbol2ScreenPoint2
        if (lineScalePoint2.x === lineScalePoint1.x) {
          symbol1ScreenPoint1 = {
            x: lineScalePoint1.x + panPixel,
            y: lineScalePoint1.y
          }
          symbol1ScreenPoint2 = {
            x: lineScalePoint2.x + panPixel,
            y: lineScalePoint2.y
          }
          symbol2ScreenPoint1 = {
            x: lineScalePoint1.x - panPixel,
            y: lineScalePoint1.y
          }
          symbol2ScreenPoint2 = {
            x: lineScalePoint2.x - panPixel,
            y: lineScalePoint2.y
          }
        } else if (lineScalePoint2.y === lineScalePoint1.y) {
          symbol1ScreenPoint1 = {
            x: lineScalePoint1.x,
            y: lineScalePoint1.y + panPixel
          }
          symbol1ScreenPoint2 = {
            x: lineScalePoint2.x,
            y: lineScalePoint2.y + panPixel
          }
          symbol2ScreenPoint1 = {
            x: lineScalePoint1.x,
            y: lineScalePoint1.y - panPixel
          }
          symbol2ScreenPoint2 = {
            x: lineScalePoint2.x,
            y: lineScalePoint2.y - panPixel
          }
        } else {
          const symbolK =
            -(lineScalePoint2.x - lineScalePoint1.x) /
            (lineScalePoint2.y - lineScalePoint1.y)
          // const symbolK = -1 / k
          const symbolAngle = Math.atan(symbolK)
          const translatedPoint = function (point, angle, panPixel) {
            const symbol1Center = {
              x: Math.cos(angle) * panPixel + point.x,
              y: Math.sin(angle) * panPixel + point.y
            }
            return symbol1Center
          }
          symbol1ScreenPoint1 = translatedPoint(
            lineScalePoint1,
            symbolAngle,
            panPixel
          )
          symbol1ScreenPoint2 = translatedPoint(
            lineScalePoint2,
            symbolAngle,
            panPixel
          )
          symbol2ScreenPoint1 = translatedPoint(
            lineScalePoint1,
            symbolAngle,
            -panPixel
          )
          symbol2ScreenPoint2 = translatedPoint(
            lineScalePoint2,
            symbolAngle,
            -panPixel
          )
        }
        const symbol1point1 = this._view.toMap(symbol1ScreenPoint1)
        const symbol1point2 = this._view.toMap(symbol1ScreenPoint2)
        const symbol2point1 = this._view.toMap(symbol2ScreenPoint1)
        const symbol2point2 = this._view.toMap(symbol2ScreenPoint2)
        return new MultiLineString({
          coordinates: [
            [symbol1point1.coordinates, symbol1point2.coordinates],
            [symbol2point1.coordinates, symbol2point2.coordinates]
          ]
        })
      }

      _getParallelSymbolGeometry0(targetLine, line) {
        const scale = 1 / 4
        const pan = this.tolerance / 1000
        const translatedLine = function (line, scale, pan) {
          const polyline = turf.lineString(line.coordinates)
          const translatedPolyline = turf.transformTranslate(polyline, pan, 180)
          const scaledLine = turf.transformScale(translatedPolyline, scale)
          return scaledLine.geometry.coordinates
        }
        return new MultiLineString({
          coordinates: [
            translatedLine(targetLine, scale, pan),
            translatedLine(targetLine, scale, -pan),
            translatedLine(line, scale, pan),
            translatedLine(line, scale, -pan)
          ]
        })
      }

      /**
       * 获取目标直线的垂线捕获结果
       * @private
       * @param {Point} targetPoint
       * @param {LineString} targetLine
       * @param {Array} lines 被捕获的直线对象
       * @param {Array} lineSlopes 被捕获的直线斜率
       * @return {Object} 垂线结果
       */
      getPerpendicularLine(targetPoint, targetLine, lines, spatialReference) {
        const perpendicularLines = []
        lines.forEach((line) => {
          const perpendicularResult = this.getParallelPoint(
            targetPoint,
            new Point({
              coordinates: targetLine.coordinates[0],
              spatialReference
            }),
            new Point({
              coordinates: line.coordinates[0],
              spatialReference
            }),
            new Point({
              coordinates: line.coordinates[1],
              spatialReference
            }),
            'perpendicular'
          )
          if (perpendicularResult) {
            const realPoint = perpendicularResult.realPoint
            const symbolGeometry = undefined
            // 暂时屏蔽计算垂足图形方法，方法需进一步修复
            // const symbolGeometry = this.getPerpendicularSymbolGeometry(
            //   new LineString({
            //     coordinates: [targetLine.coordinates[0], realPoint.coordinates]，
            //     spatialReference
            //   }),
            //   lines[i],
            //   realPoint
            // )
            perpendicularLines.push({
              line,
              realPoint,
              symbolGeometry,
              deltaTolerance: perpendicularResult.deltaTolerance
            })
          }
        })
        return perpendicularLines.length ? perpendicularLines : undefined
      }

      /**
       * 获取目标点到目标线的垂点对象
       * @private
       * @param {Point} targetPoint 目标点
       * @param {LineString} targetLine 目标线
       * @param {Number} lineSlope 直线斜率
       * @return {Array} 垂点坐标
       */
      _getPerpendicularPoint(targetPoint, targetLine, lineSlope) {
        const delta1 =
          targetLine.coordinates[0][1] - lineSlope * targetLine.coordinates[0][0]
        const delta2 =
          targetPoint.coordinates[1] + (1 / lineSlope) * targetPoint.coordinates[0]
        const x = ((delta2 - delta1) * lineSlope) / (lineSlope * lineSlope + 1)
        const y = (-1 / lineSlope) * x + delta2
        return [x, y]
      }

      /**
       * 获取描述垂线的特殊符号
       * @private
       * @param {LineString} targetLine
       * @param {LineString} line 被捕获的直线对象
       * @param {Point} perpendicularPoint 垂足坐标点
       * @return {Object} 垂线的特殊符号对象
       */
      getPerpendicularSymbolGeometry(targetLine, line, perpendicularPoint) {
        const linePoints1 = [
          turf.point(targetLine.coordinates[0]),
          turf.point(targetLine.coordinates[1])
        ]
        const linePoints2 = [
          turf.point(line.coordinates[0]),
          turf.point(line.coordinates[1])
        ]
        const distance1 = turf.distance(linePoints1[0], linePoints1[1]) // GeometryEngine.geodesicLength(targetLine)
        const distance2 = turf.distance(linePoints2[0], linePoints2[1]) // GeometryEngine.geodesicLength(line)
        const distance = Math.min(distance1, distance2) / 8
        perpendicularPoint = turf.point(perpendicularPoint.coordinates)
        let bearing2 = 0
        if (
          linePoints2[0].geometry.coordinates[0] ===
            perpendicularPoint.geometry.coordinates[0] &&
          linePoints2[0].geometry.coordinates[1] ===
            perpendicularPoint.geometry.coordinates[1]
        ) {
          bearing2 = turf.rhumbBearing(perpendicularPoint, linePoints2[1])
        } else {
          bearing2 = turf.rhumbBearing(perpendicularPoint, linePoints2[0])
        }
        let bearing1 = 0
        if (
          linePoints1[0].geometry.coordinates[0] ===
            perpendicularPoint.geometry.coordinates[0] &&
          linePoints1[0].geometry.coordinates[1] ===
            perpendicularPoint.geometry.coordinates[1]
        ) {
          bearing1 = turf.rhumbBearing(perpendicularPoint, linePoints1[1])
        } else {
          bearing1 = turf.rhumbBearing(perpendicularPoint, linePoints1[0])
        }
        const bearing3 = (bearing1 + bearing2) / 2
        const destination1 = turf.rhumbDestination(
          perpendicularPoint,
          distance,
          bearing1
        )
        const destination2 = turf.rhumbDestination(
          perpendicularPoint,
          distance,
          bearing2
        )
        const destination3 = turf.rhumbDestination(
          perpendicularPoint,
          distance * Math.sqrt(2),
          bearing3
        )
        const point1 = destination1.geometry.coordinates
        const point2 = destination2.geometry.coordinates
        const point3 = destination3.geometry.coordinates
        return new LineString({
          coordinates: [point1, point3, point2]
        })
      }

      /**
       * 正在测试中的方法
       * @private
       */
      getPerpendicularSymbolGeometry2(targetLine, line, perpendicularPoint) {
        let p1 = turf.point(targetLine.coordinates[0])
        if (
          targetLine.coordinates[0][0] === perpendicularPoint.coordinates[0] &&
          targetLine.coordinates[0][1] === perpendicularPoint.coordinates[1]
        ) {
          p1 = turf.point(targetLine.coordinates[1])
        }
        const p2 = turf.point(line.coordinates[0])
        const p3 = turf.point(line.coordinates[1])
        const distance1 = turf.distance(p1, perpendicularPoint)
        const distance2 = turf.distance(p2, perpendicularPoint)
        const distance3 = turf.distance(p3, perpendicularPoint)
        let distance = Math.min(distance1, distance2, distance3) / 8
        if (distance2 === 0) {
          distance = Math.min(distance1, distance3) / 8
        } else if (distance3 === 0) {
          distance = Math.min(distance1, distance2) / 8
        }
        perpendicularPoint = turf.point(perpendicularPoint.coordinates)

        const bearing1 = turf.rhumbBearing(perpendicularPoint, p1)
        const destination1 = turf.rhumbDestination(
          perpendicularPoint,
          distance,
          bearing1
        )
        const bearing2 = turf.rhumbBearing(perpendicularPoint, p2)
        const destination2 = turf.rhumbDestination(
          perpendicularPoint,
          distance,
          bearing2
        )
        const bearing3 = (bearing1 + bearing2) / 2
        const dis = distance * Math.cos(((bearing3 - bearing2) * Math.PI) / 180) * 2
        const destination3 = turf.rhumbDestination(
          perpendicularPoint,
          dis,
          bearing3
        )

        const point1 = destination1.geometry.coordinates
        const point2 = destination2.geometry.coordinates
        const point3 = destination3.geometry.coordinates
        return new LineString({
          coordinates: [point1, point3, point2]
        })
      }

      /**
       *根据垂足获取真正终点位置
       * @private
       * @param {Feature} currentPoint 当前终点
       * @param {Feature} startPoint 线段起点
       * @param {Feature} perpendicularPoint 垂点位置
       */
      getPerpendicularRealPosition(currentPoint, startPoint, perpendicularPoint) {
        let realPosition = null
        const distance = GeometryEngine.distance(startPoint, currentPoint)
        const direction = turf.rhumbBearing(
          turf.point(startPoint.coordinates),
          turf.point(perpendicularPoint.currentPoint)
        )
        realPosition = turf.rhumbDestination(startPoint, distance, direction)
          .geometry.coordinates
        return realPosition
      }

      /**
       *面和线是否相交
       */
      isPolylineCrossPolygon() {}

      /**
       *两个面是否相交
       */
      isPolygonCross() {}
    }
    export default SketchSnappingTool