Skip to content

Commit

Permalink
Merge pull request #2244 from elemoine/kmlwrite
Browse files Browse the repository at this point in the history
KML write support
  • Loading branch information
Éric Lemoine committed Jun 27, 2014
2 parents 2517c71 + 1ec25f3 commit be69f5b
Show file tree
Hide file tree
Showing 9 changed files with 2,827 additions and 972 deletions.
1,938 changes: 969 additions & 969 deletions examples/data/kml/2012-02-10.kml

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions examples/kml.html
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,11 @@
<div class="row-fluid">
<div class="span12">
<div id="map" class="map"></div>
<div id="no-download" class="alert alert-error" style="display: none">
The "Export KML" functionality requires a browser that supports the
<a href="http://caniuse.com/#feat=download">link download</a> attribute.
</div>
<a id="export-kml" class="btn" download="map.kml"><i class="icon-download"></i>Export KML</a>
</div>
</div>

Expand Down
35 changes: 34 additions & 1 deletion examples/kml.js
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
goog.require('ol.Map');
goog.require('ol.View2D');
goog.require('ol.format.KML');
goog.require('ol.layer.Tile');
goog.require('ol.layer.Vector');
goog.require('ol.proj');
goog.require('ol.source.BingMaps');
goog.require('ol.source.KML');

var projection = ol.proj.get('EPSG:3857');

