5

I found an example showing KML overlays at http://harrywood.co.uk/maps/examples/leaflet/kml.html but it only plots vector layer using polygons.

Is there any way to plot Ground overlays of KML (like in http://kml-samples.googlecode.com/svn/trunk/kml/Region/GroundOverlay/usa-ca-sf.kml) in Leaflet?

2

3 Answers 3

3

I found out solution using ImageOverlay from leaflet for creating Ground Overlays as below : http://leafletjs.com/reference.html#imageoverlay

1

I am building a leaflet plugin that at the moment specifically addresses KML SuperOverlay as output from gdal, with simple GroundOverlay coming soon. In case that is what you were trying to do, please visit: https://github.com/ahalota/Leaflet.KMLGroundOverlay

If you are looking to add just a single image, you need to use XMLHTTPRequest to open up your KML, and extract the coordinates. For finding just the first groundoverlay in a kml with "coordinates" tag, this would look like this:

Assuming this is the start of your input KML file:

<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2" xmlns:gx="http://www.google.com/kml/ext/2.2">
    <Document>
       <name>0/0/0.kml</name>
    <Region>
        <LatLonAltBox>
            <north>36.270066</north>
            <south>36.230095</south>
            <east>-76.430905</east>
            <west>-76.479846</west>
        </LatLonAltBox>
        <Lod>
            <minLodPixels>1</minLodPixels>
            <maxLodPixels>2048</maxLodPixels>
        </Lod>
    </Region>
    <GroundOverlay>
        <drawOrder>0</drawOrder>
        <Icon>
            <href>0.png</href>
        </Icon>
        <gx:LatLonQuad>
            <coordinates>
                -76.479846,36.230095,0
                -76.430188,36.230699,0
                -76.430905,36.270066,0
                -76.480589,36.269461,0
            </coordinates>
        </gx:LatLonQuad>
    </GroundOverlay>
    <NetworkLink>
        <name>1/0/0.png</name>
            ...

Then this code could get you that data:

function getGroundOverlayInfo(url){
    var xhr = new XMLHttpRequest();

    xhr.onerror = function() { console.log("Error while getting XML."); }
    xhr.open("GET", url, false);
    xhr.send();

    var imgUrl = xhr.responseXML.getElementsByTagName("Icon")[0].innerHTML;

    var coordString = xhr.responseXML.getElementsByTagName("coordinates")[0].innerHTML;
    coordString = coordString.replace(/(\r\n|\n|\r)/gm,",");
    var coords = coordString.split(",");
    var nwLat = parseFloat(coords[11]);
    var nwLon = parseFloat(coords[10]);
    var neLat = parseFloat(coords[8]);
    var neLon = parseFloat(coords[7]);
    var seLat = parseFloat(coords[5]);
    var seLon = parseFloat(coords[4]);
    var swLat = parseFloat(coords[2]);
    var swLon = parseFloat(coords[1]);

    return {
       anchor: [[nwLat,nwLon],[neLat,neLon],[seLat,seLon],[swLat,swLon]]},
       img: imgUrl} ;
);

var baseUrl = "//URL/WHERE/KML/FILE/LIVES/";
var kmlFile = "FILE.KML"
var kmlInfo = getGroundOverlayInfo(baserUrl+kmlFile);

If your kml has different way of providing the coordinates (or perhaps multiple ground overlays), you have to expand on this to search for other things in your xhr object.

You must have a local server running or you will likely get a cross-origin resource request error when trying to access your xml file!

Once you have your image and anchor extracted, you can then use this plugin: https://github.com/ScanEx/Leaflet.imageTransform to add it to your map:

var transformedImage = L.imageTransform(baseUrl+kmlInfo.imgUrl, kmlInfo.anchors);
transformedImage.addTo(map);

The code above is not very robust, but should be a base to get you started.

0

I had a need for a quick way to do this, and ended up with:

// initialise the map
const mymap = L.map('mapID').setView(<latLng>, <zoom>);
// add the tile layer
L.tileLayer(<url>, {<options>}).addTo(mymap);
// use omnivore to do the main conversion to geoJson
omnivore.kml('path/to/dir/doc.kml').addTo(mymap);
// use jQuery to parse the GroundOverlay items which Omnivore doesn't handle 
$.ajax({
  url: 'path/to/dir/doc.kml',
  dataType: "xml",
  success: function (response) {
    $(response).find('GroundOverlay').each(function (overlay) {
      const imgURL = "path/to/dir/" + $(this).find("href").text();
      const southWest = [$(this).find("south").text(), $(this).find("west").text()];
      const northEast = [$(this).find("north").text(), $(this).find("east").text()];
      L.imageOverlay(imgURL, [southWest, northEast], {opacity: 0.6}).addTo(mymap);
    });
  }

This depends on jQuery 3.3.1 and leaflet-omnivore.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.