Strange Issue With Entity Positioning

159 views
Skip to first unread message

martinc...@hotmail.com

unread,
Oct 14, 2019, 7:48:18 AM10/14/19
to cesium-dev
1. A concise explanation of the problem you're experiencing.

I have a 3D tileset set on top of the Cesium terrain. I am adding points and drawing a polyline between each pair with labels containing the distance, this mostly seems to be correct apart from some strange positioning that I'm seeing.

The point labels and line appear to be in the right place, but the height value of the points themselves seems to be off - the screenshots show the point labels on the 3D tileset and another shows the coloured points in the correct position, but the wrong height.

If I zoom out even further, the label that is meant to be positioned halfway between each pair of points is now underneath the terrain.

I am transforming the tileset itself on page load as it seems to be clashing with the terrain, so I am increasing the height by 8 to try and get it level with the terrain.


2. A minimal code example. If you've found a bug, this helps us reproduce and repair it.

var cesiumTerrainProvider = Cesium.createWorldTerrain();
var ellipsoidTerrainProvider = new Cesium.EllipsoidTerrainProvider();

var entities = [];
var points = [];
var linePoints = [];
var distanceLabels = [];
var line;

var viewer = new Cesium.Viewer('cesiumContainer', {
  animation: false,
  baseLayerPicker: false,
  terrainProvider: cesiumTerrainProvider,
  infoBox: true,
  scene3DOnly: true,
  timeline: false
});

var scene = viewer.scene;
var handler = new Cesium.ScreenSpaceEventHandler(scene.canvas);
scene.globe.depthTestAgainstTerrain = true;
scene.logarithmicDepthBuffer = true;

var tileset = viewer.scene.primitives.add(new Cesium.Cesium3DTileset({
  url: '/Scene/Production_1.json',
  ellipsoid: Cesium.Ellipsoid.UNIT_SPHERE
}));

var heightOffset = 8;

tileset.readyPromise.then(function(tileset) {
    // Position tileset
    var boundingSphere = tileset.boundingSphere;
    var cartographic = Cesium.Cartographic.fromCartesian(boundingSphere.center);
    var surface = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, 0.0);
    var offset = Cesium.Cartesian3.fromRadians(cartographic.longitude, cartographic.latitude, heightOffset);
    var translation = Cesium.Cartesian3.subtract(offset, surface, new Cesium.Cartesian3());
    tileset.modelMatrix = Cesium.Matrix4.fromTranslation(translation);
});

handler.setInputAction(function(click) {
  var position = viewer.scene.pickPosition(click.position);

  // there is a form step here but omitting it for brevity:

  var data = {
    position: position,
    uuid: 'point 1',
    name: 'point 1',
    description: 'point 1',
    colour: 'red'
  }

  addPoint(data);
  toggleModal();
  
}, Cesium.ScreenSpaceEventType.LEFT_DOUBLE_CLICK);

function addPoint(data) {

  var point = {
    id: data.uuid,
    name: data.name,
    description: data.description,
    position: data.position,
    allowPicking: true,
    point: {
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
      show: true,
      pixelSize: 10,
      color: Cesium.Color[data.colour].withAlpha(0.5),
      zIndex: 99
    },
    label: {
      disableDepthTestDistance: Number.POSITIVE_INFINITY,
      text: data.name,
      font: '9pt monospace',
      style: Cesium.LabelStyle.FILL_AND_OUTLINE,
      outlineWidth: 2,
      verticalOrigin: Cesium.VerticalOrigin.BOTTOM,
      pixelOffset: new Cesium.Cartesian2(0, -10)
    }
  };


  var pointObject = new Cesium.ReferenceProperty(viewer.entities, data.uuid, ['position']);
  linePoints.push(pointObject);
  points.push(point);
  entities.push(point);
  viewer.entities.add(point);

  // draw line with all points
  drawLine();
}

