Search code examples
kmlcesiumjs

Parsing Entities in Cesium


I have around 7k-8k placemarks in KML. I have to parse through each of the placemarks in cesium by importing the KML file. I have tried parsing through EntityCollection.values array but since not all the entities are placemarks, I find no other way of parsing through all placemark entities in Cesium.

I would like to know the following:

  1. How are entities grouped in EntityCollection.values?
  2. Is there any other way to access all placemark entities which are created when a KML file is imported?

I have tried to parse through the EntityCollection.values array and found out that only after an unspecified number of entities do the placemarks come.


Solution

  • When Cesium KmlDataSource loads a KML source, it flattens out the structure of the KML features such that Containers (Documents and Folders) and Placemarks are all added to an Entity Collection as an array in the order they appear in the source KML. All except the root-level container are populated in the array.

    Here is an example to load a KML source into Cesium and iterate over the entities.

    var url = "mykml.kml"; // source KML file path or URL
    viewer.dataSources
        .add(Cesium.KmlDataSource.load(url))
        .then(
                function (kmlData) {
                    parseElements(kmlData.entities)                
                }
            );
    
        function parseElements(entities) {      
            var e;
            var pointCount = 0;
            var values = entities.values;
            console.dir(values); // debug the array
            for (var i = 0; i < values.length; i++) {
                e = values[i];
                if (Cesium.defined(e.position)) {
                    // Placemark with Point geometry
                    pointCount++;
                }
                else if (Cesium.defined(e.polyline)) {
                    // Placemark with LineString geometry               
                }
                else if (Cesium.defined(e.polygon)) {
                    // Placemark with Polygon geometry
                }
                // check for other conditions
            }
            console.log(pointCount); // dump # of point placemarks
            viewer.flyTo(entities);     
        }
    

    If the source KML has ExtendedData then you can access this extended data via the entity's kml property which is a KmlFeatureData object.

    Example:

    <Placemark>
       ...
       <ExtendedData>
          <Data name="holeNumber">
            <value>1</value>
          </Data>
          <Data name="holeYardage">
            <value>234</value>
          </Data>
          <Data name="holePar">
            <value>4</value>
          </Data>
      </ExtendedData>
    </Placemark>
    

    If var "e" is an entity created from the KML above then the code snippet below will output value=234.

      var data = e.kml.extendedData;
      if (Cesium.defined(data)) {
        console.log("value=", data.holeYardage.value);      
     }