Volume Measurement in Cesium

CesiumJS is an open-source JavaScript library for creating 3D globes and maps in web browsers. Developed by he Cesium team at AGI (Analytical Graphics, Inc.), it is built on top of WebGL and provides a wide range of features for creating interactive and visually-appealing geospatial applications. It is used in a variety of industries, including GIS, defense, and energy, and can be integrated with other libraries and frameworks to create custom solutions.

The Problem

Limited Material on the Internet

Finding a solution to measure volume in CesiumJS can be challenging, as the documentation and reference materials available on the internet may not be specific to this task. Additionally, the Cesium community, while active and helpful, may not have a ready-made solution for measuring volume. To measure volume, it may be necessary to use a combination of CesiumJS’ built-in functionality and custom code. The process may involve using the 3D terrain and entities provided by CesiumJS, and utilizing concepts such as spatial referencing, polygon clipping, and volumetric calculations. It may also require a good understanding of the underlying mathematical concepts, as well as experience with JavaScript and web development. Due to these complexities, it may be necessary to seek out specialized expertise or consulting services to implement a solution to measure volume in CesiumJS.

Irregular shapes in Cesium JS

One of the most challenging aspects of volume calculation in CesiumJS is dealing with irregular shapes and structures. These types of shapes do not have a fixed or well-defined shape, making it difficult to calculate their volume. However, one approach to solving this problem is to use a near-approximate method by wrapping the irregular shape into a regular shape such as a cylinder or a cuboid.

This method involves first identifying the irregular shape’s bounding box or a minimum bounding volume which can be a cylinder or cuboid. Once the irregular shape is wrapped in the regular shape by creating a UI to resize the dimensions of the cylinder or cuboid entity, the volume of the regular shape can be calculated using standard mathematical formulas. The volume of the irregular shape can then be approximated as the volume of the regular shape. This method can be useful for shapes that have a high degree of symmetry or are close to being symmetrical. However, it should be noted that the more irregular the shape, the less accurate this method will be.

This method can be implemented in CesiumJS by using the 3D terrain and entities provided by the library and utilizing concepts such as spatial referencing and volumetric calculations.

 

Looking for Cesium Development Team?

Share the details of your request and we will provide you with a full-cycle team under one roof.

Get an Estimate

 

Sample Code

Cylinder Volume calculation

let entity = this._viewer.entities.add({
   position: this.getCartesianPosition(click.position),
   show: true,
   cylinder: {
       length: 80,
       topRadius: 40,
       bottomRadius: 40,
       material: Cesium.Color.BLUE.withAlpha(0.5)
   }
});


this.cylinderVolumeEntity = entity;


changeVolumeEntityHeight(height) {
   this.props.cylinderVolumeEntity.cylinder = new Cesium.CylinderGraphics({
       length: height,
       topRadius:this.props.cylinderVolumeEntity.cylinder._bottomRadius._value,
       bottomRadius:this.props.cylinderVolumeEntity.cylinder._bottomRadius._value,
       material: Cesium.Color.BLUE.withAlpha(0.5)
   });
}

changeVolumeEntityRadius(radius) {
   this.cylinderVolumeEntity.cylinder = new Cesium.CylinderGraphics({
       length: this.cylinderVolumeEntity.cylinder._length._value,
       topRadius:radius,
       bottomRadius:radius,
       material: Cesium.Color.BLUE.withAlpha(0.5)
   });
}

saveChangesCylinderVolume() {
   let annotation = new Annotation();
   annotation.type = AnnotationType.CYLINDER_VOLUME;
   annotation.length = this.cylinderVolumeEntity.cylinder._length._value;
   annotation.radius = this.cylinderVolumeEntity.cylinder._bottomRadius._value;
   annotation.points.push(this.cylinderVolumeEntity.position._value);
   //volume of cylinder = V = π * r * r * h
   let volume = Cesium.Math.PI * this.cylinderVolumeEntity.cylinder._bottomRadius._value * this.cylinderVolumeEntity.cylinder._bottomRadius._value * this.cylinderVolumeEntity.cylinder._length._value;
   annotation.label = volume.toFixed(4) + ' cubic m';

case:
   AnnotationType.CYLINDER_VOLUME:

                entity = {
                    id: annotation.entityID,
                    position: annotation.points[0],
                    cylinder: {
                        length: annotation.length,
                        topRadius: annotation.radius,
                        bottomRadius: annotation.radius,
                        material: Cesium.Color.BLUE.withAlpha(0.5)
                    },
                    label: {
                        text: annotation.label,
                        style: Cesium.LabelStyle.FILL_AND_OUTLINE,
                        fillColor: Cesium.Color.WHITE,
                        backgroundColor: Cesium.Color.BLACK,
                        showBackground: true,
                        scale: 0.6,
                        pixelOffset: new Cesium.Cartesian2(0, -20),
                        eyeOffset: new Cesium.Cartesian3(0, 0, -0.1),
                        disableDepthTestDistance: Number.POSITIVE_INFINITY,
                        scaleByDistance: new Cesium.NearFarScalar(400, 1.0, 4000, 0.0),
                    },
                    type: "annotationCylinderVolume",
                    annotation: annotation
                };

   this.viewer.entities.removeById(this.cylinderVolumeEntity.id);
}
<Table size='sm' striped className='toolbar_info_table'>
   <tbody>
       <tr>
           <td>Cylinder Height: </td>
           <td>
               <FormGroup>
                   <Input id={GenericIdAndClass.CYLINDER_VOLUME_HEIGHT}
                          type="number"
                          name="height"
                          onChange={e => this.changeVolumeEntityHeight(e.target.value)}
                          value={this.cylinderVolumeEntity.cylinder._length._value} />
               </FormGroup>
           </td>
       </tr>
       <tr>
           <td>Cylinder radius: </td>
           <td>
               <FormGroup>
                   <Input id={GenericIdAndClass.CYLINDER_VOLUME_RADIUS}
                          type="number"
                          name="height"
                          onChange={e => this.changeVolumeEntityRadius(e.target.value)}
                          value={this.cylinderVolumeEntity.cylinder._bottomRadius._value} />
               </FormGroup>
           </td>
       </tr>
       <tr>
           <td></td>
           <td>
               <FormGroup>
                   <Input id={GenericIdAndClass.LAYER_INFO_MAX_ZOOM_IN}
                          type="button"
                          className={"form-control"}
                          value= {"Save Changes"}
                          onClick={e => this.saveChangesCylinderVolume()}
                   />
               </FormGroup>
           </td>
       </tr>
   </tbody>
</Table>

Result

Volume Measurement in Cesium

Share this article

Related Posts