var raster = new ol.layer.Tile({
source: new ol.source.BingMaps({
imagerySet: 'Aerial',
Expand All @@ -14,7 +18,7 @@ var raster = new ol.layer.Tile({

var vector = new ol.layer.Vector({
source: new ol.source.KML({
projection: 'EPSG:3857',
projection: projection,
url: 'data/kml/2012-02-10.kml'
})
});
Expand All @@ -24,6 +28,7 @@ var map = new ol.Map({
target: document.getElementById('map'),
view: new ol.View2D({
center: [876970.8463461736, 5859807.853963373],
projection: projection,
zoom: 10
})
});
Expand Down Expand Up @@ -55,3 +60,31 @@ $(map.getViewport()).on('mousemove', function(evt) {
map.on('click', function(evt) {
displayFeatureInfo(evt.pixel);
});

var exportKMLElement = document.getElementById('export-kml');
if ('download' in exportKMLElement) {
var vectorSource = /** @type {ol.source.Vector} */ (vector.getSource());
exportKMLElement.addEventListener('click', function(e) {
if (!exportKMLElement.href) {
var features = [];
vectorSource.forEachFeature(function(feature) {
var clone = feature.clone();
clone.setId(feature.getId()); // clone does not set the id
clone.getGeometry().transform(projection, 'EPSG:4326');
features.push(clone);
});
var node = new ol.format.KML().writeFeatures(features);
var string = new XMLSerializer().serializeToString(
/** @type {Node} */ (node));
var base64 = exampleNS.strToBase64(string);
exportKMLElement.href =
'data:application/vnd.google-earth.kml+xml;base64,' + base64;
}
}, false);
} else {
var info = document.getElementById('no-download');
/**
* display error message
*/
info.style.display = '';
}
11 changes: 10 additions & 1 deletion externs/example.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,5 +5,14 @@ var exampleNS;



/** @interface */
/**
* @return {string} Renderer type.
*/
exampleNS.getRendererFromQueryString = function() {};


/**
* @param {string} str String.
* @return {string} Base64 string.
*/
exampleNS.strToBase64 = function(str) {};
175 changes: 175 additions & 0 deletions resources/example-behaviour.js
Original file line number Diff line number Diff line change
Expand Up @@ -84,3 +84,178 @@ exampleNS.getRendererFromQueryString = function() {
return undefined;
}
};

/*\
|*|
|*| Base64 / binary data / UTF-8 strings utilities
|*|
|*| https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding
|*|
\*/

/* Array of bytes to base64 string decoding */

function b64ToUint6 (nChr) {

return nChr > 64 && nChr < 91 ?
nChr - 65
: nChr > 96 && nChr < 123 ?
nChr - 71
: nChr > 47 && nChr < 58 ?
nChr + 4
: nChr === 43 ?
62
: nChr === 47 ?
63
:
0;

}

function base64DecToArr (sBase64, nBlocksSize) {

var
sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);

for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
nMod4 = nInIdx & 3;
nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
if (nMod4 === 3 || nInLen - nInIdx === 1) {
for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
}
nUint24 = 0;

}
}

return taBytes;
}

/* Base64 string to array encoding */

function uint6ToB64 (nUint6) {

return nUint6 < 26 ?
nUint6 + 65
: nUint6 < 52 ?
nUint6 + 71
: nUint6 < 62 ?
nUint6 - 4
: nUint6 === 62 ?
43
: nUint6 === 63 ?
47
:
65;

}

function base64EncArr (aBytes) {

var nMod3 = 2, sB64Enc = "";

for (var nLen = aBytes.length, nUint24 = 0, nIdx = 0; nIdx < nLen; nIdx++) {
nMod3 = nIdx % 3;
if (nIdx > 0 && (nIdx * 4 / 3) % 76 === 0) { sB64Enc += "\r\n"; }
nUint24 |= aBytes[nIdx] << (16 >>> nMod3 & 24);
if (nMod3 === 2 || aBytes.length - nIdx === 1) {
sB64Enc += String.fromCharCode(uint6ToB64(nUint24 >>> 18 & 63), uint6ToB64(nUint24 >>> 12 & 63), uint6ToB64(nUint24 >>> 6 & 63), uint6ToB64(nUint24 & 63));
nUint24 = 0;
}
}

return sB64Enc.substr(0, sB64Enc.length - 2 + nMod3) + (nMod3 === 2 ? '' : nMod3 === 1 ? '=' : '==');

}

/* UTF-8 array to DOMString and vice versa */

function UTF8ArrToStr (aBytes) {

var sView = "";

for (var nPart, nLen = aBytes.length, nIdx = 0; nIdx < nLen; nIdx++) {
nPart = aBytes[nIdx];
sView += String.fromCharCode(
nPart > 251 && nPart < 254 && nIdx + 5 < nLen ? /* six bytes */
/* (nPart - 252 << 32) is not possible in ECMAScript! So...: */
(nPart - 252) * 1073741824 + (aBytes[++nIdx] - 128 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 247 && nPart < 252 && nIdx + 4 < nLen ? /* five bytes */
(nPart - 248 << 24) + (aBytes[++nIdx] - 128 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 239 && nPart < 248 && nIdx + 3 < nLen ? /* four bytes */
(nPart - 240 << 18) + (aBytes[++nIdx] - 128 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 223 && nPart < 240 && nIdx + 2 < nLen ? /* three bytes */
(nPart - 224 << 12) + (aBytes[++nIdx] - 128 << 6) + aBytes[++nIdx] - 128
: nPart > 191 && nPart < 224 && nIdx + 1 < nLen ? /* two bytes */
(nPart - 192 << 6) + aBytes[++nIdx] - 128
: /* nPart < 127 ? */ /* one byte */
nPart
);
}

return sView;

}

function strToUTF8Arr (sDOMStr) {

var aBytes, nChr, nStrLen = sDOMStr.length, nArrLen = 0;

/* mapping... */

for (var nMapIdx = 0; nMapIdx < nStrLen; nMapIdx++) {
nChr = sDOMStr.charCodeAt(nMapIdx);
nArrLen += nChr < 0x80 ? 1 : nChr < 0x800 ? 2 : nChr < 0x10000 ? 3 : nChr < 0x200000 ? 4 : nChr < 0x4000000 ? 5 : 6;
}

aBytes = new Uint8Array(nArrLen);

/* transcription... */

for (var nIdx = 0, nChrIdx = 0; nIdx < nArrLen; nChrIdx++) {
nChr = sDOMStr.charCodeAt(nChrIdx);
if (nChr < 128) {
/* one byte */
aBytes[nIdx++] = nChr;
} else if (nChr < 0x800) {
/* two bytes */
aBytes[nIdx++] = 192 + (nChr >>> 6);
aBytes[nIdx++] = 128 + (nChr & 63);
} else if (nChr < 0x10000) {
/* three bytes */
aBytes[nIdx++] = 224 + (nChr >>> 12);
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
aBytes[nIdx++] = 128 + (nChr & 63);
} else if (nChr < 0x200000) {
/* four bytes */
aBytes[nIdx++] = 240 + (nChr >>> 18);
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
aBytes[nIdx++] = 128 + (nChr & 63);
} else if (nChr < 0x4000000) {
/* five bytes */
aBytes[nIdx++] = 248 + (nChr >>> 24);
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
aBytes[nIdx++] = 128 + (nChr & 63);
} else /* if (nChr <= 0x7fffffff) */ {
/* six bytes */
aBytes[nIdx++] = 252 + /* (nChr >>> 32) is not possible in ECMAScript! So...: */ (nChr / 1073741824);
aBytes[nIdx++] = 128 + (nChr >>> 24 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 18 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 12 & 63);
aBytes[nIdx++] = 128 + (nChr >>> 6 & 63);
aBytes[nIdx++] = 128 + (nChr & 63);
}
}

return aBytes;

}

exampleNS.strToBase64 = function(str) {
return base64EncArr(strToUTF8Arr(str));
};
Loading

0 comments on commit be69f5b

Please sign in to comment.