5

I am very new to this GIS thing.

I have to integrate export to KML option in one of my project.

I could not see this option while googling.

Is there option to do this?

<!DOCTYPE html>
<html>
<head>
    <title>Leaflet.draw vector editing handlers</title>

    <script src="libs/leaflet-src.js"></script>
    <link rel="stylesheet" href="libs/leaflet.css" />

    <script src="../src/Leaflet.draw.js"></script>
    <link rel="stylesheet" href="../dist/leaflet.draw.css" />

    <link rel="stylesheet" href="../src/NavBar/Leaflet.NavBar.css" />

    <script src="../src/Toolbar.js"></script>
    <script src="../src/Tooltip.js"></script>

    <script src="../src/ext/GeometryUtil.js"></script>
    <script src="../src/ext/LatLngUtil.js"></script>
    <script src="../src/ext/LineUtil.Intersect.js"></script>
    <script src="../src/ext/Polygon.Intersect.js"></script>
    <script src="../src/ext/Polyline.Intersect.js"></script>


    <script src="../src/draw/DrawToolbar.js"></script>
    <script src="../src/draw/handler/Draw.Feature.js"></script>
    <script src="../src/draw/handler/Draw.SimpleShape.js"></script>
    <script src="../src/draw/handler/Draw.Polyline.js"></script>
    <script src="../src/draw/handler/Draw.Circle.js"></script>
    <script src="../src/draw/handler/Draw.Marker.js"></script>
    <script src="../src/draw/handler/Draw.Polygon.js"></script>
    <script src="../src/draw/handler/Draw.Rectangle.js"></script>


    <script src="../src/edit/EditToolbar.js"></script>
    <script src="../src/edit/handler/EditToolbar.Edit.js"></script>
    <script src="../src/edit/handler/EditToolbar.Delete.js"></script>

    <script src="../src/Control.Draw.js"></script>
    <script src="../src/NavBar/Leaflet.NavBar.js"></script>
    <script src="../src/edit/handler/Edit.Poly.js"></script>
    <script src="../src/edit/handler/Edit.SimpleShape.js"></script>
    <script src="../src/edit/handler/Edit.Circle.js"></script>
    <script src="../src/edit/handler/Edit.Rectangle.js"></script>
    <script src="../src/edit/handler/Edit.Marker.js"></script>
</head>
<body>
    <div id="map" style="width: 900px; height: 500px; border: 1px solid #ccc"></div>
    <button type="button" onclick="plotAccidents();">plot accidents</button><br/>
    <button type="button" onclick="clearAccidents();">clear accidents</button><br/>
    <button type="button" onclick="addWMS();">Add WMS</button><br/>
    <button type="button" onclick="panTo();">Pan To Address</button><br/>

