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.