Search code examples
cesiumjs

How to use cesium.js to make a line with flowing texture like a picture


enter image description here

Like this picture, I tried to use the image material and GLSL combined with Cesium to achieve, but ultimately did not succeed.

The following code is my attempt, currently only can be drawn like this, the problem is that I can not change the color, can only change the color of the line by modifying the color of the picture:

enter image description here

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();
        }
        Cesium.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 &&
                  Property.equals(this._color, other._color))
        }
        Cesium.PolylineTrailLinkMaterialProperty = PolylineTrailLinkMaterialProperty;
        Cesium.Material.PolylineTrailLinkType = 'PolylineTrailLink';
        Cesium.Material.PolylineTrailLinkImage = "./sampledata/images/colors1.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(1.0, 1.0, 0.0, 0.5),
                    image: Cesium.Material.PolylineTrailLinkImage,
                    time: 0
                },
                source: Cesium.Material.PolylineTrailLinkSource
            },
            translucent: function (material) {
                return true;
            }
        });

        function parabolaEquation(options, resultOut) {
            //y=-(4h/L^2)*x^2+h 
            var h = options.height && options.height > 5000 ? options.height : 5000;
            var L = Math.abs(options.pt1.lon - options.pt2.lon) > Math.abs(options.pt1.lat - options.pt2.lat) ? Math.abs(options.pt1.lon - options.pt2.lon) : Math.abs(options.pt1.lat - options.pt2.lat);
            var num = options.num && options.num > 50 ? options.num : 50;
            var result = [];
            var dlt = L / num;
            if (Math.abs(options.pt1.lon - options.pt2.lon) > Math.abs(options.pt1.lat - options.pt2.lat)) {
                var delLat = (options.pt2.lat - options.pt1.lat) / num;
                if (options.pt1.lon - options.pt2.lon > 0) {
                    dlt = -dlt;
                }
                for (var i = 0; i < num; i++) {
                    var tempH = h - Math.pow((-0.5 * L + Math.abs(dlt) * i), 2) * 4 * h / Math.pow(L, 2);
                    var lon = options.pt1.lon + dlt * i;
                    var lat = options.pt1.lat + delLat * i;
                    result.push([lon, lat, tempH]);
                }
            } else {
                var delLon = (options.pt2.lon - options.pt1.lon) / num;
                if (options.pt1.lat - options.pt2.lat > 0) {
                    dlt = -dlt;
                }
                for (var i = 0; i < num; i++) {
                    var tempH = h - Math.pow((-0.5 * L + Math.abs(dlt) * i), 2) * 4 * h / Math.pow(L, 2);
                    var lon = options.pt1.lon + delLon * i;
                    var lat = options.pt1.lat + dlt * i;
                    result.push([lon, lat, tempH]);
                }
            }
            if (resultOut != undefined) {
                resultOut = result;
            }
            return result;
        }

        var isAdd = false;
        var material = null;
        var center = { lon: 114.302312702, lat: 30.598026044 }viewer.entities.add({
                            name: 'PolylineTrailLink' + j,
                            polyline: {
                                positions: Cesium.Cartesian3.fromDegreesArrayHeights(pointArr),
                                width: 2,
                                material: material
                            }
                        });

Solution

  • Sometimes a faded path can be emulated by placing a "stripe" material across a line, rotated so the entire line is just the transition from one stripe color to the other.

    Sandcastle Demo - This is a modified version of the Interpolation Demo, with a faded yellow line.

    path : {
        resolution : 1,
        // ************************************************************
        // This material uses a single stripe, turned sideways, to fade
        // the color across a length of the line.
        // ************************************************************
        material : new Cesium.StripeMaterialProperty({
            // The newest part of the line is bright yellow.
            evenColor: Cesium.Color.YELLOW,
            // The oldest part of the line is yellow with a low alpha value.
            oddColor: Cesium.Color.YELLOW.withAlpha(0.1),
            repeat: 1,
            offset: 0.25,
            orientation: Cesium.StripeOrientation.VERTICAL
        }),
        leadTime: 0,
        trailTime: 60 * 2,
        width : 10
    }