WKT String : <span id="wktstring"></span>
    <script>
        var bounds;
        var plotbounds;
        var count=0;
        var checked =1;
        var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
            osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
            osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib});
            map = new L.Map('map', {layers: [osm], center: new L.LatLng(47.58, 29.22), zoom: 13}),
            drawnItems = L.featureGroup().addTo(map);

        var markers = new L.FeatureGroup(); 
        map.addControl(new L.Control.Draw({
            edit: { featureGroup: drawnItems }
        }));

        map.on('draw:created', function(event) {
            var layer = event.layer;

            drawnItems.addLayer(layer);
        });
        L.control.navbar().addTo(map);

        function plotAccidents()
        {
            populate();
            map.addLayer(markers);
        }
        function clearAccidents()
        {
            map.removeLayer(markers);
        }

        function getRandomLatLng(map) {

        //if(bounds==null)
        bounds = map.getBounds();
        if(count==0)
        {
        console.log(bounds);

        }
        //if(count==0)
        //{
            //console.log("southWest");
            //console.log(bounds.getSouthWest());
        //}
        southWest = bounds.getSouthWest();
        northEast = bounds.getNorthEast();
        lngSpan = northEast.lng - southWest.lng;
        latSpan = northEast.lat - southWest.lat;
    count++;
    return new L.LatLng(
    southWest.lat + latSpan * Math.random(),
    southWest.lng + lngSpan * Math.random());
    }

    function populate() {
    for (var i = 0; i < 10; i++) {
        var point = getRandomLatLng(map);

        if(plotbounds!=null && !plotbounds.contains(point))
        continue;
        var marker = L.marker(point);
        marker.bindPopup("<p>Accident details goes here</p>", {
            showOnMouseOver: true
        });
        markers.addLayer(marker);
    }
    return false;
}
function toWKT(layer) {
    var lng, lat, coords = [];

    if (layer instanceof L.Polygon || layer instanceof L.Polyline) {
        var latlngs = layer.getLatLngs();
        for (var i = 0; i < latlngs.length; i++) {
            latlngs[i]
            coords.push(latlngs[i].lng + " " + latlngs[i].lat);
            if (i === 0) {
                lng = latlngs[i].lng;
                lat = latlngs[i].lat;
            }
    };
        if (layer instanceof L.Polygon) {
            return "POLYGON((" + coords.join(",") + "," + lng + " " + lat + "))";
        } else if (layer instanceof L.Polyline) {
            return "LINESTRING(" + coords.join(",") + ")";
        }
    } else if (layer instanceof L.Marker) {
        return "POINT(" + layer.getLatLng().lng + " " + layer.getLatLng().lat + ")";
    }
}
var drawnItems = new L.LayerGroup();
map.on('draw:created', function (e) {
    var type = e.layerType; 

    plotbounds = e.layer.getBounds();
    console.log(plotbounds);
    var layer = e.layer;
    drawnItems.addLayer(layer);
    document.getElementById('wktstring').innerHTML=(toWKT(layer));
});



map.addLayer(drawnItems);
function addWMS()
{
    L.tileLayer.wms("http://sedac.ciesin.columbia.edu/geoserver/wms", {
    layers: 'gpw-v3:gpw-v3-population-density_2000',
    format: 'image/png',
    version: '1.1.0',
    transparent: true,
    attribution: "",
    tiled:true
}).addTo(map);
}
function panTo()
{
    map.panTo(new L.LatLng(40.737, -73.923));
}
</script>
</body>
</html>
  • I updated the answer – toms Aug 27 '15 at 14:29
6
+50

Indirectly, using tokml, after first converting to geojson:

<html>
<head>
    <link rel="stylesheet" href="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.css" />
</head>
<body>
    <div id="map" style="width: 700px; height: 500px"></div>
    <script src="http://cdn.leafletjs.com/leaflet-0.7.3/leaflet.js"></script>
    <!-- include this from here: https://raw.githubusercontent.com/mapbox/tokml/master/tokml.js -->
    <script src="tokml.js"></script>

    <script>
        // set up a basic map and add a marker
        var map = L.map('map').setView([51.505, -0.09], 13);
        var marker = L.marker([51.5, -0.11]).addTo(map);

        // convert marker to geojson
        // layers also have a toGeoJSON function
        var json = marker.toGeoJSON();

        // then export to kml
        var kml = tokml(json);
    </script>
</body>

the kml that results from the above operation:

<?xml version="1.0" encoding="UTF-8"?>
  <kml xmlns="http://www.opengis.net/kml/2.2">
    <Document>
      <Placemark>
        <ExtendedData></ExtendedData>
        <Point>
          <coordinates>-0.11,51.5</coordinates>
        </Point>
      </Placemark>
    </Document>
</kml>

Update:

If it is drawnItems that you want to convert to kml, you can use toGeoJSON on the featureGroup:

var json = drawnItems.toGeoJSON();
var kml = tokml(json);

This works layers with mixed geometries (points, lines, polygons).

I don't know where it makes the most sense for you to do this in your code. drawnItems is declared in global scope, so you could do this in draw.on('created'), or in a new function triggered by an export button (for example).

  • thank you. i need to conver a layer which contains multiple shapes. – shanavascet Aug 24 '15 at 4:51
  • can you post some code in your question? At least how you are creating the data and adding it to the map. – toms Aug 24 '15 at 18:47
  • i have added the code. I thought first to convert the layer to geojson. but could n't find any option. can you pls give any suggestion like how ot proceed. I have scene the same option available in ArcGIS. – shanavascet Aug 25 '15 at 6:46
2

