cesium-军事标绘(钳形攻势)

 1.实现说明

已知两点坐标如何实现直接在cesium上直接绘制钳形攻势箭头,实现效果如下:

辛苦总结麻烦点个赞哈!

钳形攻势

2.代码实现

(1)数据处理

 主要实现创造地理空间数据通过geojson形式

  drawLineGeojson () {
       var geoJsonData = {
        "type": "FeatureCollection",
        "features": [
          {
            "type": "Feature",
            "properties": {
              'type': 'pincer',
              'color': 'green'
            },
            "geometry": {
              "coordinates": [
                [
                  114.21356084473587,
                  26.76204596411918
                ],
                [
                  115.97714004616273,
                  24.99893198497439
                ]
              ],
              "type": "LineString"
            }
          }
        ]
      }
    for (let index = 0; index < geoJsonData.features.length; index++) {
      const coordinates = geoJsonData.features[index].geometry.coordinates;
      const properties = geoJsonData.features[index].properties;
        let arr = this.getAttackcoordinates(coordinates[0], coordinates[1], 100)
        this.createPincerArrow(arr, properties)
    }
  },

(2)箭头数据处理

  利用turf.js实现坐标偏移(从而获得三个点坐标)

  // (1.3) 钳形攻势数据处理
  getAttackcoordinates (startData, endData, num) {
    // 提供的坐标点
    const startPoint = startData;
    const endPoint = endData;
    // 转换为Turf.js点要素
    const start = turf.point(startPoint);
    const end = turf.point(endPoint);

    // 计算线段的角度
    const bearing = turf.bearing(start, end);

    // 获取新坐标离起始点有20公里距离
    const newStart = turf.destination(start, 20, bearing);
    const newEnd = turf.destination(end, -20, bearing);

    // 向南偏转90度,得到新的角度
    const bearingSouth = (bearing + 90) % 360;
    // 向北偏转90度,得到新的角度
    const bearingNorth = (bearing - 90 + 360) % 360;
    // 指定距离(单位:千米)
    const distance = Math.floor(Math.random() * (num - 10 + 1)) + 10;
    // 使用Turf.js计算向南偏转90度后的终点坐标;
    const endSouth = turf.destination(newStart, distance, bearingSouth);
    // 使用Turf.js计算向北偏转90度后的终点坐标
    const endNorth = turf.destination(newStart, distance, bearingNorth);
    return [endSouth.geometry.coordinates, endNorth.geometry.coordinates, newEnd.geometry.coordinates]
  },

(3)绘制钳形攻势

        燕尾攻击箭头绘制如下:

  // (1.5) 绘制钳形箭头
  createPincerArrow (lnglatArr, properties) {
    let material = Cesium.Color.fromCssColorString('#d81e06').withAlpha(0.7);
    if (properties.color == 'red') {
      material = Cesium.Color.fromCssColorString('#d81e06').withAlpha(0.7);
    } else if (properties.color == 'blue') {
      material = Cesium.Color.fromCssColorString('#1296db').withAlpha(0.7);
    } else {
      material = Cesium.Color.fromCssColorString('#67C23A').withAlpha(0.7);
    }
    var res = drawPincer.doubleArrow(lnglatArr);
    var returnData = res.polygonalPoint;
    this.currentViewer.entities.add({
      name: 'polyon',
      polygon: {
        hierarchy: new Cesium.PolygonHierarchy(returnData),
        show: true,
        fill: true,
        clampToGround: true,
        material: material
      }
    }
    );
  },

(4)引用函数

        所需引用函数,还需引入turf.js

import DrawPincer from './tool/draw/drawPincerArrow.js'
const drawPincer = new DrawPincer();

(5)函数内容

        这个函数内容,直接引用即可

