    import { Feature, ViewEventType, Projection } from '../../base'
    import { Polygon, Point, LineString } from '../../base/geometry'
    import SketchBaseDrawTool from './SketchBaseDrawTool'
    import Color from '../../base/Color'
    import SketchPointDrawTool from './SketchPointDrawTool'
    import SketchPolygonDrawTool from './SketchPolygonDrawTool'
    import SketchStyle from './SketchStyle'
    import { SimpleLineSymbol } from '../../base/symbol'
    /**
     * 面绘图工具类
     * @class SketchPolylineDrawTool
     * @moduleEX SketchEditorModule
     * @extends SketchBaseDrawTool
     * @param {Object} options 构造参数
     * @param {MapView|SceneView}  [options.view]  地图视图对象
     * @param {GraphicsLayer}  [options.layer]  草图图层管对象
     * @param {SketchStyle}  [options.sketchStyle]  草图符号
     */
    class SketchPolylineDrawTool extends SketchBaseDrawTool {
      constructor(options) {
        super(options)
        // 初始化事件
        this._initEvent()
        this._drawTools = [this]
        this._otherDrawTools = []
      }

      /**
       * @description 初始化事件
       * @private
       */
      _initEvent() {
        this._processEvent = this._processEvent.bind(this)
        this.on('pan', this._processEvent)
        this.on('vertexScale', this._processEvent)
        this.on('midVertexScale', this._processEvent)
        this.on('vertexMove', this._processEvent)
        this.on('midVertexAdd', this._processEvent)
      }

      /**
       * @description 鼠标绘制图形：鼠标单击绘制区的一个顶点；鼠标移动，区图形随鼠标位置变动；鼠标双击，完成区图形绘制。
       */
      drawFeature() {
        // 屏蔽地图默认双击事件
        this.view._mapActionControl('double-click-zoom', false)
        // 控制鼠标移动事件频率
        const timer = null
        // 鼠标点击两次以上，即有两个以上的点构成区时，触发鼠标移动时逻辑
        let isStartDrawing = false
        let afterClick = false
        // 鼠标移动过程中，控制鼠标移动逻辑触发次数
        let moving = false
        // 当前正在绘制的图形对象
        let feature = null
        let pixelCoords = []
        // 绘制过程中所有的端点
        let polylineSpots = []
        // 绘制过程中所有所有线段的斜率
        const polylineSpotSlopes = []
        // timer判断是单击事件、双击事件
        const clickTimer = null
        // 区分单击、双击事件，若为双击事件，则阻止单击事件逻辑触发
        // let preventClick = false
        let lastAction = ''
        // 获取两点斜率
        const getSlope = function (point1, point2) {
          return (point1[1] - point2[1]) / (point1[0] - point2[0])
        }
        // 捕获到的坐标点
        let snapPoint = null
        // 处理鼠标点击事件。点击后渲染端点图形，渲染区图形
        const handlerClick = (options) => {
          // clickTimer = setTimeout(() => {
          //   preventClick = false
          // }, 300)
          // // 判断是否为单击事件
          // if (preventClick) return
          if (!options || !options.x || !options.y) return
          clearTimeout(timer)
          this._editMode = 3
          const pixelCoord = { x: options.x, y: options.y }
          let geoCoord = null
          if (!snapPoint) {
            // 如果没有捕获结果，则此时坐标点为屏幕地理坐标
            geoCoord = this.view.toMap({ x: pixelCoord.x, y: pixelCoord.y })
            // if (this._hight) {
            //   geoCoord = new Point({
            //     coordinates: [
            //       geoCoord.coordinates[0],
            //       geoCoord.coordinates[1],
            //       this._hight
            //     ],
            //     spatialReference: this._spatialReference
            //   })
            // }
          } else {
            // 如果有捕获结果，则此时坐标点选取捕获的坐标点
            geoCoord = snapPoint
          }
          if (polylineSpots.length === 0) {
            pixelCoords.push(pixelCoord)
            polylineSpots.push(geoCoord.coordinates)
          } else if (polylineSpots.length === 1) {
            pixelCoords.push(pixelCoord)
            polylineSpots.push(geoCoord.coordinates)
            feature = this._getFeature()
            feature.geometry._pixelCoords = pixelCoords
            feature.geometry.coordinates = polylineSpots
            // 保存当前编辑中的geometry
            this._polylineGeometry = feature
          } else {
            pixelCoords[pixelCoords.length - 1] = pixelCoord
            polylineSpots[polylineSpots.length - 1] = geoCoord.coordinates
            feature.geometry._pixelCoords = pixelCoords
            feature.geometry.coordinates = polylineSpots
            // feature.geometry.coordinates[feature.geometry.coordinates.length - 1] =
            //   geoCoord.coordinates
          }
          // 临时解决，move事件有可能发生在两个click事件之间，导致多绘制一个点
          if (
            lastAction === 'move' &&
            polylineSpots[polylineSpots.length - 1][0] ===
              polylineSpots[polylineSpots.length - 2][0] &&
            polylineSpots[polylineSpots.length - 1][1] ===
              polylineSpots[polylineSpots.length - 2][1]
          ) {
            polylineSpots.splice(polylineSpots.length - 1)
          }

          const pointDrawTool = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            _parent: this,
            sketchStyle: this.sketchStyle
          })
          pointDrawTool.addFeature(geoCoord)
          const vertexGraphic = pointDrawTool.sketchStage.entityGraphic
          this.sketchStage.entityGraphic = feature
          this.sketchStage.vertexGraphics.push(vertexGraphic)

          // 在polyline中更新所有图形
          if (feature) {
            isStartDrawing = true
            afterClick = isStartDrawing
          }
          // preventClick = true
          // 计算线段斜率
          if (polylineSpots.length > 1) {
            polylineSpotSlopes.push(
              getSlope(
                polylineSpots[polylineSpots.length - 1],
                polylineSpots[polylineSpots.length - 2]
              )
            )
          }
          // this.startTime = new Date().getTime()
          lastAction = 'click'
          // 发送绘制一个顶点完成事件
          this.fire(
            'drawn-vertex',
            { geometry: pointDrawTool.sketchStage.entityGraphic },
            self
          )
        }
        // 处理平移时，鼠标移动时逻辑。鼠标移动时根据鼠标坐标实时更新区图形。
        let isFirstAdd = true
        const handlerMove = (options) => {
          if (!options || !options.x || !options.y) return
          if (!isStartDrawing || moving) return
          clearTimeout(timer)
          moving = true
          // 清除捕获效果（上一次）
          if (this.sketchStage.snapGraphics.length > 0) {
            this.sketchStage.snapGraphics.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this.sketchStage.snapGraphics = []
          }

          const pixelCoord = { x: options.x, y: options.y }
          const geoCoord = this.view.toMap({ x: pixelCoord.x, y: pixelCoord.y })
          // if (this._hight) {
          //   geoCoord = new Point({
          //     coordinates: [
          //       geoCoord.coordinates[0],
          //       geoCoord.coordinates[1],
          //       this._hight
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // }

          this.endTime = new Date().getTime()
          if (afterClick) {
            pixelCoords[pixelCoords.length] = pixelCoord
            polylineSpots[polylineSpots.length] = geoCoord.coordinates
            afterClick = false
          } else {
            pixelCoords[pixelCoords.length - 1] = pixelCoord
            polylineSpots[polylineSpots.length - 1] = geoCoord.coordinates
          }
          this.sketchStage.entityGraphic = feature

          // 鼠标移动时，去捕获重合点、点在线上、平行线、垂直线
          snapPoint = this.getSnapGraphics(
            geoCoord,
            polylineSpots,
            polylineSpotSlopes
          )
          if (snapPoint) {
            polylineSpots[polylineSpots.length - 1] = snapPoint.coordinates // geoCoord.coordinates
          }

          // 更新草图图层
          feature.geometry._pixelCoords = pixelCoords
          feature.geometry.coordinates = JSON.parse(JSON.stringify(polylineSpots))
          if (isFirstAdd) {
            this._addFeaturesToMap(feature)
            isFirstAdd = false
          }
          moving = false
          lastAction = 'move'
        }
        // 处理鼠标双击时，处理逻辑
        const handlerDoubleClick = () => {
          clearTimeout(clickTimer)
          clearTimeout(timer)
          // preventClick = true

          // if (!isStartDrawing) {
          //   feature = null
          //   polylineSpots = []
          //   pixelCoords = []
          //   return
          // }

          polylineSpots = []
          pixelCoords = []
          // 停止绘制
          this.stop()
          // 清除捕获效果
          if (this.sketchStage.snapGraphics.length > 0) {
            this.sketchStage.snapGraphics.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this.sketchStage.snapGraphics = []
          }
          this._editMode = 0
          // 发送绘制完成事件
          this.fire('drawn', { geometry: feature.geometry }, self)
          // 绘制完成后，移除顶点
          this.sketchStage.vertexGraphics.forEach((feature) => {
            this._removeFeatureFromMap(feature)
          })
          this.sketchStage.vertexGraphics = []
          // 恢复地图默认双击事件
          this.view._mapActionControl('double-click-zoom', true)
          lastAction = 'double-click'
        }
        // 移除绘制事件
        this._drawEventHandlers.push(handlerClick, handlerMove, handlerDoubleClick)
        this.view.on(ViewEventType.immediateClick, handlerClick)
        this.view.on(ViewEventType.pointerMove, handlerMove)
        this.view.on(ViewEventType.doubleClick, handlerDoubleClick)
      }

      /**
       * @description 添加图形
       * @param {Array} points 生成面的点地理坐标集
       * @param {SketchStyle} sketchStyle 面的符号样式
       */
      addFeature(points, sketchStyle, attributes) {
        let lineStyle = null
        if (!sketchStyle || !sketchStyle.lineStyle) {
          lineStyle = this.sketchStyle.lineStyle
        } else {
          lineStyle = sketchStyle.lineStyle
        }

        const feature = this._getFeature(points, lineStyle)
        if (attributes) {
          feature.attributes = attributes
        }
        this.sketchStage.entityGraphic = feature
        // 更新图层图形
        this._addFeaturesToMap(feature)
      }

      addFeatureByGeometry(geometry, sketchStyle, attributes) {
        let symbol = null
        if (!sketchStyle || !sketchStyle.lineStyle) {
          symbol = this.sketchStyle.lineStyle
        } else {
          symbol = sketchStyle.lineStyle
        }

        const feature = new Feature({
          geometry,
          symbol
        })
        if (attributes) {
          feature.attributes = attributes
        }
        this.sketchStage.entityGraphic = feature
        // 更新图层图形
        this._addFeaturesToMap(feature)
      }

      /**
       * @description 获取feature实例
       * @private
       * @param {Point} point 生成面的点地理坐标集
       * @param {Symbol} symbol 点的符号样式
       */
      _getFeature(points) {
        if (!points) {
          points = [
            [0, 0],
            [1, 1]
          ]
        }
        const geometry = new LineString({
          coordinates: points,
          spatialReference: this._spatialReference
        })
        const symbol = this.sketchStyle.lineStyle
        const polylineGeometry = new Feature({
          geometry,
          symbol
        })
        return polylineGeometry
      }

      /**
       * @description 捕获草图
       * @param {Feature} feature 被选中feature对象
       * @param {Object} event 选中事件参数
       */
      hitTestFeature(feature, event) {
        if (!this._parent && this.editOption.showSelectBox) {
          if (this._editMode === 0) {
            this._editMode = 1
          } else if (this._editMode === 2) {
            // 临时，把clickMap的事件删掉，否则在图形都被删掉时会被触发
            this.view.off(ViewEventType.immediateClick, this._mapClickEvent)
            this._mapClickEvent = null
            this._editMode = 1
          }
          // 进入图形编辑状态，高亮点元素,用新图形代替高亮，展示选中图形时的辅助图形
          this.selectFeature(feature)
        }
        if (this._parent && this._parent._editMode === 1) {
          // 注册图形编辑时的事件，平移图形
          this.startPanGraphics(feature, event)
        } else if (this._parent && this._parent._editMode === 2) {
          // 进入顶点编辑状态，添加顶点+中点辅助图形
          // 调用辅助图形的父级图形的selectFeatureVertex，
          // 1.添加顶点编辑状态的辅助图形
          // 2.删除当前编辑图形状态的辅助图形
          // this._parent.selectFeatureVertex(this._parent.entityGraphic)
        }
      }

      /**
       * @description 选中草图feature
       * @param {Feature} feature 被选中草图feature对象
       */
      selectFeature(feature) {
        if (!this.editOption.showSelectBox) return
        // 1.删除当前编辑图形状态的辅助图形
        // 2.添加顶点编辑状态的辅助图形
        this._clearEditGraphics(2)
        // 加载选时的辅助图形，外包盒
        const extent = feature.geometry.extent
        const polygonDrawTool = new SketchPolygonDrawTool({
          view: this.view,
          layer: this.layer,
          sketchStyle: new SketchStyle({
            fillStyle: this.sketchStyle._selectBoxStyle,
            isShowSegmentLength: true,
            isShowArea: true
          }),
          editOption: {
            showSelectBox: false,
            _hitTestMode: 1
          },
          _parent: this // 或者只传父级相应pan的事件
        })
        // 注册hitTest事件移动图形
        // this._hitTestDrawToolStack.push(polygonDrawTool)
        this._drawTools.push(polygonDrawTool)
        // if (this._hight) {
        //   polygonDrawTool.addFeature([
        //     [extent.xmax, extent.ymax, this._hight],
        //     [extent.xmax, extent.ymin, this._hight],
        //     [extent.xmin, extent.ymin, this._hight],
        //     [extent.xmin, extent.ymax, this._hight],
        //     [extent.xmax, extent.ymax, this._hight]
        //   ])
        // } else {
        //   polygonDrawTool.addFeature([
        //     [extent.xmax, extent.ymax],
        //     [extent.xmax, extent.ymin],
        //     [extent.xmin, extent.ymin],
        //     [extent.xmin, extent.ymax],
        //     [extent.xmax, extent.ymax]
        //   ])
        // }
        polygonDrawTool.addFeature([
          [extent.xmax, extent.ymax],
          [extent.xmax, extent.ymin],
          [extent.xmin, extent.ymin],
          [extent.xmin, extent.ymax],
          [extent.xmax, extent.ymax]
        ])

        this.sketchStage.selectBoxGraphics = [
          polygonDrawTool.sketchStage.entityGraphic
        ]
        // 外包盒顶点和终点
        let boxVertexPoints = []
        // if (this._hight) {
        //   boxVertexPoints = [
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmax, extent.ymax, this._hight],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'ne'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmax, extent.ymin, this._hight],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'se'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmin, extent.ymin, this._hight],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'sw'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmin, extent.ymax, this._hight],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'nw'
        //     },
        //     // midPoint
        //     {
        //       point: new Point({
        //         coordinates: [
        //           (extent.xmax + extent.xmin) / 2,
        //           extent.ymax,
        //           this._hight
        //         ],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'n',
        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [
        //           (extent.xmax + extent.xmin) / 2,
        //           extent.ymin,
        //           this._hight
        //         ],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 's',
        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [
        //           extent.xmax,
        //           (extent.ymax + extent.ymin) / 2,
        //           this._hight
        //         ],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'e',

        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [
        //           extent.xmin,
        //           (extent.ymax + extent.ymin) / 2,
        //           this._hight
        //         ],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'w',
        //       type: 'midVertex'
        //     }
        //   ]
        // } else {
        //   boxVertexPoints = [
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmax, extent.ymax],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'ne'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmax, extent.ymin],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'se'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmin, extent.ymin],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'sw'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmin, extent.ymax],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'nw'
        //     },
        //     // midPoint
        //     {
        //       point: new Point({
        //         coordinates: [(extent.xmax + extent.xmin) / 2, extent.ymax],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'n',
        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [(extent.xmax + extent.xmin) / 2, extent.ymin],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 's',
        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmax, (extent.ymax + extent.ymin) / 2],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'e',

        //       type: 'midVertex'
        //     },
        //     {
        //       point: new Point({
        //         coordinates: [extent.xmin, (extent.ymax + extent.ymin) / 2],
        //         spatialReference: this._spatialReference
        //       }),
        //       direction: 'w',
        //       type: 'midVertex'
        //     }
        //   ]
        // }
        boxVertexPoints = [
          {
            point: new Point({
              coordinates: [extent.xmax, extent.ymax],
              spatialReference: this._spatialReference
            }),
            direction: 'ne'
          },
          {
            point: new Point({
              coordinates: [extent.xmax, extent.ymin],
              spatialReference: this._spatialReference
            }),
            direction: 'se'
          },
          {
            point: new Point({
              coordinates: [extent.xmin, extent.ymin],
              spatialReference: this._spatialReference
            }),
            direction: 'sw'
          },
          {
            point: new Point({
              coordinates: [extent.xmin, extent.ymax],
              spatialReference: this._spatialReference
            }),
            direction: 'nw'
          }
        ]
        if (this._sketchEditor && this._sketchEditor._getCenterCoordinate) {
          const midVertexPoints = [
            // midPoint
            {
              point: new Point({
                coordinates: this._sketchEditor._getCenterCoordinate(
                  [extent.xmax, extent.ymax],
                  [extent.xmax, extent.ymin]
                ),
                spatialReference: this._spatialReference
              }),
              direction: 'e',
              type: 'midVertex'
            },
            {
              point: new Point({
                coordinates: this._sketchEditor._getCenterCoordinate(
                  [extent.xmax, extent.ymin],
                  [extent.xmin, extent.ymin]
                ),
                spatialReference: this._spatialReference
              }),
              direction: 's',
              type: 'midVertex'
            },
            {
              point: new Point({
                coordinates: this._sketchEditor._getCenterCoordinate(
                  [extent.xmin, extent.ymin],
                  [extent.xmin, extent.ymax]
                ),
                spatialReference: this._spatialReference
              }),
              direction: 'w',

              type: 'midVertex'
            },
            {
              point: new Point({
                coordinates: this._sketchEditor._getCenterCoordinate(
                  [extent.xmin, extent.ymax],
                  [extent.xmax, extent.ymax]
                ),
                spatialReference: this._spatialReference
              }),
              direction: 'n',
              type: 'midVertex'
            }
          ]
          boxVertexPoints = boxVertexPoints.concat(midVertexPoints)
        }
        const pointDrawTools = []
        const boxVertexGraphics = []
        boxVertexPoints.forEach((item) => {
          const pointDrawTool = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            sketchStyle: new SketchStyle({
              vertexStyle: this.sketchStyle._selectBoxVertexStyle
            }),
            editOption: {
              showSelectBox: false,
              _hitTestMode: 1
            },
            _parent: this // 或者只传父级相应pan的事件
          })
          // 注册hitTest事件移动图形
          // this._hitTestDrawToolStack.push(pointDrawTool)
          this._drawTools.push(pointDrawTool)
          pointDrawTool.addFeature(item.point, this.sketchStage, {
            direction: item.direction,
            type: item.type
          })
          pointDrawTools.push(pointDrawTool)
          boxVertexGraphics.push(pointDrawTool.sketchStage.entityGraphic)
        })
        this.sketchStage.selectBoxVertexGraphics = boxVertexGraphics
        if (this._otherDrawTools) {
          this._otherDrawTools.push(polygonDrawTool)
        } else {
          this._otherDrawTools = [polygonDrawTool]
        }
        this._otherDrawTools = this._otherDrawTools.concat(pointDrawTools)

        // 添加到undoRedoManager中
        if (this.undoRedoManager) {
          this.undoRedoManager.addProcess('add', this.sketchStage)
        }

        // 点击到地图没有feature图形区域，退出编辑
        if (
          !this._mapClickEvent &&
          (!this._parent || (this._parent && !this._parent._mapClickEvent))
        ) {
          this._mapClickEvent = () => {
            if (this._preventFirstCall) {
              this._preventFirstCall = undefined
              return
            }
            const removedFeatures = this.sketchStage.selectBoxGraphics
              .concat(this.sketchStage.selectBoxVertexGraphics)
              .concat(this.sketchStage.vertexGraphics)
              .concat(this.sketchStage.midVertexGraphics)
            removedFeatures.forEach((feature) => {
              this._removeFeatureFromMap(feature)
            })
            this.view.off(ViewEventType.immediateClick, this._mapClickEvent)
            this.view._mapActionControl('drag-pan', true)
            this._mapClickEvent = null
            // 发送草图没有被选中状态
            this.fire('selected', { isSelected: false }, self)
            this.sketchStage.selectBoxGraphics = []
            this.sketchStage.selectBoxVertexGraphics = []
            this.sketchStage.vertexGraphics = []
            this.sketchStage.midVertexGraphics = []
          }
          this._hitTestEventHandlers.push(this._mapClickEvent)
          this._preventFirstCall = true
          this.view.on(ViewEventType.immediateClick, this._mapClickEvent)
        }
      }

      /**
       * @description 选中feature图形顶点
       * @private
       * @param {Feature} feature 被选中feature对象
       */
      selectFeatureVertex(feature) {
        // 1.删除当前编辑图形状态的辅助图形
        // 2.添加顶点编辑状态的辅助图形
        this._clearEditGraphics(1)

        const pointDrawTools = []
        const midPointDrawTools = []
        feature.geometry.coordinates.forEach((coordinate, i) => {
          // 渲染线的每一个顶点
          const pointDrawTool = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            sketchStyle: new SketchStyle({
              vertexStyle: this.sketchStyle._selectVertexStyle
            }),
            editOption: {
              showSelectBox: false,
              _hitTestMode: 1
            },
            _parent: this // 或者只传父级相应pan的事件
          })
          const point = new Point({
            coordinates: coordinate,
            spatialReference: this._spatialReference
          })
          // 注册hitTest事件移动图形
          // this._hitTestDrawToolStack.push(pointDrawTool)
          this._drawTools.push(pointDrawTool)
          pointDrawTool.addFeature(point, undefined, {
            vertexIndex: i
          })
          pointDrawTools.push(pointDrawTool)
          this.sketchStage.vertexGraphics.push(
            pointDrawTool.sketchStage.entityGraphic
          )
          // 渲染顶点之间的每一个中点
          if (i > 0) {
            const midPointDrawTool = new SketchPointDrawTool({
              view: this.view,
              layer: this.layer,
              sketchStyle: new SketchStyle({
                vertexStyle: this.sketchStyle._selectMidVertexStyle
              }),
              editOption: {
                showSelectBox: false,
                _hitTestMode: 1
              },
              _parent: this // 或者只传父级相应pan的事件
            })
            midPointDrawTools.push(midPointDrawTool)
            const lastCoordinate = feature.geometry.coordinates[i - 1]
            let point = null
            if (coordinate.length > 2) {
              point = new Point({
                coordinates: [
                  (coordinate[0] + lastCoordinate[0]) / 2,
                  (coordinate[1] + lastCoordinate[1]) / 2,
                  (coordinate[2] + lastCoordinate[2]) / 2
                ],
                spatialReference: this._spatialReference
              })
            } else {
              point = new Point({
                coordinates: [
                  (coordinate[0] + lastCoordinate[0]) / 2,
                  (coordinate[1] + lastCoordinate[1]) / 2
                ],
                spatialReference: this._spatialReference
              })
            }
            // 注册hitTest事件移动图形
            // this._hitTestDrawToolStack.push(midPointDrawTool)
            this._drawTools.push(midPointDrawTool)
            midPointDrawTool.addFeature(point, undefined, {
              vertexIndex: i - 1,
              type: 'midVertex'
            })
            this.sketchStage.midVertexGraphics.push(
              midPointDrawTool.sketchStage.entityGraphic
            )
          }
        })
        const drawTools = pointDrawTools.concat(midPointDrawTools)
        this._otherDrawTools = this._otherDrawTools
          ? this._otherDrawTools.concat(drawTools)
          : drawTools
        // 添加到undoRedoManager中
        if (this.undoRedoManager) {
          this.undoRedoManager.addProcess('add', this.sketchStage)
        }
      }

      /**
       * @description 平移图形
       * @param {Feature} feature 被选中feature对象
       * @param {Object} event 拾取事件
       */
      startPanGraphics(feature, event) {
        this.view._mapActionControl('drag-pan', false)
        const timer = null
        let moving = false
        this._startPan = true
        const lon = event.mapPoint.coordinates[0]
        const lat = event.mapPoint.coordinates[1]
        let startPoint = null
        // if (this._hight) {
        //   startPoint = Projection.project(
        //     new Point({
        //       coordinates: [lon, lat, this._hight]
        //     }),
        //     this._spatialReference
        //   )
        // } else {
        //   startPoint = Projection.project(
        //     new Point({
        //       coordinates: [lon, lat]
        //     }),
        //     this._spatialReference
        //   )
        // }
        startPoint = Projection.project(
          new Point({
            coordinates: [lon, lat]
          }),
          this._spatialReference
        )
        let isClickEvent = true
        const isClickTimer = setTimeout(() => {
          isClickEvent = false
        }, 200)
        // 移除父级草图地图点击事件。点图形仍然会触发mapClick事件。
        if (this._parent && this._parent._mapClickEvent) {
          this.view.off(ViewEventType.immediateClick, this._parent._mapClickEvent)
        }

        // 处理平移时，鼠标移动时逻辑。
        const handlerMove = (options) => {
          if (!options || !options.x || !options.y) return
          if (moving || !this._startPan || !this._editMode === 1) return
          if (isClickEvent) return
          clearTimeout(timer)
          moving = true

          const pixelCoord = { x: options.x, y: options.y }
          const movePoint = this.view.toMap({
            x: pixelCoord.x,
            y: pixelCoord.y
          })
          // if (this._hight) {
          //   movePoint = new Point({
          //     coordinates: [
          //       movePoint.coordinates[0],
          //       movePoint.coordinates[1],
          //       this._hight
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // }
          const deltaX = movePoint.coordinates[0] - startPoint.coordinates[0]
          const deltaY = movePoint.coordinates[1] - startPoint.coordinates[1]
          if (deltaX === 0 && deltaY === 0) {
            moving = false
            return
          }

          const coordinates = []
          feature.geometry.coordinates[0].forEach((coordinate) => {
            coordinates.push(this.getPanCoordinates(coordinate, deltaX, deltaY))
          })
          // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
          // const newGeometry = new Polygon({
          //   coordinates: [coordinates],
          //   spatialReference: this._spatialReference
          // })
          const newGeometry = new Polygon({
            coordinates: [
              [
                [0, 0],
                [0, 0],
                [0, 0],
                [0, 0]
              ]
            ],
            spatialReference: this._spatialReference
          })
          newGeometry.coordinates = [coordinates]

          startPoint = movePoint
          // 发送平移事件给父级草图
          this._dispatchEvent(
            'pan',
            { deltaPosition: { x: deltaX, y: deltaY } },
            this
          )
          this.updateFeature(newGeometry, feature)
          moving = false
        }
        // 处理平移时，鼠标按下后抬起逻辑。
        const handlerUp = () => {
          if (!this._editMode === 1) return
          if (!this._startPan) return
          if (isClickEvent && this._parent && this._parent._editMode === 1) {
            this._parent._editMode = 2
            clearTimeout(isClickTimer)
            // 在图形编辑状态时，当鼠标单击时，进入顶点编辑状态，添加顶点+中点辅助图形，调用辅助图形的父级图形的selectFeatureVertex。
            // 当鼠标移动时，则是平移事件
            this._parent.selectFeatureVertex(this._parent.sketchStage.entityGraphic)
            if (this._parent && this._parent._mapClickEvent) {
              this.view.on(
                ViewEventType.immediateClick,
                this._parent._mapClickEvent
              )
            }
            this._startPan = false
            // pan事件移除
            this.view.off(ViewEventType.pointerMove, handlerMove)
            this.view.off(ViewEventType.pointerUp, handlerUp)
            return
          }
          // this._stopHitTest()
          this._editMode = 0
          this._startPan = false
          if (this._enableMapDrag) {
            this._enableMapDrag()
          }
          this.view.off(ViewEventType.pointerMove, handlerMove)
          this.view.off(ViewEventType.pointerUp, handlerUp)

          // 添加到undoRedoManager中
          if (this._parent && this._parent.undoRedoManager) {
            this._parent.undoRedoManager.addProcess(
              'update',
              this._parent.sketchStage
            )
          }
          // 重新注册父级草图地图点击事件
          if (this._parent && this._parent._mapClickEvent) {
            this._parent._preventFirstCall = true
            this.view.on(ViewEventType.immediateClick, this._parent._mapClickEvent)
          }
        }
        // 注册平移时鼠标相关事件
        this._hitTestEventHandlers.push(handlerMove)
        this._hitTestEventHandlers.push(handlerUp)
        this.view.on(ViewEventType.pointerUp, handlerUp)
        this.view.on(ViewEventType.pointerMove, handlerMove)
      }

      /**
       * @description 响应图形平移事件
       * @private
       * @param {Object} event 拾取事件参数
       */
      _processEvent(event) {
        if (event.type === 'pan') {
          // 处理平移逻辑
          this._handlerPanEvent(event)
        } else if (event.type === 'vertexScale') {
          // 处理顶点缩放逻辑
          this._handlerVertexScaleEvent(event)
        } else if (event.type === 'midVertexScale') {
          // 处理中点缩放逻辑
          this._handlerMidVertexScaleEvent(event)
        } else if (event.type === 'vertexMove') {
          // 处理移动顶点逻辑
          this._handlerVertexMoveEvent(event)
        } else if (event.type === 'midVertexAdd') {
          // 处理中点位置增加顶点逻辑
          this._handlerMidVertexAddEvent(event)
        }
      }

      /**
       * @description 响应平移事件
       * @private
       * @param {Object} event 拾取事件参数
       */
      _handlerPanEvent(event) {
        // 更新当前草图的图形位置
        const newCoordinates = []
        this.sketchStage.entityGraphic.geometry.coordinates.forEach(
          (coordinate) => {
            newCoordinates.push(
              this.getPanCoordinates(
                coordinate,
                event.deltaPosition.x,
                event.deltaPosition.y
              )
            )
          }
        )
        // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
        // const newGeometry = new LineString({
        //   coordinates: newCoordinates,
        //   spatialReference: this._spatialReference
        // })
        const newGeometry = new LineString({
          coordinates: [
            [0, 0],
            [1, 1]
          ],
          spatialReference: this._spatialReference
        })
        newGeometry.coordinates = newCoordinates

        this.sketchStage.entityGraphic.geometry = newGeometry
        // 更新同级的辅助草图的图形位置
        if (this._otherDrawTools) {
          this._otherDrawTools.forEach((drawTool) => {
            drawTool._processEvent(event)
          })
        }
      }

      /**
       * @description 响应顶点缩放事件
       * @private
       * @param {Object} event 传入事件参数
       */
      _handlerVertexScaleEvent(event) {
        if (event.action === 'scale') {
          // 更新当前草图的图形位置
          let newGeometry = null
          if (!this.sketchStage.entityGraphic.attributes.lastCoordinates) {
            const oriCoordinates = JSON.parse(
              JSON.stringify(this.sketchStage.entityGraphic.geometry.coordinates)
            )
            this.sketchStage.entityGraphic.attributes.lastCoordinates =
              oriCoordinates
          }
          const newCoordinates = this.getScaleCoordinates(
            this.sketchStage.entityGraphic.geometry.coordinates,
            event.direction,
            event.extent,
            // this.sketchStage.entityGraphic.geometry.extent,
            event.startPoint,
            event.movePoint,
            this.sketchStage.entityGraphic.attributes.lastCoordinates
          )
          // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
          // newGeometry = new LineString({
          //     coordinates: newCoordinates,
          //     spatialReference: this._spatialReference
          //   })
          newGeometry = new LineString({
            coordinates: [
              [0, 0],
              [1, 1]
            ],
            spatialReference: this._spatialReference
          })
          newGeometry.coordinates = newCoordinates

          this.sketchStage.entityGraphic.geometry = newGeometry
          // extent = item.geometry.extent
          // 更新同级的辅助草图的图形位置
          if (this._otherDrawTools) {
            this._otherDrawTools.forEach((drawTool) => {
              // 传给子草图的extent应该是草图改变前的，不是草图改变后的extent
              // event.extent = extent
              drawTool._processEvent(event)
            })
          }
        } else if (event.action === 'stop') {
          if (this.sketchStage.entityGraphic.attributes.lastCoordinates) {
            this.sketchStage.entityGraphic.attributes.lastCoordinates = undefined
          }
          if (this._otherDrawTools) {
            this._otherDrawTools.forEach((drawTool) => {
              // if (drawTool.sketchStage.entityGraphic.id !== event.feature.id) {
              drawTool._processEvent(event)
              // }
            })
          }
        }
      }

      /**
       * @description 响应中点缩放事件
       * @private
       * @param {Object} event 传入事件参数
       */
      _handlerMidVertexScaleEvent(event) {
        // 更新当前草图的图形位置
        let newGeometry = null
        if (!this.sketchStage.entityGraphic.attributes.lastCoordinates) {
          const oriCoordinates = JSON.parse(
            JSON.stringify(this.sketchStage.entityGraphic.geometry.coordinates)
          )
          this.sketchStage.entityGraphic.attributes.lastCoordinates = oriCoordinates
        }
        const newCoordinates = this.getMidScaleCoordinates(
          this.sketchStage.entityGraphic.geometry.coordinates,
          event.direction,
          event.extent,
          // item.geometry.extent,
          event.startPoint,
          event.movePoint,
          this.sketchStage.entityGraphic.attributes.lastCoordinates
        )
        // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
        // newGeometry = new LineString({
        //   coordinates: newCoordinates,
        //   spatialReference: this._spatialReference
        // })
        newGeometry = new LineString({
          coordinates: [
            [0, 0],
            [1, 1]
          ],
          spatialReference: this._spatialReference
        })
        newGeometry.coordinates = newCoordinates

        this.sketchStage.entityGraphic.geometry = newGeometry
        // extent = item.geometry.extent
        // newEntityGraphic = this.sketchStage.entityGraphic

        // this.sketchStage.entityGraphic = newEntityGraphic
        // 更新同级的辅助草图的图形位置
        if (this._otherDrawTools) {
          this._otherDrawTools.forEach((drawTool) => {
            // 传给子草图的extent应该是草图改变前的，不是草图改变后的extent
            // event.extent = extent
            drawTool._processEvent(event)
          })
        }
        if (event.action === 'stop') {
          if (this.sketchStage.entityGraphic.attributes.lastCoordinates) {
            this.sketchStage.entityGraphic.attributes.lastCoordinates = undefined
          }
          if (this._otherDrawTools) {
            this._otherDrawTools.forEach((drawTool) => {
              // if (drawTool.sketchStage.entityGraphic.id !== event.feature.id) {
              drawTool._processEvent(event)
              // }
            })
          }
        }
      }

      /**
       * @description 响应移动顶点事件
       * @private
       * @param {Object} event 传入事件参数
       */
      _handlerVertexMoveEvent(event) {
        // 更新当前草图的图形位置
        this.sketchStage.currentVertexIndex = event.vertexIndex
        const entityGraphic = this.sketchStage.entityGraphic
        const originCoordinates = entityGraphic.geometry.coordinates
        entityGraphic.geometry.coordinates[event.vertexIndex] =
          event.movePoint.coordinates

        // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
        // entityGraphic.geometry = new LineString({
        //   coordinates: entityGraphic.geometry.coordinates,
        //   spatialReference: this._spatialReference
        // })
        const newCoordinates = JSON.parse(
          JSON.stringify(entityGraphic.geometry.coordinates)
        )
        entityGraphic.geometry = new LineString({
          coordinates: [
            [0, 0],
            [1, 1]
          ],
          spatialReference: this._spatialReference
        })
        entityGraphic.geometry.coordinates = newCoordinates

        // 更新同级的辅助草图的图形位置
        if (this._otherDrawTools) {
          if (event.vertexIndex === 0) {
            const feature = this.sketchStage.midVertexGraphics[event.vertexIndex]
            const p = originCoordinates[event.vertexIndex]
            const pNext = originCoordinates[event.vertexIndex + 1]
            feature.geometry.coordinates = [
              (pNext[0] + p[0]) / 2,
              (pNext[1] + p[1]) / 2
            ]
            feature.geometry = new Point({
              coordinates: feature.geometry.coordinates,
              spatialReference: this._spatialReference
            })
          } else if (event.vertexIndex === originCoordinates.length - 1) {
            const featureLast =
              this.sketchStage.midVertexGraphics[event.vertexIndex - 1]
            const pLast = originCoordinates[event.vertexIndex - 1]
            const p = originCoordinates[event.vertexIndex]
            featureLast.geometry.coordinates = [
              (pLast[0] + p[0]) / 2,
              (pLast[1] + p[1]) / 2
            ]
            featureLast.geometry = new Point({
              coordinates: featureLast.geometry.coordinates,
              spatialReference: this._spatialReference
            })
          } else {
            const feature = this.sketchStage.midVertexGraphics[event.vertexIndex]
            const featureLast =
              this.sketchStage.midVertexGraphics[event.vertexIndex - 1]
            const pLast = originCoordinates[event.vertexIndex - 1]
            const p = originCoordinates[event.vertexIndex]
            const pNext = originCoordinates[event.vertexIndex + 1]
            feature.geometry.coordinates = [
              (pNext[0] + p[0]) / 2,
              (pNext[1] + p[1]) / 2
            ]
            feature.geometry = new Point({
              coordinates: feature.geometry.coordinates,
              spatialReference: this._spatialReference
            })
            featureLast.geometry.coordinates = [
              (pLast[0] + p[0]) / 2,
              (pLast[1] + p[1]) / 2
            ]
            featureLast.geometry = new Point({
              coordinates: featureLast.geometry.coordinates,
              spatialReference: this._spatialReference
            })
          }
        }
      }

      /**
       * @description 响应中点位置增加顶点事件
       * @private
       * @param {Object} event 传入事件参数
       */
      _handlerMidVertexAddEvent(event) {
        if (event.action === 'changeFeature') {
          // 向当前草图几何对象中插入一个顶点
          this.sketchStage.entityGraphic.geometry.coordinates.splice(
            event.vertexIndex + 1,
            0,
            event.point.coordinates
          )
          // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
          // this.sketchStage.entityGraphic.geometry = new LineString({
          //   coordinates: this.sketchStage.entityGraphic.geometry.coordinates,
          //   spatialReference: this._spatialReference
          // })
          const newCoordinates = JSON.parse(
            JSON.stringify(this.sketchStage.entityGraphic.geometry.coordinates)
          )
          this.sketchStage.entityGraphic.geometry = new LineString({
            coordinates: [
              [0, 0],
              [1, 1]
            ],
            spatialReference: this._spatialReference
          })
          this.sketchStage.entityGraphic.geometry.coordinates = newCoordinates
        }
        if (event.action === 'moveMidVertex') {
          // 根据移动的顶点实时位置，更新当前草图图形顶点坐标
          this.sketchStage.currentVertexIndex = event.vertexIndex
          this.sketchStage.entityGraphic.geometry.coordinates[
            event.vertexIndex + 1
          ] = event.movePoint.coordinates
          // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
          // this.sketchStage.entityGraphic.geometry = new LineString({
          //   coordinates: this.sketchStage.entityGraphic.geometry.coordinates,
          //   spatialReference: this._spatialReference
          // })
          const newCoordinates = JSON.parse(
            JSON.stringify(this.sketchStage.entityGraphic.geometry.coordinates)
          )
          this.sketchStage.entityGraphic.geometry = new LineString({
            coordinates: [
              [0, 0],
              [1, 1]
            ],
            spatialReference: this._spatialReference
          })
          this.sketchStage.entityGraphic.geometry.coordinates = newCoordinates
        }
        if (event.action === 'addVertex') {
          // 更新同级的辅助草图的图形顶点
          // 增加一个新的顶点和两个中点图形
          const oldMidId =
            this.sketchStage.midVertexGraphics[event.vertexIndex].id.toString()
          const pointDrawTool = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            sketchStyle: new SketchStyle({
              vertexStyle: this.sketchStyle._selectVertexStyle
            }),
            editOption: {
              showSelectBox: false,
              _hitTestMode: 1
            },
            _parent: this // 或者只传父级相应pan的事件
          })
          // this._hitTestDrawToolStack.push(pointDrawTool)
          this._drawTools.push(pointDrawTool)
          pointDrawTool.addFeature(event.point)
          this.sketchStage.vertexGraphics.splice(
            event.vertexIndex + 1,
            0,
            pointDrawTool.sketchStage.entityGraphic
          )

          // 添加第一个中点
          const p =
            this.sketchStage.entityGraphic.geometry.coordinates[event.vertexIndex]
          let newMidPoint1 = null
          // if (this._hight) {
          //   newMidPoint1 = new Point({
          //     coordinates: [
          //       (p[0] + event.point.coordinates[0]) / 2,
          //       (p[1] + event.point.coordinates[1]) / 2,
          //       this._hight
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // } else {
          //   newMidPoint1 = new Point({
          //     coordinates: [
          //       (p[0] + event.point.coordinates[0]) / 2,
          //       (p[1] + event.point.coordinates[1]) / 2
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // }
          let hight1 = null
          if (this._getHight) {
            hight1 = 0
          }
          if (hight1) {
            newMidPoint1 = new Point({
              coordinates: [
                (p[0] + event.point.coordinates[0]) / 2,
                (p[1] + event.point.coordinates[1]) / 2,
                hight1
              ],
              spatialReference: this._spatialReference
            })
          } else {
            newMidPoint1 = new Point({
              coordinates: [
                (p[0] + event.point.coordinates[0]) / 2,
                (p[1] + event.point.coordinates[1]) / 2
              ],
              spatialReference: this._spatialReference
            })
          }

          const midPointDrawTool1 = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            sketchStyle: new SketchStyle({
              vertexStyle: this.sketchStyle._selectMidVertexStyle
            }),
            editOption: {
              showSelectBox: false,
              _hitTestMode: 1
            },
            _parent: this // 或者只传父级相应pan的事件
          })
          // this._hitTestDrawToolStack.push(midPointDrawTool1)
          this._drawTools.push(midPointDrawTool1)
          midPointDrawTool1.addFeature(newMidPoint1, undefined, {
            type: 'midVertex'
          })
          // 下标为vertexIndex的元素被替换掉
          this.sketchStage.midVertexGraphics.splice(
            event.vertexIndex,
            1,
            midPointDrawTool1.sketchStage.entityGraphic
          )
          // 添加第二个中点
          const pNext =
            this.sketchStage.entityGraphic.geometry.coordinates[
              event.vertexIndex + 2
            ]
          let newMidPoint2 = null
          // if (this._hight) {
          //   newMidPoint2 = new Point({
          //     coordinates: [
          //       (pNext[0] + event.point.coordinates[0]) / 2,
          //       (pNext[1] + event.point.coordinates[1]) / 2,
          //       this._hight
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // } else {
          //   newMidPoint2 = new Point({
          //     coordinates: [
          //       (pNext[0] + event.point.coordinates[0]) / 2,
          //       (pNext[1] + event.point.coordinates[1]) / 2
          //     ],
          //     spatialReference: this._spatialReference
          //   })
          // }
          let hight2 = null
          if (this._getHight) {
            hight2 = 0
          }
          if (hight2) {
            newMidPoint2 = new Point({
              coordinates: [
                (pNext[0] + event.point.coordinates[0]) / 2,
                (pNext[1] + event.point.coordinates[1]) / 2,
                hight2
              ],
              spatialReference: this._spatialReference
            })
          } else {
            newMidPoint2 = new Point({
              coordinates: [
                (pNext[0] + event.point.coordinates[0]) / 2,
                (pNext[1] + event.point.coordinates[1]) / 2
              ],
              spatialReference: this._spatialReference
            })
          }
          const midPointDrawTool2 = new SketchPointDrawTool({
            view: this.view,
            layer: this.layer,
            sketchStyle: new SketchStyle({
              vertexStyle: this.sketchStyle._selectMidVertexStyle
            }),
            editOption: {
              showSelectBox: false,
              _hitTestMode: 1
            },
            _parent: this // 或者只传父级相应pan的事件
          })
          // this._hitTestDrawToolStack.push(midPointDrawTool2)
          this._drawTools.push(midPointDrawTool2)
          midPointDrawTool2.addFeature(newMidPoint2, undefined, {
            type: 'midVertex'
          })
          // 下标为vertexIndex的元素后面添加一个新元素
          this.sketchStage.midVertexGraphics.splice(
            event.vertexIndex + 1,
            0,
            midPointDrawTool2.sketchStage.entityGraphic
          )
          // 更新每个feature的VertexIndex
          this.sketchStage.vertexGraphics.forEach((feature, i) => {
            if (feature.attributes) {
              feature.attributes.vertexIndex = i
            } else {
              feature.attributes = {
                vertexIndex: i
              }
            }
          })
          this.sketchStage.midVertexGraphics.forEach((feature, i) => {
            if (feature.attributes) {
              feature.attributes.vertexIndex = i
            } else {
              feature.attributes = {
                vertexIndex: i
              }
            }
          })
          this._otherDrawTools.forEach((drawTool) => {
            if (drawTool.sketchStage.entityGraphic.id === oldMidId) {
              this._removeFeatureFromMap(drawTool.sketchStage.entityGraphic)
            }
          })
          this._otherDrawTools.push(pointDrawTool)
          this._otherDrawTools.push(midPointDrawTool1)
          this._otherDrawTools.push(midPointDrawTool2)
        }
      }

      /**
       * 图形捕获，捕获重合点、点在线上、平行线、垂直线
       * @private
       * @param {Point} geoCoord 当前坐标点
       * @param {Array} polygonSpots 被捕获的顶点数据组
       * @param {Array} polygonSpotSlopes 被捕获的直线斜率数据组
       */
      getSnapGraphics(targetPoint, polygonSpots) {
        let realPoint = null
        const tolerance = this.getDistanceByPixel
          ? this.getDistanceByPixel(this.sketchSnappingTool.pixelTolerance)
          : 200
        const moveLine = new LineString({
          coordinates: polygonSpots.slice(polygonSpots.length - 2),
          spatialReference: this._spatialReference
        })
        let geometries
        if (this.sketchSnappingTool.snapSketchGeometry && polygonSpots.length > 3) {
          const entityPolyline = new LineString({
            coordinates: polygonSpots.slice(0, polygonSpots.length - 2),
            spatialReference: this._spatialReference
          })
          geometries = this.snapAndReferGeometries.concat([entityPolyline])
        } else {
          geometries = this.snapAndReferGeometries
        }
        // 获取捕获结果
        const snapResult = this.sketchSnappingTool.snapGeometries(
          targetPoint,
          moveLine,
          geometries,
          tolerance
        )
        if (snapResult.coincidentPoint) {
          // 端点重合
          const pointFeature = new Feature({
            geometry: snapResult.coincidentPoint.realPoint,
            symbol: this.sketchStyle._coincidentPointStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          realPoint = snapResult.coincidentPoint.realPoint
        } else if (snapResult.inLineAndParallel) {
          snapResult.inLineAndParallel.lines.forEach((line) => {
            const lineFeature = new Feature({
              geometry: line,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(lineFeature)
          })
          const pointFeature = new Feature({
            geometry: snapResult.inLineAndParallel.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          if (snapResult.inLineAndParallel.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.inLineAndParallel.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.inLineAndParallel.realPoint
        } else if (snapResult.inLineAndPerpendicular) {
          snapResult.inLineAndPerpendicular.lines.forEach((line) => {
            const lineFeature = new Feature({
              geometry: line,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(lineFeature)
          })
          const pointFeature = new Feature({
            geometry: snapResult.inLineAndPerpendicular.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          if (snapResult.inLineAndPerpendicular.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.inLineAndPerpendicular.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.inLineAndPerpendicular.realPoint
        } else if (snapResult.pointInLine) {
          // 点在线上捕获上图
          const lineFeature = new Feature({
            geometry: snapResult.pointInLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.pointInLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          realPoint = snapResult.pointInLine.realPoint
        } else if (snapResult.parallelLine) {
          // 平行捕获结果上图
          const lineFeature = new Feature({
            geometry: snapResult.parallelLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.parallelLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          // 渲染高亮平行
          if (snapResult.parallelLine.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.parallelLine.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.parallelLine.realPoint
        } else if (snapResult.perpendicularLine) {
          // 渲染高亮垂直，坐标点
          const lineFeature = new Feature({
            geometry: snapResult.perpendicularLine.line,
            symbol: new SimpleLineSymbol({
              color: new Color(255, 255, 0, 1),
              width: 3
            })
          })
          this.sketchStage.snapGraphics.push(lineFeature)
          const pointFeature = new Feature({
            geometry: snapResult.perpendicularLine.realPoint,
            symbol: this.sketchStyle._selectVertexStyle
          })
          this.sketchStage.snapGraphics.push(pointFeature)
          // 渲染高亮垂足
          if (snapResult.perpendicularLine.symbolGeometry) {
            const symbolFeature = new Feature({
              geometry: snapResult.perpendicularLine.symbolGeometry,
              symbol: new SimpleLineSymbol({
                color: new Color(255, 255, 0, 1),
                width: 3
              })
            })
            this.sketchStage.snapGraphics.push(symbolFeature)
          }
          realPoint = snapResult.perpendicularLine.realPoint
        }
        this.sketchStage.snapGraphics.forEach((feature) => {
          this._addFeaturesToMap(feature)
        })
        return realPoint
      }

      /**
       * @description 选中图形顶点
       * @private
       */
      selectVertex() {}

      /**
       * @description 选中图形中点点
       */
      addMidVertex(index, point) {
        const midPointDrawTool = new SketchPointDrawTool()
        midPointDrawTool.addPoint(point)
        this.sketchStage.midVertexGraphics = midPointDrawTool
      }

      /**
       * 当前草图图形中插入新的顶点
       * @private
       * @param {Point} point 新增/插入顶点
       * @param {Number} index 新增/新增点的序号,从1开始
       */
      addVertex(point, index) {
        index--
        const newGeometry = null
        if (index > -1 && index <= this.sketchStage.midVertexGraphics.length + 1) {
          let vertexCount = 0
          let newCoordinates = []

          vertexCount =
            this.sketchStage.entityGraphic.geometry.coordinates.length - 1
          if (index <= vertexCount) {
            // 向当前草图几何对象中插入一个顶点
            newCoordinates = this.sketchStage.entityGraphic.geometry.coordinates
            newCoordinates.splice(index, 0, point.coordinates)
            // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
            // this.sketchStage.entityGraphic.geometry = new LineString({
            //       coordinates: newCoordinates,
            //       spatialReference: this._spatialReference
            //     })
            this.sketchStage.entityGraphic.geometry = new LineString({
              coordinates: [
                [0, 0],
                [1, 1]
              ],
              spatialReference: this._spatialReference
            })
            this.sketchStage.entityGraphic.geometry.coordinates = newCoordinates

            // 更新同级的辅助草图的图形顶点
            let pointDrawTool = undefined
            let midPointDrawTool2 = undefined
            const extent = this.sketchStage.entityGraphic.geometry.extent
            if (this.sketchStage.selectBoxGraphics.length > 0) {
              this.sketchStage.selectBoxGraphics.forEach((feature) => {
                feature.geometry.coordinates = [
                  [
                    [extent.xmax, extent.ymax],
                    [extent.xmax, extent.ymin],
                    [extent.xmin, extent.ymin],
                    [extent.xmin, extent.ymax],
                    [extent.xmax, extent.ymax]
                  ]
                ]
              })
            }
            if (this.sketchStage.selectBoxVertexGraphics.length > 0) {
              const points = [
                [extent.xmax, extent.ymax],
                [extent.xmax, extent.ymin],
                [extent.xmin, extent.ymin],
                [extent.xmin, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymin],
                [extent.xmax, (extent.ymax + extent.ymin) / 2],
                [extent.xmin, (extent.ymax + extent.ymin) / 2]
              ]
              this.sketchStage.selectBoxVertexGraphics.forEach((feature, i) => {
                feature.geometry.coordinates = points[i]
              })
            }
            // 增加一个新的顶点
            if (this.sketchStage.vertexGraphics.length > 0) {
              pointDrawTool = new SketchPointDrawTool({
                view: this.view,
                layer: this.layer,
                sketchStyle: new SketchStyle({
                  vertexStyle: this.sketchStyle._selectVertexStyle
                }),
                editOption: {
                  showSelectBox: false,
                  _hitTestMode: 1
                },
                _parent: this // 或者只传父级相应pan的事件
              })
              // this._hitTestDrawToolStack.push(pointDrawTool)
              this._drawTools.push(pointDrawTool)
              pointDrawTool.addFeatureByGeometry(point)
              this.sketchStage.vertexGraphics.splice(
                index,
                0,
                pointDrawTool.sketchStage.entityGraphic
              )
              // 更新每个feature的VertexIndex
              this.sketchStage.vertexGraphics.forEach((feature, i) => {
                if (feature.attributes) {
                  feature.attributes.vertexIndex = i
                } else {
                  feature.attributes = {
                    vertexIndex: i
                  }
                }
              })
            }
            // 修改第一个中点坐标，增加第二个新的中点
            if (this.sketchStage.midVertexGraphics.length > 0) {
              let replaceIndex = -1
              let addIndex = -1
              let pLast = null
              let pNext = null
              if (index === 0) {
                addIndex = 0
                pNext = this.sketchStage.entityGraphic.geometry.coordinates[1]
              } else if (index === this.sketchStage.midVertexGraphics.length + 1) {
                addIndex = this.sketchStage.midVertexGraphics.length - 2
                pNext =
                  this.sketchStage.entityGraphic.geometry.coordinates[addIndex]
              } else {
                replaceIndex = index - 1
                addIndex = index + 1
                pLast =
                  this.sketchStage.entityGraphic.geometry.coordinates[replaceIndex]
                pNext =
                  this.sketchStage.entityGraphic.geometry.coordinates[addIndex]
              }
              // 修改第一个中点
              if (replaceIndex > -1) {
                const newMidPoint1 = new Point({
                  coordinates: [
                    (pLast[0] + point.coordinates[0]) / 2,
                    (pLast[1] + point.coordinates[1]) / 2
                  ],
                  spatialReference: this._spatialReference
                })
                // 下标为Index的上一个点坐标被替换掉新坐标
                this.sketchStage.midVertexGraphics[
                  replaceIndex
                ].geometry.coordinates = newMidPoint1.coordinates
              }
              // 添加第二个中点
              if (addIndex > -1) {
                const newMidPoint2 = new Point({
                  coordinates: [
                    (pNext[0] + point.coordinates[0]) / 2,
                    (pNext[1] + point.coordinates[1]) / 2
                  ],
                  spatialReference: this._spatialReference
                })
                midPointDrawTool2 = new SketchPointDrawTool({
                  view: this.view,
                  layer: this.layer,
                  sketchStyle: new SketchStyle({
                    vertexStyle: this.sketchStyle._selectMidVertexStyle
                  }),
                  editOption: {
                    showSelectBox: false,
                    _hitTestMode: 1
                  },
                  _parent: this // 或者只传父级相应pan的事件
                })
                // this._hitTestDrawToolStack.push(midPointDrawTool2)
                this._drawTools.push(midPointDrawTool2)
                midPointDrawTool2.addFeatureByGeometry(newMidPoint2, undefined, {
                  type: 'midVertex'
                })
                // 下标为Index的元素后面添加一个新元素
                this.sketchStage.midVertexGraphics.splice(
                  index,
                  0,
                  midPointDrawTool2.sketchStage.entityGraphic
                )
              }
              this.sketchStage.midVertexGraphics.forEach((feature, i) => {
                if (feature.attributes) {
                  feature.attributes.vertexIndex = i
                } else {
                  feature.attributes = {
                    vertexIndex: i
                  }
                }
              })
            }
            // 修改drawTool集合中增加一个顶点两个中点
            if (pointDrawTool) {
              this._otherDrawTools.push(pointDrawTool)
            }
            if (midPointDrawTool2) {
              this._otherDrawTools.push(midPointDrawTool2)
            }
            this.undoRedoManager.addProcess('update', this.sketchStage)
          }
          return newGeometry
        }
      }

      /**
       * 更新当前草图图形的某个顶点
       * @param {Point} point 新的顶点
       * @param {Number} index 需更新的顶点的序号
       */
      updateVertex(point, index) {
        index--
        let newGeometry = null
        if (index > -1) {
          const vertexCount =
            this.sketchStage.entityGraphic.geometry.coordinates.length
          if (index < vertexCount) {
            // 当前草图几何对象中更新顶点，更新草图实体图形
            const entityGraphic = this.sketchStage.entityGraphic
            const newCoordinates = entityGraphic.geometry.coordinates
            entityGraphic.geometry.coordinates = newCoordinates
            this.currentVertexIndex = index

            newCoordinates[index] = point.coordinates
            // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
            // entityGraphic.geometry = new LineString({
            //       coordinates: entityGraphic.geometry.coordinates,
            //       spatialReference: this._spatialReference
            //     })
            const newGeometryCoordinates = JSON.parse(
              JSON.stringify(entityGraphic.geometry.coordinates)
            )
            entityGraphic.geometry = new LineString({
              coordinates: [
                [0, 0],
                [1, 1]
              ],
              spatialReference: this._spatialReference
            })
            entityGraphic.geometry.coordinates = newGeometryCoordinates

            newGeometry = entityGraphic.geometry
            this.sketchStage.entityGraphic.geometry = newGeometry

            const extent = entityGraphic.geometry.extent
            if (this.sketchStage.selectBoxGraphics.length > 0) {
              this.sketchStage.selectBoxGraphics.forEach((feature) => {
                feature.geometry.coordinates = [
                  [
                    [extent.xmax, extent.ymax],
                    [extent.xmax, extent.ymin],
                    [extent.xmin, extent.ymin],
                    [extent.xmin, extent.ymax],
                    [extent.xmax, extent.ymax]
                  ]
                ]
              })
            }
            if (this.sketchStage.selectBoxVertexGraphics.length > 0) {
              const points = [
                [extent.xmax, extent.ymax],
                [extent.xmax, extent.ymin],
                [extent.xmin, extent.ymin],
                [extent.xmin, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymin],
                [extent.xmax, (extent.ymax + extent.ymin) / 2],
                [extent.xmin, (extent.ymax + extent.ymin) / 2]
              ]
              this.sketchStage.selectBoxVertexGraphics.forEach((feature, i) => {
                feature.geometry.coordinates = points[i]
              })
            }
            // 更新顶点图形
            if (this.sketchStage.vertexGraphics.length > 0) {
              this.sketchStage.vertexGraphics[index].geometry.coordinates =
                point.coordinates
            }
            // 更新中点图形
            if (this.sketchStage.midVertexGraphics.length > 0) {
              const pLast = newCoordinates[index - 1]
              const p = newCoordinates[index]
              const pNext = newCoordinates[index + 1]
              let updateIndex1 = -1
              let updateIndex2 = -1
              if (index === 0) {
                updateIndex1 = index
              } else if (index === vertexCount - 1) {
                updateIndex2 = index - 1
              } else {
                updateIndex1 = index
                updateIndex2 = index - 1
              }
              if (updateIndex1 > -1) {
                const feature1 = this.sketchStage.midVertexGraphics[updateIndex1]
                feature1.geometry.coordinates = [
                  (pNext[0] + p[0]) / 2,
                  (pNext[1] + p[1]) / 2
                ]
                feature1.geometry = new Point({
                  coordinates: feature1.geometry.coordinates,
                  spatialReference: this._spatialReference
                })
              }
              if (updateIndex2 > -1) {
                const feature2 = this.sketchStage.midVertexGraphics[updateIndex2]
                feature2.geometry.coordinates = [
                  (pLast[0] + p[0]) / 2,
                  (pLast[1] + p[1]) / 2
                ]
                feature2.geometry = new Point({
                  coordinates: feature2.geometry.coordinates,
                  spatialReference: this._spatialReference
                })
              }
            }
          }
          this.undoRedoManager.addProcess('update', this.sketchStage)
        }
        return newGeometry
      }

      /**
       * 移除草图图形的某个顶点
       * @param {Number} index 需更新的顶点的序号
       */
      removeVertex(index) {
        index--
        let newGeometry = null
        if (index > -1) {
          const vertexCount =
            this.sketchStage.entityGraphic.geometry.coordinates.length
          if (vertexCount > 2 && index < vertexCount) {
            const newCoordinates =
              this.sketchStage.entityGraphic.geometry.coordinates
            // 更新草图实体图形
            newCoordinates.splice(index, 1)
            // 临时，三维geometry extent有bug，暂时用先创建二维geometry，再赋值三维坐标
            // newGeometry = new LineString({
            //       coordinates: newCoordinates,
            //       spatialReference: this._spatialReference
            //     })
            newGeometry = new LineString({
              coordinates: [
                [0, 0],
                [1, 1]
              ],
              spatialReference: this._spatialReference
            })
            newGeometry.coordinates = newCoordinates

            this.sketchStage.entityGraphic.geometry = newGeometry
            // 更新草图辅助图形
            const extent = this.sketchStage.entityGraphic.geometry.extent
            if (this.sketchStage.selectBoxGraphics.length > 0) {
              this.sketchStage.selectBoxGraphics.forEach((feature) => {
                feature.geometry.coordinates = [
                  [
                    [extent.xmax, extent.ymax],
                    [extent.xmax, extent.ymin],
                    [extent.xmin, extent.ymin],
                    [extent.xmin, extent.ymax],
                    [extent.xmax, extent.ymax]
                  ]
                ]
              })
            }
            if (this.sketchStage.selectBoxVertexGraphics.length > 0) {
              const points = [
                [extent.xmax, extent.ymax],
                [extent.xmax, extent.ymin],
                [extent.xmin, extent.ymin],
                [extent.xmin, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymax],
                [(extent.xmax + extent.xmin) / 2, extent.ymin],
                [extent.xmax, (extent.ymax + extent.ymin) / 2],
                [extent.xmin, (extent.ymax + extent.ymin) / 2]
              ]
              this.sketchStage.selectBoxVertexGraphics.forEach((feature, i) => {
                feature.geometry.coordinates = points[i]
              })
            }
            if (this.sketchStage.vertexGraphics.length > 0) {
              const oriFeatureId =
                this.sketchStage.vertexGraphics[index].id.toString()
              this._removeFeatureFromMap(this.sketchStage.vertexGraphics[index])
              this.sketchStage.vertexGraphics.splice(index, 1)
              this.sketchStage.vertexGraphics.forEach((feature, i) => {
                if (feature.attributes) {
                  feature.attributes.vertexIndex = i
                } else {
                  feature.attributes = {
                    vertexIndex: i
                  }
                }
              })
              this._otherDrawTools = this._otherDrawTools.filter((drawTool) => {
                if (drawTool.sketchStage.entityGraphic.id !== oriFeatureId) {
                  return drawTool
                }
              })
            }
            if (this.sketchStage.midVertexGraphics.length > 0) {
              let newMidCoordinates = []
              let updateIndex = -1
              let removeIndex = -1
              if (index === 0) {
                removeIndex = 0
              } else if (index === vertexCount - 1) {
                removeIndex = index - 1
              } else {
                newMidCoordinates = [
                  (newGeometry.coordinates[index - 1][0] +
                    newGeometry.coordinates[index][0]) /
                    2,
                  (newGeometry.coordinates[index - 1][1] +
                    newGeometry.coordinates[index][1]) /
                    2
                ]
                updateIndex = index - 1
                removeIndex = index
              }
              if (updateIndex > -1) {
                this.sketchStage.midVertexGraphics[updateIndex].geometry =
                  new Point({
                    coordinates: newMidCoordinates,
                    spatialReference: this._spatialReference
                  })
              }
              const oriFeatureId =
                this.sketchStage.vertexGraphics[removeIndex].id.toString()
              this._removeFeatureFromMap(
                this.sketchStage.midVertexGraphics[removeIndex]
              )
              this.sketchStage.midVertexGraphics.splice(removeIndex, 1)
              // this._otherDrawTools.filter(drawTool => drawTool.sketchStage.entityGraphic.id!= )
              this.sketchStage.midVertexGraphics.forEach((feature, i) => {
                if (feature.attributes) {
                  feature.attributes.vertexIndex = i
                } else {
                  feature.attributes = {
                    vertexIndex: i
                  }
                }
              })
              this._otherDrawTools = this._otherDrawTools.filter((drawTool) => {
                if (drawTool.sketchStage.entityGraphic.id !== oriFeatureId) {
                  return drawTool
                }
              })
            }
          }
          this.undoRedoManager.addProcess('update', this.sketchStage)
        }
        return newGeometry
      }
    }
    export default SketchPolylineDrawTool