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?: any, _options?: any): 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 a specified DrapeTarget
, or floating at a certain altitude.
Both the KMLCodec
and the KMLModel
emit the "KMLGroundOverlay"
event with a KMLGroundOverlayFeature
.
You can register a handler function that consumes this event.
In the handler, create a layer to visualize the KMLGroundOverlayFeature
with createGroundOverlayLayer
, which is exported from the @luciad/ria/util/KMLUtil
module.
You do get instances of |
See the Draping on 3D Tiles how to page’s KML section to learn about draping possibilities. |
Handle KML screen overlays
A KML screen overlay represents an image overlay that you need to add to the view instead of to the map, such as a legend
or a logo.
Both the KMLCodec
and the KMLModel
emit the "KMLScreenOverlay"
event with a KMLScreenOverlayFeature
.
You can register a handler function that consumes this event.
In the handler, create a HTMLElement
to add the image to.
You don’t get instances of |
See the |
See the Example of how to handle "KMLNetworkLink", "KMLGroundOverlay", and "KMLScreenOverlay" events.
Example of how to handle "KMLNetworkLink", "KMLGroundOverlay", and "KMLScreenOverlay" events
"KMLNetworkLink"
, "KMLGroundOverlay",
and "KMLScreenOverlay"
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)); (layer.model as KMLModel)?.on("KMLScreenOverlay", (screenOverlay: KMLScreenOverlayFeature) => onKMLScreenOverlayEvent(screenOverlay)); } //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 layer with the referenced image createGroundOverlayLayer(map, groundOverlay, { layerOptions: { id: `${id}`, label: `${name}` } }).then(layer => { //Add the layer to the map map.layerTree.addChild(layer, "below", parentLayer); }); } } //Handler to consume KMLScreenOverlay event function onKMLScreenOverlayEvent(screenOverlay: KMLScreenOverlayFeature) { //For an example implementation see ScreenOverlay.tsx in the KML sample. createOverlay(screenOverlay); }
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
, KMLGroundOverlayFeature
and KMLScreenOverlayFeature
.
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 |
Handle KML parsing errors
While decoding KML data, the KMLCodec
might encounter a problem with the input data.
This can be a fatal error from which the KMLCodec
cannot recover, or an error for which a best effort is done by providing fallback behavior.
When a fatal error occurs, the KMLCodec
will emit the "KMLFatalError"
event.
You can register a handler function that consumes this event on the KMLCodec
or the KMLModel
.
Non-fatal errors and fallback behavior that occurred while decoding a KMLFeature
are reported in the errorMessages
property.