cesium 生成抛物线 流动线

效果图

cesium 生成抛物线 流动线_第1张图片

代码思路,根据起点终点坐标以及需要设置的抛物线高度生成抛物线坐标串,然后根据坐标串生成cesium实体线,并修改材质为流动线 

viewer.entities.removeById('pwxline')
      viewer.entities.removeById('verticalPwxline')
      let startPoint = this.clickPoint
      let endPoint = row.geoPositon.split(',')
      let height = this.getFlatternDistance(startPoint.lat, startPoint.lng, parseFloat(endPoint[1]), parseFloat(endPoint[0]))//高度是根据起始点距离的一半
      let positions = this.parabolaEquation({//生成抛物线代码
        startPoint: { lng: parseFloat(endPoint[0]), lat: parseFloat(endPoint[1]) },
        endPoint: { lng: startPoint.lng, lat: startPoint.lat },
        height: height / 2,
        num: 100
      })
      this.positionsParabola2.push(positions) //获取抛物线坐标串
      let postionarry = []
      for (let i = 0; i < positions.length; i++) {
        postionarry.push(positions[i].lng, positions[i].lat, positions[i].height)
      }

      //let entity = viewer.entities.getOrCreateEntity(this.PDPointSelectID)
//因为流动线材质代码
      require('../../../../assets/plugins/PolylineTrailLinkMaterial')

      let model = viewer.entities.add({
        id: 'pwxline',
        name: 'polyline',
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArrayHeights(postionarry),
          width: 20,
          material: new Cesium.PolylineTrailLinkMaterialProperty(Cesium.Color.AQUA, 5000)//修改抛物线材质
        }
      })

      let verticalPwxlinePosition = []
      verticalPwxlinePosition.push(parseFloat(endPoint[0]), parseFloat(endPoint[1]), 0)
      verticalPwxlinePosition.push(parseFloat(endPoint[0]), parseFloat(endPoint[1]), 55)
      viewer.entities.add({
        id: 'verticalPwxline',
        name: 'verticalPwxline',
        polyline: {
          positions: Cesium.Cartesian3.fromDegreesArrayHeights(verticalPwxlinePosition),
          width: 5,
          material: Cesium.Color.AQUA.withAlpha(0.5)
        }
      })

      viewer.flyTo(model, {
        complete: () => {}
      })

生成抛物线代码

 parabolaEquation(options) {
      // 方程 y=-(4h/L^2)*x^2+h h:顶点高度 L:横纵间距较大者
      const h = options.height && options.height > 50 ? options.height : 50
      const L =
        Math.abs(options.startPoint.lng - options.endPoint.lng) > Math.abs(options.startPoint.lat - options.endPoint.lat)
          ? Math.abs(options.startPoint.lng - options.endPoint.lng)
          : Math.abs(options.startPoint.lat - options.endPoint.lat)
      const num = options.num && options.num > 50 ? options.num : 50
      const result = []
      let dlt = L / num
      if (Math.abs(options.startPoint.lng - options.endPoint.lng) > Math.abs(options.startPoint.lat - options.endPoint.lat)) {
        //以 lng 为基准
        const delLat = (options.endPoint.lat - options.startPoint.lat) / num
        if (options.startPoint.lng - options.endPoint.lng > 0) {
          dlt = -dlt
        }
        for (let i = 0; i < num; i++) {
          const tempH = h - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * h) / Math.pow(L, 2)
          const lng = options.startPoint.lng + dlt * i
          const lat = options.startPoint.lat + delLat * i
          result.push({ lng, lat, height: tempH })
        }
      } else {
        //以 lat 为基准
        let dellng = (options.endPoint.lng - options.startPoint.lng) / num
        if (options.startPoint.lat - options.endPoint.lat > 0) {
          dlt = -dlt
        }
        for (let i = 0; i < num; i++) {
          const tempH = h - (Math.pow(-0.5 * L + Math.abs(dlt) * i, 2) * 4 * h) / Math.pow(L, 2)
          const lng = options.startPoint.lng + dellng * i
          const lat = options.startPoint.lat + dlt * i
          result.push({ lng, lat, height: tempH })
        }
      }
      // 落地
      result.push({ lng: options.endPoint.lng, lat: options.endPoint.lat, height: options.endPoint.height || 0 })
      return result
    },

