| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327 |
- /**
- * @Author: Caven
- * @Date: 2022-05-28 10:25:24
- */
-
- import { Cesium } from '../../../namespace'
- import Overlay from '../Overlay'
- import State from '../../state/State'
- import Parse from '../../parse/Parse'
- import { Transform } from '../../transform'
- import { Util } from '../../utils'
- import { IMG_PARTICLES } from '../../images/base64'
-
- const DEF_STYLE = {
- color: Cesium.Color.ORANGE,
- }
-
- class LightCylinderPrimitive extends Overlay {
- constructor(center, length, topRadius, bottomRadius) {
- super()
- this._center = Parse.parsePosition(center)
- this._length = length || 100
- this._topRadius = topRadius || 1
- this._bottomRadius = bottomRadius || 50
- this._delegate = new Cesium.PrimitiveCollection()
- this._style = { ...DEF_STYLE }
- this._state = State.INITIALIZED
- }
-
- get type() {
- return Overlay.getOverlayType('light-cylinder-primitive')
- }
-
- set center(position) {
- this._center = Parse.parsePosition(position)
- this._updatePrimitives()
- }
-
- get center() {
- return this._center
- }
-
- set length(length) {
- this._length = length
- this._updatePrimitives()
- }
-
- get length() {
- return this._length
- }
-
- set topRadius(topRadius) {
- this._topRadius = topRadius
- this._updatePrimitives()
- }
-
- get topRadius() {
- return this._topRadius
- }
-
- set bottomRadius(bottomRadius) {
- this._bottomRadius = bottomRadius
- this._updatePrimitives()
- }
-
- get bottomRadius() {
- return this._bottomRadius
- }
-
- /**
- *
- * @param center
- * @param radius
- * @return {[]}
- * @private
- */
- _computeEllipsePositions(center, radius) {
- let cep = Cesium.EllipseGeometryLibrary.computeEllipsePositions(
- {
- center: Transform.transformWGS84ToCartesian(center),
- semiMajorAxis: radius,
- semiMinorAxis: radius,
- rotation: 0,
- granularity: 0.005,
- },
- false,
- true
- )
- let pnts = Cesium.Cartesian3.unpackArray(cep.outerPositions)
- pnts.push(pnts[0])
- return pnts
- }
-
- /**
- *
- * @param topPts
- * @param bottomPts
- * @param height
- * @return {Cesium.GeometryInstance}
- */
- _createCylinderInstance(topPts, bottomPts, height) {
- let newpts = bottomPts.slice()
- let length = bottomPts.length
- let len_2 = 2 * length
- let sts = []
- let st_interval = 1.0 / (length - 1)
- let define_indices = []
- let ep = []
- const addHeight = (p, alt = 0) => {
- let c = Cesium.Cartographic.fromCartesian(p)
- c.height += alt
- return Cesium.Cartographic.toCartesian(c)
- }
- for (let i = 0; i < length; i++) {
- ep.push(addHeight(topPts[i], height))
- sts.push(i * st_interval, 0)
- let i_1 = i + 1
- let i_11 = (i + 1) % length
- let len_2_i_1 = len_2 - i_1
- define_indices.push(...[len_2_i_1 - 1, len_2_i_1, i])
- define_indices.push(...[i, i_11, len_2_i_1 - 1])
- }
-
- for (let i in ep) {
- newpts.push(ep[length - i - 1])
- sts.push(1 - i * st_interval, 1)
- }
-
- let polygon = Cesium.PolygonGeometry.createGeometry(
- new Cesium.PolygonGeometry({
- polygonHierarchy: new Cesium.PolygonHierarchy(newpts),
- perPositionHeight: true,
- })
- )
- polygon.indices = define_indices
- polygon.attributes.st.values = sts
- return new Cesium.GeometryInstance({
- geometry: polygon,
- })
- }
-
- /**
- *
- * @return {HTMLCanvasElement}
- * @private
- */
- _getCircleImage() {
- let canvas = document.createElement('canvas')
- canvas.width = 512
- canvas.height = 512
- let ctx = canvas.getContext('2d')
- ctx.fillStyle = 'rgba(255,255,255,0)'
- ctx.strokeStyle = 'rgba(255, 255, 255,255)'
- ctx.setLineDash([50, 50])
- ctx.lineWidth = 30
- ctx.beginPath()
- ctx.arc(256, 256, 150, 0, Math.PI * 2, true)
- ctx.stroke()
- ctx.restore()
- return canvas
- }
-
- /**
- *
- * @param image
- * @return {HTMLCanvasElement}
- * @private
- */
- _getParticlesImage(image) {
- let canvas = document.createElement('canvas')
- canvas.width = 64
- canvas.height = 256
- let ctx = canvas.getContext('2d')
- ctx.clearRect(0, 0, 64, 256)
- ctx.drawImage(image, 0, 0)
- ctx.drawImage(image, 33, 0)
- return canvas
- }
-
- /**
- *
- * @private
- */
- _updatePrimitives() {
- this._delegate.removeAll()
-
- const isGroud = this._center.alt === 0
-
- let topPositions = this._computeEllipsePositions(
- this._center,
- this._topRadius
- )
- let innerBottomPostions = this._computeEllipsePositions(
- this._center,
- this._bottomRadius * 0.7
- )
- let bottomPositions = this._computeEllipsePositions(
- this._center,
- this._bottomRadius
- )
-
- // update buttom circle
- const circleOpt = {
- geometryInstances: new Cesium.GeometryInstance({
- geometry: new Cesium.PolygonGeometry({
- polygonHierarchy: new Cesium.PolygonHierarchy(
- this._computeEllipsePositions(this._center, this._bottomRadius * 2)
- ),
- perPositionHeight: !isGroud,
- }),
- asynchronous: false,
- }),
- }
-
- // ring
- let ring = isGroud
- ? new Cesium.GroundPrimitive(circleOpt)
- : new Cesium.Primitive(circleOpt)
-
- ring.appearance = new Cesium.EllipsoidSurfaceAppearance({
- material: Cesium.Material.fromType(Cesium.Material.CircleRingType, {
- color: this._style.color,
- }),
- })
-
- // circle
- let circle = isGroud
- ? new Cesium.GroundPrimitive(circleOpt)
- : new Cesium.Primitive(circleOpt)
-
- circle.appearance = new Cesium.EllipsoidSurfaceAppearance({
- material: Cesium.Material.fromType(Cesium.Material.CircleRotateType, {
- color: this._style.color,
- image: this._getCircleImage(),
- }),
- })
-
- // cylinder
- let cylinder = new Cesium.Primitive({
- geometryInstances: this._createCylinderInstance(
- topPositions,
- innerBottomPostions,
- this._length
- ),
- appearance: new Cesium.EllipsoidSurfaceAppearance({
- material: Cesium.Material.fromType(Cesium.Material.CylinderFadeType, {
- color: this._style.color,
- }),
- }),
- asynchronous: false,
- })
-
- if (isGroud) {
- Cesium.GroundPrimitive.initializeTerrainHeights().then(() => {
- this._delegate.add(ring)
- this._delegate.add(circle)
- this._delegate.add(cylinder)
- })
- } else {
- this._delegate.add(ring)
- this._delegate.add(circle)
- this._delegate.add(cylinder)
- }
-
- // particles
- Cesium.Resource.fetchImage({ url: IMG_PARTICLES }).then((image) => {
- let particles = new Cesium.Primitive({
- geometryInstances: this._createCylinderInstance(
- topPositions,
- bottomPositions,
- this._length
- ),
- appearance: new Cesium.EllipsoidSurfaceAppearance({
- material: Cesium.Material.fromType(
- Cesium.Material.CylinderParticlesType,
- {
- color: this._style.color,
- image: this._getParticlesImage(image),
- }
- ),
- }),
- asynchronous: false,
- })
- this._delegate.add(particles)
- })
- }
-
- /**
- *
- * @private
- */
- _mountedHook() {
- /**
- * set the positions
- */
- this.center = this._center
- }
-
- /**
- *
- * @param frameState
- */
- update(frameState) {
- this._delegate.update(frameState)
- }
-
- /**
- *
- * @param style
- * @returns {LightCylinderPrimitive}
- */
- setStyle(style) {
- if (!style || Object.keys(style).length === 0) {
- return this
- }
- Util.merge(this._style, style)
- return this
- }
-
- destroy() {
- return Cesium.destroyObject(this)
- }
- }
-
- Overlay.registerType('light-cylinder-primitive')
-
- export default LightCylinderPrimitive
|