I am looking at the same issue. Firstly Converting to geoJSON and then KML. This tokml looks promising and seems to work. First problem is geoJSON does not recognise Circles, so i needed a workaround foir that - found on another thread.

So what I am doing.

In need a function to replace circle shapes with calculated polygons when added. Then a function to generate geoJSON, ( i assigned to a button ). The simply posing the geoJSON tokml.
Here is my version of the process. I fire shapes1 on a button when i have finished $('#textareashowinggeojson').val(shapes1).select();

From there you can simply run tokml with that textarea or simply the value returned from shapes1

    function createGeodesicPolygon(origin, radius, sides, rotation, projection) {

        var latlon = origin; //leaflet equivalent
        var angle;
        var new_lonlat, geom_point;
        var points = [];

        for (var i = 0; i < sides; i++) {
            angle = (i * 360 / sides) + rotation;
            new_lonlat = destinationVincenty(latlon, angle, radius); 
            geom_point = L.latLng(new_lonlat.lng, new_lonlat.lat); 

            points.push(geom_point); 
        }   

        return points; 
    };
    L.Util.VincentyConstants = {
        a: 6378137,
        b: 6356752.3142,
        f: 1/298.257223563  
    };  
    function destinationVincenty(lonlat, brng, dist) { //rewritten to work with leaflet

        var u = L.Util;
        var ct = u.VincentyConstants;
        var a = ct.a, b = ct.b, f = ct.f;
        var lon1 = lonlat.lng;
        var lat1 = lonlat.lat;
        var s = dist;
        var pi = Math.PI;
        var alpha1 = brng * pi/180 ; //converts brng degrees to radius
        var sinAlpha1 = Math.sin(alpha1);
        var cosAlpha1 = Math.cos(alpha1);
        var tanU1 = (1-f) * Math.tan( lat1 * pi/180 /* converts lat1 degrees to radius */ ); 
        var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
        var sigma1 = Math.atan2(tanU1, cosAlpha1);
        var sinAlpha = cosU1 * sinAlpha1;
        var cosSqAlpha = 1 - sinAlpha*sinAlpha;
        var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
        var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
        var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
        var sigma = s / (b*A), sigmaP = 2*Math.PI;
        while (Math.abs(sigma-sigmaP) > 1e-12) {
            var cos2SigmaM = Math.cos(2*sigma1 + sigma);
            var sinSigma = Math.sin(sigma);
            var cosSigma = Math.cos(sigma);
            var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
                B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
            sigmaP = sigma;
            sigma = s / (b*A) + deltaSigma;
        }
        var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
        var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
            (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
        var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
        var lam = lambda - (1-C) * f * sinAlpha *
            (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));  
        var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
        var lamFunc = lon1 + (lam * 180/pi); //converts lam radius to degrees
        var lat2a = lat2 * 180/pi; //converts lat2a radius to degrees

        return L.latLng(lamFunc, lat2a);

    };

    map.on('draw:created', function (e) {

        var type = e.layerType,
            layer = e.layer;

        if (type === 'circle') {

            var origin = layer.getLatLng(); //center of drawn circle
            var radius = layer.getRadius(); //radius of drawn circle
            var projection = L.CRS.EPSG4326;
            var polys = createGeodesicPolygon(origin, radius, 60, 0, projection); //these are the points that make up the circle
            var polygon = []; // store the geometry
            for (var i = 0; i < polys.length; i++) {
                var geometry = [polys[i].lat, polys[i].lng]; 
                polygon.push(geometry);
            }
            var cpolygon = L.polygon(polygon);
            drawnItems.addLayer(cpolygon);
        } else {
            //Just do as normal
            drawnItems.addLayer(layer);
        }
    });

    var getShapes1 = function(drawnItems) {
        var shapes1 = JSON.stringify(drawnItems.toGeoJSON());
        return shapes1;
    };
0

I quickly grabbed your and slapped up something. You seem to have redeclared the drawnitems further on - not sure why Function at the bottom of the javascript should get you what you need.

