Visualize KML placemarks
A KML placemark is a feature with associated geometry. LuciadRIA represents it as KMLPlacemarkFeature
.
Visualizing KML data with KML placemarks on a map requires two steps:
//First decode the data into a model
const model = new KMLModel(url);
//Create a layer for the model
//The layer visualizes the KML data using the
//styling information provided in the data
const layer = new KMLLayer(model);
//Add the layer to the map
map.layerTree.addChild(layer);
You can also use a KMLCodec
with any kind of Store
. For example, you can use a WFSFeatureStore
to connect to a WFS service returning KML data, or you can implement a custom Store
that decodes KML data from a string.
Store
that reads KML data directly from a string.
//StringStore is a read only store that can handle KML data from a string
class StringStore implements Store {
private readonly content: string;
private readonly codec: Codec;
constructor(kmlString: string) {
this.content = kmlString;
this.codec = new KMLCodec();
}
query(_query?: object, _options?: object): Cursor | Promise<Cursor> {
return this.codec.decode({content: this.content});
}
}
//Instantiate the StringStore and configure a FeatureModel with it.
//Where the kmlString contains a text with KML data
const store = new StringStore(kmlString);
const model = new FeatureModel(store);
//Create a layer for the model
const layer = new KMLLayer(model as KMLModel);
//Add the layer to the map
map.layerTree.addChild(layer);
Handle KML network links
A KML network link is a feature that references a KML or KMZ file on a local or remote network.
LuciadRIA represents a KML network link as KMLNetworkLinkFeature
.
When the KMLCodec
encounters a KML network link while it’s decoding KML data, it emits a "KMLNetworkLink"
event with the KMLNetworkLinkFeature
instance.
For your convenience, the KMLModel
propagates this event from the KMLCodec
.
You can register a handler function that consumes this event to create a new KMLLayer
for the emitted KMLNetworkLinkFeature
.
You don’t get instances of |
Handle KML ground overlays
A KML ground overlay represents an image overlay draped onto the terrain.
Both the KMLCodec
and the KMLModel
emit the "KMLGroundOverlay"
event with a KMLGroundOverlayFeature
.
You can register a handler function that consumes this event to create a new RasterTileSetLayer
for the emitted KMLGroundOverlayFeature
.
You don’t get instances of |
Example of how to handle "KMLNetworkLink" and "KMLGroundOverlay" events
"KMLNetworkLink"
and "KMLGroundOverlay"
events.
//Register handlers for KML events
addListeners(parentLayer);
function addListeners(layer: KMLLayer) {
(layer.model as KMLModel)?.on("KMLNetworkLink",
(networkLink: KMLNetworkLinkFeature) => onKMLNetworkLinkEvent(networkLink, layer));
(layer.model as KMLModel)?.on("KMLGroundOverlay",
(groundOverlay: KMLGroundOverlayFeature) => onKMLGroundOverlayEvent(groundOverlay, layer));
}
//Handler to consume KMLNetworkLink event
function onKMLNetworkLinkEvent(networkLink: KMLNetworkLinkFeature, parentLayer: KMLLayer) {
const {link, name, id} = networkLink.properties;
if (link.href) {
//Create a new KML layer that points to the network link's KML data
const kmlLayerForNetworkLink = new KMLLayer(new KMLModel(link.href), {
id: `${id}`,
label: `${name}`
});
//Register handlers for newly created KML layer
addListeners(kmlLayerForNetworkLink);
//Add the layer to the map
map.layerTree.addChild(kmlLayerForNetworkLink, "above", parentLayer);
}
}
//Handler to consume KMLGroundOverlay event
function onKMLGroundOverlayEvent(groundOverlay: KMLGroundOverlayFeature, parentLayer: KMLLayer) {
const {id, properties, shape} = groundOverlay;
const {icon, name} = properties;
if (shape && shape.bounds && icon && icon.href) {
//Create a new raster layer with the referenced image
const model = new UrlTileSetModel({
reference: getReference("CRS:84"),
bounds: shape?.bounds,
baseURL: icon.href,
levelCount: 1
});
const rasterLayer = new RasterTileSetLayer(model, {
id: `${id}`,
label: `${name}`
});
//Add the layer to the map
map.layerTree.addChild(rasterLayer, "below", parentLayer);
}
}
Handle the KML data structure
KML data holds features nested in KML containers: KML document and KML folder. LuciadRIA represents those as
KMLDocumentContainer
and KMLFolderContainer
.
Both KMLDocumentContainer
and KMLFolderContainer
expose the children
property with a value that’s an ordered array of
all discovered KML features of the types KMLFolderContainer
, KMLPlacemarkFeature
, but also the types KMLNetworkLinkFeature
and MLGroundOverlayFeature
.
When the KMLCodec
has fully decoded the KML data, it emits a single "KMLTree"
event with
the top-most KML container element. Usually, that’s a KMLDocumentContainer
.
You can register a handler for the "KMLTree"
event on the KMLCodec
or KMLModel
to build a user interface
that reflects the hierarchical data structure.
Each KMLFeature
has common properties
that you can use for setting the initial states of UI components, for example:
-
open
- specifies whether to show an expanded or collapsed Document or Folder. -
visibility
- specifies whether to make a feature visible or not when it’s first loaded. -
snippet
- a short description of the feature.
"KMLTree"
event to count specific features.
// Count all features in folders that contain the "Buildings" text in the "name" property
(kmlLayer.model as KMLModel)?.on("KMLTree", (treeData: KMLFeature[]) => {
const count = treeData.reduce((result: number, feature: KMLFeature) => {
return (feature instanceof KMLFolderContainer &&
feature.properties.name &&
feature.properties.name.indexOf("Buildings") > -1) ?
result + feature.children.length :
result
}, 0);
console.log("Number of features in 'Buildings' folders", count);
});
See the |