export default class DrawPincer {
  doubleArrow (inputPoint) {
    var $this = this;
    this.connPoint = null;
    this.tempPoint4 = null;
    this.points = inputPoint;
    var result = {
      controlPoint: null,
      polygonalPoint: null
    };
    //获取已经点击的坐标数
    var t = inputPoint.length;
    if (!(2 > t)) {
      if (2 == t) return inputPoint;
      var o = this.points[0],    //第一个点
        e = this.points[1],        //第二个点
        r = this.points[2],        //第三个点
        t = inputPoint.length; //获取已经点击的坐标数
      //下面的是移动点位后的坐标
      3 == t ? this.tempPoint4 = $this.getTempPoint4(o, e, r) : this.tempPoint4 = this.points[3],
        3 == t || 4 == t ? this.connPoint = $this.mid(o, e) : this.connPoint = this.points[4];
      var n, g;
      $this.isClockWise(o, e, r) ? (n = $this.getArrowPoints(o, this.connPoint, this.tempPoint4, !1), g = $this.getArrowPoints(this.connPoint, e, r, !0)) : (n = $this.getArrowPoints(e, this.connPoint, r, !1), g = $this.getArrowPoints(this.connPoint, o, this.tempPoint4, !0));
      var i = n.length,
        s = (i - 5) / 2,
        a = n.slice(0, s),
        l = n.slice(s, s + 5),
        u = n.slice(s + 5, i),
        c = g.slice(0, s),
        p = g.slice(s, s + 5),
        h = g.slice(s + 5, i);
      c = $this.getBezierPoints(c);
      var d = $this.getBezierPoints(h.concat(a.slice(1)));
      u = $this.getBezierPoints(u);
      var f = c.concat(p, d, l, u);
      var newArray = $this.array2Dto1D(f);
      result.controlPoint = [o, e, r, this.tempPoint4, this.connPoint];
      result.polygonalPoint = Cesium.Cartesian3.fromDegreesArray(newArray);
    }
    return result;
  }

  getTempPoint4 (t, o, e) {
    var $this = this;
    var r, n, g, i, s = $this.mid(t, o),
      a = $this.distance(s, e),
      l = $this.getAngleOfThreePoints(t, s, e);
    return l < Math.PI / 2 ? (n = a * Math.sin(l), g = a * Math.cos(l), i = $this.getThirdPoint(t, s, Math.PI / 2, n, !1), r = $this.getThirdPoint(s, i, Math.PI / 2, g, !0)) : l >= Math.PI / 2 && l < Math.PI ? (n = a * Math.sin(Math.PI - l), g = a * Math.cos(Math.PI - l), i = $this.getThirdPoint(t, s, Math.PI / 2, n, !1), r = $this.getThirdPoint(s, i, Math.PI / 2, g, !1)) : l >= Math.PI && l < 1.5 * Math.PI ? (n = a * Math.sin(l - Math.PI), g = a * Math.cos(l - Math.PI), i = $this.getThirdPoint(t, s, Math.PI / 2, n, !0), r = $this.getThirdPoint(s, i, Math.PI / 2, g, !0)) : (n = a * Math.sin(2 * Math.PI - l), g = a * Math.cos(2 * Math.PI - l), i = $this.getThirdPoint(t, s, Math.PI / 2, n, !0), r = $this.getThirdPoint(s, i, Math.PI / 2, g, !1)),
      r
  }

  mid (t, o) {
    return [(t[0] + o[0]) / 2, (t[1] + o[1]) / 2]
  }

  isClockWise (t, o, e) {
    return (e[1] - t[1]) * (o[0] - t[0]) > (o[1] - t[1]) * (e[0] - t[0])
  }

  getArrowPoints (t, o, e, r) {
    var $this = this;
    var doubleArrowDefualParam = {
      type: "doublearrow",
      headHeightFactor: .25,
      headWidthFactor: .3,
      neckHeightFactor: .85,
      fixPointCount: 4,
      neckWidthFactor: .15
    }
    this.type = doubleArrowDefualParam.type,
      this.headHeightFactor = doubleArrowDefualParam.headHeightFactor,
      this.headWidthFactor = doubleArrowDefualParam.headWidthFactor,
      this.neckHeightFactor = doubleArrowDefualParam.neckHeightFactor,
      this.neckWidthFactor = doubleArrowDefualParam.neckWidthFactor;
    var n = $this.mid(t, o),
      g = $this.distance(n, e),
      i = $this.getThirdPoint(e, n, 0, .3 * g, !0),
      s = $this.getThirdPoint(e, n, 0, .5 * g, !0);
    i = $this.getThirdPoint(n, i, Math.PI / 2, g / 5, r),
      s = $this.getThirdPoint(n, s, Math.PI / 2, g / 4, r);
    var a = [n, i, s, e],
      l = $this.getArrowHeadPoints(a, this.headHeightFactor, this.headWidthFactor, this.neckHeightFactor, this.neckWidthFactor),
      u = l[0],
      c = l[4],
      p = $this.distance(t, o) / $this.getBaseLength(a) / 2,
      h = $this.getArrowBodyPoints(a, u, c, p),
      d = h.length,
      f = h.slice(0, d / 2),
      E = h.slice(d / 2, d);
    return f.push(u),
      E.push(c),
      f = f.reverse(),
      f.push(o),
      E = E.reverse(),
      E.push(t),
      f.reverse().concat(l, E)
  }