genKml()

    var bounds;
    var plotbounds;
    var count=0;
    var checked =1;
    var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
        osmAttrib = '&copy; <a href="http://openstreetmap.org/copyright">OpenStreetMap</a> contributors',
        osm = L.tileLayer(osmUrl, {maxZoom: 18, attribution: osmAttrib});
        map = new L.Map('map', {layers: [osm], center: new L.LatLng(47.58, 29.22), zoom: 13}),
        drawnItems;

    var markers = new L.FeatureGroup(); 


    drawnItems = L.featureGroup().addTo(map);
    map.addControl(new L.Control.Draw({
        draw: {
            circle: true, 
            polygon: {allowIntersection: false}                    
        },
        edit: { featureGroup: drawnItems }
    }));

    map.on('draw:created', function (e) {

        var type = e.layerType,
            layer = e.layer;

        if (type === 'circle') {

            var origin = layer.getLatLng(); //center of drawn circle
            var radius = layer.getRadius(); //radius of drawn circle
            var projection = L.CRS.EPSG4326;
            var polys = createGeodesicPolygon(origin, radius, 60, 0, projection); //these are the points that make up the circle
            var polygon = []; // store the geometry
            for (var i = 0; i < polys.length; i++) {
                var geometry = [polys[i].lat, polys[i].lng]; 
                polygon.push(geometry);
            }
            var cpolygon = L.polygon(polygon);
            drawnItems.addLayer(cpolygon);
        } else {

            drawnItems.addLayer(layer);
        }
    });


    var getShapes = function(drawnItems) {
        var shapes = JSON.stringify(drawnItems.toGeoJSON());
        return shapes;
    };


    L.control.navbar().addTo(map);

    function plotAccidents()
    {
        populate();
        map.addLayer(markers);
    }
    function clearAccidents()
    {
        map.removeLayer(markers);
    }

    function getRandomLatLng(map) {

    //if(bounds==null)
    bounds = map.getBounds();
    if(count==0)
    {
    console.log(bounds);

    }
    //if(count==0)
    //{
        //console.log("southWest");
        //console.log(bounds.getSouthWest());
    //}
    southWest = bounds.getSouthWest();
    northEast = bounds.getNorthEast();
    lngSpan = northEast.lng - southWest.lng;
    latSpan = northEast.lat - southWest.lat;
count++;
return new L.LatLng(
southWest.lat + latSpan * Math.random(),
southWest.lng + lngSpan * Math.random());
}

