orientation?

I have an array of “orientations” in a variable “orient” [, 120], [, 130], [, 150]

How can I set this array or transform to so that I can set the “orientation” property of an entity such that it knows what orientation is at any given point in time when I use the timeslider?

The following does not work:
var prop = new Cesium.SampledProperty(Number);

var mytimes = ;

var myheads = ;

// loop thorough each item in “orient” and do the following:

for(var i = 0; i < orient.length; i++) {

var mytime = Cesium.JulianDate.fromDate(orient[i][0]);

var heading = Cesium.Math.toRadians(orient[i][1]);

mytimes.push(mytime);

myheads.push(heading);

}

prop.addSamples(mytimes, myheads)

In my entity I set:

orientation: prop

I keep geting a “RangeError: Invalid array length”, what is the right way to do this?

Orientation is not a number, it is a Quaternion. If you’d like to orient a model with heading only, you need to compute a Quaternion from it. You need the position at the time of the heading for the computation (and you can just use 0 for pitch and roll). If your positions and orientation times don’t line up, then you can create a position property first and use getValue(time) to get the position for each heading time. I wrote up an issue for us to add HeadingOrientationProperty to handle this use case directly (similar to what VelocityOrientationProperty already does).

Here’s some pseudo-code mirrors from your own code.

var myPositions = //parallel with orient array

var prop = new Cesium.SampledProperty(Quaternion);

var mytimes = ;

var myheads = ;

// loop thorough each item in “orient” and do the following:

for(var i = 0; i < orient.length; i++) {

var mytime = Cesium.JulianDate.fromDate(orient[i][0]);

var heading = Cesium.Math.toRadians(orient[i][1]);

mytimes.push(mytime);

myheads.push(Transforms.headingPitchRollQuaternion(myPositions[i], heading, 0, 0));

}

prop.addSamples(mytimes, myheads)

You need to create a new Cesium.SampledProperty of type quaternion

Ex: var orientation = new Cesium.SampledProperty(Cesium.Quaternion);

Then push quaternions to an array:

quaternionArray = ;

var quaternion = new Cesium.Quaternion();

quaternionArray.push(quaternion);

Finally add the times and quaternions to the sampled property:

orientation.addSamples(times, quaternionArray);

Note: You aren’t able to define an orientation with just a heading angle, instead try using this to create quaternions from a heading, pitch and roll

https://github.com/AnalyticalGraphicsInc/cesium/blob/1.8/Source/Core/Transforms.js#L408

Thank you both. Is there a method/way to get the “number of samples” in a SampledProperty? Also, is there a way to get the “current sample index” that the entity is currently on after load?

Hello everyone,

thank you for your solution. I worked like a charm !! It is a pity that there is no documentation on SampledProperty used with Cesium.Quaternion in the official website. Also there is no example with in the sandCastle.

I modified a few lines of one code example to illustrate orientation possibilities in cesium (copy/paste the code in HTML and JAVASCRIPT tabs in Cesium sandCastle :

HTML CODE :
<style>
    @import url(../templates/bucket.css);
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div id="toolbar">
    <div id="interpolationMenu"></div>
</div>

JAVASCRIPT CODE :
var viewer = new Cesium.Viewer('cesiumContainer', {
    terrainProviderViewModels : , //Disable terrain changing
    infoBox : false, //Disable InfoBox widget
    selectionIndicator : false //Disable selection indicator
});

//Enable lighting based on sun/moon positions
viewer.scene.globe.enableLighting = true;

//Use STK World Terrain
viewer.terrainProvider = new Cesium.CesiumTerrainProvider({
    url : ‘https://assets.agi.com/stk-terrain/world’,
    requestWaterMask : true,
    requestVertexNormals : true
});

//Enable depth testing so things behind the terrain disappear.
viewer.scene.globe.depthTestAgainstTerrain = true;

//Set the random number seed for consistent results.
Cesium.Math.setRandomNumberSeed(3);

//Set bounds of our simulation time
var start = Cesium.JulianDate.fromDate(new Date(2015, 2, 25, 16));
var stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate());

//Make sure viewer is at the desired time.
viewer.clock.startTime = start.clone();
viewer.clock.stopTime = stop.clone();
viewer.clock.currentTime = start.clone();
viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP; //Loop at the end
viewer.clock.multiplier = 10;