function drawLine() {

  // remove line
  removeLine();

  if (linePoints.length > 0) {
    line = viewer.entities.add({
      polyline: {
        id: 'Line 1',
        positions: new Cesium.PositionPropertyArray(linePoints),
        width: 5,
        heightReference: Cesium.HeightReference.RELATIVE_TO_GROUND,
        disableDepthTestDistance: Number.POSITIVE_INFINITY,
        material: new Cesium.PolylineOutlineMaterialProperty({
          color: Cesium.Color.RED.withAlpha(0.5),
          outlineColor: Cesium.Color.RED.withAlpha(0.5),
          outlineWidth: 2.5
        })
      }
    });

    setTimeout(function() {
      calculateDistance();
    }, 500);
  }
}

function calculateDistance() {
  // console.log('calculate distance');

  if (linePoints.length > 1) {
    // console.log(linePoints.length);

    for (var i = 0; i < (linePoints.length - 1); i++) {

      var start = linePoints[i]._targetEntity._position._value;
      var end = linePoints[i + 1]._targetEntity._position._value;
      var ellipsoid = scene.globe.ellipsoid;
      var geodesic = new Cesium.EllipsoidGeodesic(ellipsoid.cartesianToCartographic(start), ellipsoid.cartesianToCartographic(end));
      var midpoint = geodesic.interpolateUsingFraction(0.5, new Cesium.Cartographic());
      var distance = Cesium.Cartesian3.distance(start, end).toFixed(2);

      var entity = viewer.entities.add({
        position: Cesium.Cartographic.toCartesian(midpoint),
        label: {
          disableDepthTestDistance: Number.POSITIVE_INFINITY,
          show: true,
          showBackground: true,
          font: '12px monospace',
          horizontalOrigin: Cesium.HorizontalOrigin.LEFT,
          verticalOrigin: Cesium.VerticalOrigin.CENTER,
          pixelOffset: new Cesium.Cartesian2(-50, 0),
          scale: 1.0,
          text: distance + ' metres'
        }
      });

      distanceLabels.push(entity);

    }
  }
}

function removeLine() {
  if (line) {
    viewer.entities.remove(line);
    removeDistanceLabels();
  }

  line = null;
}

function removeDistanceLabels() {
  for (var i = 0; i < distanceLabels.length; i++) {
    viewer.entities.remove(distanceLabels[i]);
  }

  distanceLabels = [];
}


3. Context. Why do you need to do this? We might know a better way to accomplish your goal.

Attempting to add points to a 3D tileset and be able to measure horizontal and vertical distances between them.


4. The Cesium version you're using, your operating system and browser.

Cesium 1.62, OS X Mojave, Chrome.
Screenshot 2019-10-14 at 12.33.38.png
Screenshot 2019-10-14 at 12.35.02.png
Screenshot 2019-10-14 at 12.36.49.png

martinc...@hotmail.com

unread,
Oct 14, 2019, 8:39:52 AM10/14/19
to cesium-dev
hmm, I actually managed to fix the point position by removing the heightReference altogether, even though I tried NONE, CLAMP_TO_GROUND and RELATIVE_TO_GROUND - I thought (incorrectly?) that those were the three options and one would have been the default?

Still the same issue with the labels between points, looking at that just now.

Cheers,
Martin

martinc...@hotmail.com

unread,
Oct 14, 2019, 8:40:32 AM10/14/19
to cesium-dev
sorry, forgot image. 
Screenshot 2019-10-14 at 13.37.20.png

martinc...@hotmail.com

unread,
Oct 14, 2019, 9:18:43 AM10/14/19
to cesium-dev
think I've fixed the label positioning:

var start = linePoints[i]._targetEntity._position._value;
var end = linePoints[i + 1]._targetEntity._position._value;
var ellipsoid = scene.globe.ellipsoid;
var distance = Cesium.Cartesian3.distance(start, end).toFixed(2);

var midpoint = new Cesium.Cartesian3(Math.min(start.x, end.x) + (Math.max(start.x, end.x) - Math.min(start.x, end.x)) / 2, Math.min(start.y, end.y) + (Math.max(start.y, end.y) - Math.min(start.y, end.y)) / 2, Math.min(start.z, end.z) + (Math.max(start.z, end.z) - Math.min(start.z, end.z)) / 2);

 var entity = viewer.entities.add({
        position: midpoint,
        // etc.
});

Cheers,
Martin
Reply all
Reply to author
Forward
0 new messages