function populate() {
for (var i = 0; i < 10; i++) {
    var point = getRandomLatLng(map);

    if(plotbounds!=null && !plotbounds.contains(point))
    continue;
    var marker = L.marker(point);
    marker.bindPopup("<p>Accident details goes here</p>", {
        showOnMouseOver: true
    });
    markers.addLayer(marker);
}
return false;

} function toWKT(layer) { var lng, lat, coords = [];

if (layer instanceof L.Polygon || layer instanceof L.Polyline) {
    var latlngs = layer.getLatLngs();
    for (var i = 0; i < latlngs.length; i++) {
        latlngs[i]
        coords.push(latlngs[i].lng + " " + latlngs[i].lat);
        if (i === 0) {
            lng = latlngs[i].lng;
            lat = latlngs[i].lat;
        }
};
    if (layer instanceof L.Polygon) {
        return "POLYGON((" + coords.join(",") + "," + lng + " " + lat + "))";
    } else if (layer instanceof L.Polyline) {
        return "LINESTRING(" + coords.join(",") + ")";
    }
} else if (layer instanceof L.Marker) {
    return "POINT(" + layer.getLatLng().lng + " " + layer.getLatLng().lat + ")";
}

}

    function createGeodesicPolygon(origin, radius, sides, rotation, projection) {

        var latlon = origin; //leaflet equivalent
        var angle;
        var new_lonlat, geom_point;
        var points = [];

        for (var i = 0; i < sides; i++) {
            angle = (i * 360 / sides) + rotation;
            new_lonlat = destinationVincenty(latlon, angle, radius); 
            geom_point = L.latLng(new_lonlat.lng, new_lonlat.lat); 

            points.push(geom_point); 
        }   

        return points; 
    };
    L.Util.VincentyConstants = {
        a: 6378137,
        b: 6356752.3142,
        f: 1/298.257223563  
    };  
    function destinationVincenty(lonlat, brng, dist) { //rewritten to work with leaflet

        var u = L.Util;
        var ct = u.VincentyConstants;
        var a = ct.a, b = ct.b, f = ct.f;
        var lon1 = lonlat.lng;
        var lat1 = lonlat.lat;
        var s = dist;
        var pi = Math.PI;
        var alpha1 = brng * pi/180 ; //converts brng degrees to radius
        var sinAlpha1 = Math.sin(alpha1);
        var cosAlpha1 = Math.cos(alpha1);
        var tanU1 = (1-f) * Math.tan( lat1 * pi/180 /* converts lat1 degrees to radius */ ); 
        var cosU1 = 1 / Math.sqrt((1 + tanU1*tanU1)), sinU1 = tanU1*cosU1;
        var sigma1 = Math.atan2(tanU1, cosAlpha1);
        var sinAlpha = cosU1 * sinAlpha1;
        var cosSqAlpha = 1 - sinAlpha*sinAlpha;
        var uSq = cosSqAlpha * (a*a - b*b) / (b*b);
        var A = 1 + uSq/16384*(4096+uSq*(-768+uSq*(320-175*uSq)));
        var B = uSq/1024 * (256+uSq*(-128+uSq*(74-47*uSq)));
        var sigma = s / (b*A), sigmaP = 2*Math.PI;
        while (Math.abs(sigma-sigmaP) > 1e-12) {
            var cos2SigmaM = Math.cos(2*sigma1 + sigma);
            var sinSigma = Math.sin(sigma);
            var cosSigma = Math.cos(sigma);
            var deltaSigma = B*sinSigma*(cos2SigmaM+B/4*(cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)-
                B/6*cos2SigmaM*(-3+4*sinSigma*sinSigma)*(-3+4*cos2SigmaM*cos2SigmaM)));
            sigmaP = sigma;
            sigma = s / (b*A) + deltaSigma;
        }
        var tmp = sinU1*sinSigma - cosU1*cosSigma*cosAlpha1;
        var lat2 = Math.atan2(sinU1*cosSigma + cosU1*sinSigma*cosAlpha1,
            (1-f)*Math.sqrt(sinAlpha*sinAlpha + tmp*tmp));
        var lambda = Math.atan2(sinSigma*sinAlpha1, cosU1*cosSigma - sinU1*sinSigma*cosAlpha1);
        var C = f/16*cosSqAlpha*(4+f*(4-3*cosSqAlpha));
        var lam = lambda - (1-C) * f * sinAlpha *
            (sigma + C*sinSigma*(cos2SigmaM+C*cosSigma*(-1+2*cos2SigmaM*cos2SigmaM)));  
        var revAz = Math.atan2(sinAlpha, -tmp);  // final bearing
        var lamFunc = lon1 + (lam * 180/pi); //converts lam radius to degrees
        var lat2a = lat2 * 180/pi; //converts lat2a radius to degrees

        return L.latLng(lamFunc, lat2a);

    };

var drawnItems = new L.LayerGroup(); map.on('draw:created', function (e) { var type = e.layerType;

plotbounds = e.layer.getBounds();
console.log(plotbounds);
var layer = e.layer;
drawnItems.addLayer(layer);
document.getElementById('wktstring').innerHTML=(toWKT(layer));

});

map.addLayer(drawnItems); function addWMS() { L.tileLayer.wms("http://sedac.ciesin.columbia.edu/geoserver/wms", { layers: 'gpw-v3:gpw-v3-population-density_2000', format: 'image/png', version: '1.1.0', transparent: true, attribution: "", tiled:true }).addTo(map); } function panTo() { map.panTo(new L.LatLng(40.737, -73.923)); }

function genKml() { var myJSONdata = getShapes(drawnItems); run(JSON.parse(myJSONdata)); };

<script src='../src/site/site.js'></script>

0

Further to that simply include the tokml.js file Then this will generate the kml. JSON.parse is required for tokml to work. the options for tokml documentname documentdescription simplestyle are optional

var kshapes = JSON.stringify(drawnItems.toGeoJSON());
    var kmlDoc = tokml(JSON.parse(kshapes), {
        documentName: 'My Polygons',
        documentDescription: 'Some stuff I drew', 
        simplestyle: true
    });

I am then going to post the results in a form to another page to generate a file to download.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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