//Set timeline to simulation bounds
viewer.timeline.zoomTo(start, stop);

var lon = 0;
var lat = 45;
var radius = 0.03;

//Generate a random circular pattern with varying heights.

    var positionProperty = new Cesium.SampledPositionProperty();
    var orientationProperty = new Cesium.SampledProperty(Cesium.Quaternion);
    
    for (var i = 0; i <= 360; i += 45) {
        var radians = Cesium.Math.toRadians(i);
        var time = Cesium.JulianDate.addSeconds(start, i, new Cesium.JulianDate());
        
        // compute positions
        var position = Cesium.Cartesian3.fromDegrees(lon + (radius * 1.5 * Math.cos(radians)), lat + (radius * Math.sin(radians)), Cesium.Math.nextRandomNumber() * 500 + 1750);
        positionProperty.addSample(time, position);
         
        // compute orientations
        var heading = Cesium.Math.toRadians(90+i);
        var pitch = Cesium.Math.toRadians(20);
        var roll = Cesium.Math.toRadians(0);
        var hpRoll = new Cesium.HeadingPitchRoll(heading,pitch,roll);
        var orientation = Cesium.Transforms.headingPitchRollQuaternion(position,hpRoll);
        orientationProperty.addSample(time, orientation);
               
        //Also create a point for each sample we generate.
        viewer.entities.add({
            position : position,
            point : {
                pixelSize : 8,
                color : Cesium.Color.TRANSPARENT,
                outlineColor : Cesium.Color.YELLOW,
                outlineWidth : 3
            }
        });
    }

//Actually create the entity
var entity = viewer.entities.add({

    //Set the entity availability to the same interval as the simulation time.
    availability : new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
        start : start,
        stop : stop
    })]),

    //Use our computed positions
    position : positionProperty,

    //Automatically compute orientation based on position movement.
    orientation : orientationProperty,

    //Load the Cesium plane model to represent the entity
    model : {
        uri : '../../SampleData/models/CesiumAir/Cesium_Air.gltf',
        minimumPixelSize : 64
    },

    //Show the path as a pink line sampled in 1 second increments.
    path : {
        resolution : 1,
        material : new Cesium.PolylineGlowMaterialProperty({
            glowPower : 0.1,
            color : Cesium.Color.YELLOW
        }),
        width : 10
    }
});

//Add button to view the path from the top down
Sandcastle.addDefaultToolbarButton('View Top Down', function() {
    viewer.trackedEntity = undefined;
    viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(0, Cesium.Math.toRadians(-90)));
});

//Add button to view the path from the side
Sandcastle.addToolbarButton('View Side', function() {
    viewer.trackedEntity = undefined;
    viewer.zoomTo(viewer.entities, new Cesium.HeadingPitchRange(Cesium.Math.toRadians(-90), Cesium.Math.toRadians(-15), 7500));
});

//Add button to track the entity as it moves
Sandcastle.addToolbarButton('View Aircraft', function() {
    viewer.trackedEntity = entity;
});

//Add a combo box for selecting each interpolation mode.
Sandcastle.addToolbarMenu([{
    text : 'Interpolation: Linear Approximation',
    onselect : function() {
        entity.position.setInterpolationOptions({
            interpolationDegree : 1,
            interpolationAlgorithm : Cesium.LinearApproximation
        });
    }
}, {
    text : 'Interpolation: Lagrange Polynomial Approximation',
    onselect : function() {
        entity.position.setInterpolationOptions({
            interpolationDegree : 5,
            interpolationAlgorithm : Cesium.LagrangePolynomialApproximation
        });
    }
}, {
    text : 'Interpolation: Hermite Polynomial Approximation',
    onselect : function() {
        entity.position.setInterpolationOptions({
            interpolationDegree : 2,
            interpolationAlgorithm : Cesium.HermitePolynomialApproximation
        });
    }
}], 'interpolationMenu');

Hi Florent,

Glad you worked it out and thanks for your examples! We’re always trying to extend our collection of learning materials and there’s definitely plenty of room for improvement. I’ve added this idea to our Cesium Learning Materials update thread here: https://github.com/AnalyticalGraphicsInc/cesium/issues/5207

Please feel free to contribute if you have any other thoughts on what would make Cesium easier to learn!

Cheers,

  • Rachel