流动线代码

// 流动线纹理
function PolylineTrailLinkMaterialProperty(color, duration) {
  this._definitionChanged = new Cesium.Event()
  this._color = undefined
  this._colorSubscription = undefined
  this.color = color
  this.duration = duration
  this._time = new Date().getTime()
}

Object.defineProperties(PolylineTrailLinkMaterialProperty.prototype, {
  isConstant: {
    get: function () {
      return false
    }
  },
  definitionChanged: {
    get: function () {
      return this._definitionChanged
    }
  },
  color: Cesium.createPropertyDescriptor('color')
})

PolylineTrailLinkMaterialProperty.prototype.getType = function (time) {
  return 'PolylineTrailLink'
}
PolylineTrailLinkMaterialProperty.prototype.getValue = function (time, result) {
  if (!Cesium.defined(result)) {
    result = {}
  }
  result.color = Cesium.Property.getValueOrClonedDefault(this._color, time, Cesium.Color.WHITE, result.color)
  result.image = Cesium.Material.PolylineTrailLinkImage
  result.time = ((new Date().getTime() - this._time) % this.duration) / this.duration
  return result
}
PolylineTrailLinkMaterialProperty.prototype.equals = function (other) {
  return this === other || (other instanceof PolylineTrailLinkMaterialProperty && Cesium.Property.equals(this._color, other._color))
}

Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty
Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink'
Cesium.Material.PolylineTrailLinkImage = '/static/images/a3.png' //图片 图片为箭头
Cesium.Material.PolylineTrailLinkSource =
  'czm_material czm_getMaterial(czm_materialInput materialInput)\n\
{\n\
    czm_material material = czm_getDefaultMaterial(materialInput);\n\
    vec2 st = materialInput.st;\n\
    vec4 colorImage = texture2D(image, vec2(fract(st.s - time), st.t));\n\
    material.alpha = colorImage.a * color.a;\n\
    material.diffuse = (colorImage.rgb+color.rgb)/2.0;\n\
    return material;\n\
}'

Cesium.Material._materialCache.addMaterial(Cesium.Material.PolylineTrailLinkType, {
  fabric: {
    type: Cesium.Material.PolylineTrailLinkType,
    uniforms: {
      color: new Cesium.Color(255.0, 255.0, 255.0, 1),
      image: Cesium.Material.PolylineTrailLinkImage,
      time: 0
    },
    source: Cesium.Material.PolylineTrailLinkSource
  },
  translucent: function (material) {
    return true
  }
})

计算起始点距离代码

 //计算两点间距离
    getFlatternDistance(lat1, lng1, lat2, lng2) {
      var EARTH_RADIUS = 6378137.0 //单位M
      var PI = Math.PI

      function getRad(d) {
        return (d * PI) / 180.0
      }
      var f = getRad((lat1 + lat2) / 2)
      var g = getRad((lat1 - lat2) / 2)
      var l = getRad((lng1 - lng2) / 2)

      var sg = Math.sin(g)
      var sl = Math.sin(l)
      var sf = Math.sin(f)

      var s, c, w, r, d, h1, h2
      var a = EARTH_RADIUS
      var fl = 1 / 298.257

      sg = sg * sg
      sl = sl * sl
      sf = sf * sf

      s = sg * (1 - sl) + (1 - sf) * sl
      c = (1 - sg) * (1 - sl) + sf * sl

      w = Math.atan(Math.sqrt(s / c))
      r = Math.sqrt(s * c) / w
      d = 2 * w * a
      h1 = (3 * r - 1) / 2 / c
      h2 = (3 * r + 1) / 2 / s

      return d * (1 + fl * (h1 * sf * (1 - sg) - h2 * (1 - sf) * sg))
    },

你可能感兴趣的:(cesium)