  getArrowHeadPoints (t, o, e) {
    var $this = this;
    var doubleArrowDefualParam = {
      type: "doublearrow",
      headHeightFactor: .25,
      headWidthFactor: .3,
      neckHeightFactor: .85,
      fixPointCount: 4,
      neckWidthFactor: .15
    }
    this.type = doubleArrowDefualParam.type,
      this.headHeightFactor = doubleArrowDefualParam.headHeightFactor,
      this.headWidthFactor = doubleArrowDefualParam.headWidthFactor,
      this.neckHeightFactor = doubleArrowDefualParam.neckHeightFactor,
      this.neckWidthFactor = doubleArrowDefualParam.neckWidthFactor;
    var r = $this.getBaseLength(t),
      n = r * this.headHeightFactor,
      g = t[t.length - 1],
      i = ($this.distance(o, e), n * this.headWidthFactor),
      s = n * this.neckWidthFactor,
      a = n * this.neckHeightFactor,
      l = $this.getThirdPoint(t[t.length - 2], g, 0, n, !0),
      u = $this.getThirdPoint(t[t.length - 2], g, 0, a, !0),
      c = $this.getThirdPoint(g, l, Math.PI / 2, i, !1),
      p = $this.getThirdPoint(g, l, Math.PI / 2, i, !0),
      h = $this.getThirdPoint(g, u, Math.PI / 2, s, !1),
      d = $this.getThirdPoint(g, u, Math.PI / 2, s, !0);
    return [h, c, g, p, d];
  }

  getArrowBodyPoints (t, o, e, r) {
    var $this = this;
    for (var n = $this.wholeDistance(t), g = $this.getBaseLength(t), i = g * r, s = $this.distance(o, e), a = (i - s) / 2, l = 0, u = [], c = [], p = 1; p < t.length - 1; p++) {
      var h = $this.getAngleOfThreePoints(t[p - 1], t[p], t[p + 1]) / 2;
      l += $this.distance(t[p - 1], t[p]);
      var d = (i / 2 - l / n * a) / Math.sin(h),
        f = $this.getThirdPoint(t[p - 1], t[p], Math.PI - h, d, !0),
        E = $this.getThirdPoint(t[p - 1], t[p], h, d, !1);
      u.push(f), c.push(E)
    }
    return u.concat(c)
  }

  getBezierPoints (t) {
    if (t.length <= 2) return t;
    for (var o = [], e = t.length - 1, r = 0; 1 >= r; r += .01) {
      for (var n = 0, y = 0, g = 0; e >= g; g++) {
        var i = this.getBinomialFactor(e, g),
          s = Math.pow(r, g),
          a = Math.pow(1 - r, e - g);
        n += i * s * a * t[g][0], y += i * s * a * t[g][1]
      }
      o.push([n, y])
    }
    return o.push(t[e]), o
  }

  getBaseLength (t) {
    return Math.pow(this.wholeDistance(t), .99)
  }

  wholeDistance (t) {
    for (var o = 0, e = 0; e < t.length - 1; e++) o += this.distance(t[e], t[e + 1]);
    return o
  }

  getBinomialFactor (t, o) {
    return this.getFactorial(t) / (this.getFactorial(o) * this.getFactorial(t - o))
  }

  getFactorial (t) {
    if (1 >= t) return 1;
    if (2 == t) return 2;
    if (3 == t) return 6;
    if (4 == t) return 24;
    if (5 == t) return 120;
    for (var o = 1, e = 1; t >= e; e++) o *= e;
    return o
  }

  array2Dto1D (array) {
    var newArray = [];
    array.forEach(function (elt) {
      newArray.push(elt[0]);
      newArray.push(elt[1]);
    });
    return newArray;
  }

  distance (t, o) {
    return Math.sqrt(Math.pow(t[0] - o[0], 2) + Math.pow(t[1] - o[1], 2))
  }

  getAngleOfThreePoints (t, o, e) {
    var r = this.getAzimuth(o, t) - this.getAzimuth(o, e);
    return 0 > r ? r + 2 * Math.PI : r
  }

  getAzimuth (t, o) {
    var e, r = Math.asin(Math.abs(o[1] - t[1]) / this.distance(t, o));
    return o[1] >= t[1] && o[0] >= t[0] ? e = r + Math.PI : o[1] >= t[1] && o[0] < t[0] ? e = 2 * Math.PI - r : o[1] < t[1] && o[0] < t[0] ? e = r : o[1] < t[1] && o[0] >= t[0] && (e = Math.PI - r), e
  }

  getThirdPoint (t, o, e, r, n) {
    var g = this.getAzimuth(t, o),
      i = n ? g + e : g - e,
      s = r * Math.cos(i),
      a = r * Math.sin(i);
    return [o[0] + s, o[1] + a]
  }
}

  • 10
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

浩7_GIS

谢谢你

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值