[Mapbender-commits] r9431 - trunk/mapbender/http/extensions
svn_mapbender at osgeo.org
svn_mapbender at osgeo.org
Thu Apr 7 01:27:52 PDT 2016
Author: armin11
Date: 2016-04-07 01:27:52 -0700 (Thu, 07 Apr 2016)
New Revision: 9431
Modified:
trunk/mapbender/http/extensions/togeojson.js
trunk/mapbender/http/extensions/tokml.js
Log:
New versions from mapbox project
Modified: trunk/mapbender/http/extensions/togeojson.js
===================================================================
--- trunk/mapbender/http/extensions/togeojson.js 2016-04-06 14:21:56 UTC (rev 9430)
+++ trunk/mapbender/http/extensions/togeojson.js 2016-04-07 08:27:52 UTC (rev 9431)
@@ -1,9 +1,9 @@
var toGeoJSON = (function() {
'use strict';
- var removeSpace = (/\s*/g),
- trimSpace = (/^\s*|\s*$/g),
- splitSpace = (/\s+/);
+ var removeSpace = /\s*/g,
+ trimSpace = /^\s*|\s*$/g,
+ splitSpace = /\s+/;
// generate a short, numeric hash of a string
function okhash(x) {
if (!x || !x.length) return 0;
@@ -55,7 +55,7 @@
if (ele) {
e = parseFloat(nodeVal(ele));
if (!isNaN(e)) {
- ll.push(e);
+ ll.push(e);
}
}
return {
@@ -83,6 +83,8 @@
}
function xml2str(str) {
// IE9 will create a new XMLSerializer but it'll crash immediately.
+ // This line is ignored because we don't run coverage tests in IE9
+ /* istanbul ignore next */
if (str.xml !== undefined) return str.xml;
return serializer.serializeToString(str);
}
@@ -92,28 +94,45 @@
var gj = fc(),
// styleindex keeps track of hashed styles in order to match features
- styleIndex = {},
+ styleIndex = {}, styleByHash = {},
+ // stylemapindex keeps track of style maps to expose in properties
+ styleMapIndex = {},
// atomic geospatial types supported by KML - MultiGeometry is
// handled separately
geotypes = ['Polygon', 'LineString', 'Point', 'Track', 'gx:Track'],
// all root placemarks in the file
placemarks = get(doc, 'Placemark'),
- styles = get(doc, 'Style');
+ styles = get(doc, 'Style'),
+ styleMaps = get(doc, 'StyleMap');
for (var k = 0; k < styles.length; k++) {
- styleIndex['#' + attr(styles[k], 'id')] = okhash(xml2str(styles[k])).toString(16);
+ var hash = okhash(xml2str(styles[k])).toString(16);
+ styleIndex['#' + attr(styles[k], 'id')] = hash;
+ styleByHash[hash] = styles[k];
}
+ for (var l = 0; l < styleMaps.length; l++) {
+ styleIndex['#' + attr(styleMaps[l], 'id')] = okhash(xml2str(styleMaps[l])).toString(16);
+ var pairs = get(styleMaps[l], 'Pair');
+ var pairsMap = {};
+ for (var m = 0; m < pairs.length; m++) {
+ pairsMap[nodeVal(get1(pairs[m], 'key'))] = nodeVal(get1(pairs[m], 'styleUrl'));
+ }
+ styleMapIndex['#' + attr(styleMaps[l], 'id')] = pairsMap;
+
+ }
for (var j = 0; j < placemarks.length; j++) {
gj.features = gj.features.concat(getPlacemark(placemarks[j]));
}
function kmlColor(v) {
var color, opacity;
- v = v || "";
- if (v.substr(0, 1) === "#") { v = v.substr(1); }
+ v = v || '';
+ if (v.substr(0, 1) === '#') { v = v.substr(1); }
if (v.length === 6 || v.length === 3) { color = v; }
if (v.length === 8) {
opacity = parseInt(v.substr(0, 2), 16) / 255;
- color = v.substr(2);
+ color = '#' + v.substr(6, 2) +
+ v.substr(4, 2) +
+ v.substr(2, 2);
}
return [color, isNaN(opacity) ? undefined : opacity];
}
@@ -123,7 +142,7 @@
if (elems.length === 0) elems = get(root, 'gx:coord');
for (var i = 0; i < elems.length; i++) coords.push(gxCoord(nodeVal(elems[i])));
var timeElems = get(root, 'when');
- for (var i = 0; i < timeElems.length; i++) times.push(nodeVal(timeElems[i]));
+ for (var j = 0; j < timeElems.length; j++) times.push(nodeVal(timeElems[j]));
return {
coords: coords,
times: times
@@ -184,13 +203,30 @@
timeSpan = get1(root, 'TimeSpan'),
extendedData = get1(root, 'ExtendedData'),
lineStyle = get1(root, 'LineStyle'),
- polyStyle = get1(root, 'PolyStyle');
+ polyStyle = get1(root, 'PolyStyle'),
+ visibility = get1(root, 'visibility');
if (!geomsAndTimes.geoms.length) return [];
if (name) properties.name = name;
- if (styleUrl && styleIndex[styleUrl]) {
+ if (styleUrl) {
+ if (styleUrl[0] !== '#') {
+ styleUrl = '#' + styleUrl;
+ }
+
properties.styleUrl = styleUrl;
- properties.styleHash = styleIndex[styleUrl];
+ if (styleIndex[styleUrl]) {
+ properties.styleHash = styleIndex[styleUrl];
+ }
+ if (styleMapIndex[styleUrl]) {
+ properties.styleMapHash = styleMapIndex[styleUrl];
+ properties.styleHash = styleIndex[styleMapIndex[styleUrl].normal];
+ }
+ // Try to populate the lineStyle or polyStyle since we got the style hash
+ var style = styleByHash[properties.styleHash];
+ if (style) {
+ if (!lineStyle) lineStyle = get1(style, 'LineStyle');
+ if (!polyStyle) polyStyle = get1(style, 'PolyStyle');
+ }
}
if (description) properties.description = description;
if (timeSpan) {
@@ -215,8 +251,8 @@
outline = nodeVal(get1(polyStyle, 'outline'));
if (pcolor) properties.fill = pcolor;
if (!isNaN(popacity)) properties['fill-opacity'] = popacity;
- if (fill) properties['fill-opacity'] = fill === "1" ? 1 : 0;
- if (outline) properties['stroke-opacity'] = outline === "1" ? 1 : 0;
+ if (fill) properties['fill-opacity'] = fill === '1' ? properties['fill-opacity'] || 1 : 0;
+ if (outline) properties['stroke-opacity'] = outline === '1' ? properties['stroke-opacity'] || 1 : 0;
}
if (extendedData) {
var datas = get(extendedData, 'Data'),
@@ -229,6 +265,9 @@
properties[simpleDatas[i].getAttribute('name')] = nodeVal(simpleDatas[i]);
}
}
+ if (visibility) {
+ properties.visibility = nodeVal(visibility);
+ }
if (geomsAndTimes.coordTimes.length) {
properties.coordTimes = (geomsAndTimes.coordTimes.length === 1) ?
geomsAndTimes.coordTimes[0] : geomsAndTimes.coordTimes;
@@ -311,7 +350,7 @@
}
function getRoute(node) {
var line = getPoints(node, 'rtept');
- if (!line) return;
+ if (!line.line) return;
var routeObj = {
type: 'Feature',
properties: getProperties(node),
Modified: trunk/mapbender/http/extensions/tokml.js
===================================================================
--- trunk/mapbender/http/extensions/tokml.js 2016-04-06 14:21:56 UTC (rev 9430)
+++ trunk/mapbender/http/extensions/tokml.js 2016-04-07 08:27:52 UTC (rev 9431)
@@ -23,17 +23,35 @@
), [['xmlns', 'http://www.opengis.net/kml/2.2']]);
};
-function feature(options) {
+function feature(options, styleHashesArray) {
return function(_) {
+ if (!_.properties || !geometry.valid(_.geometry)) return '';
+ var geometryString = geometry.any(_.geometry);
+ if (!geometryString) return '';
+
var styleDefinition = '',
styleReference = '';
- if (options.simplestyle && hasStyle(_.properties)) {
- styleDefinition = iconstyle(_.properties);
- styleReference = tag('styleUrl', '#' + iconHash(_.properties));
+ if (options.simplestyle) {
+ var styleHash = hashStyle(_.properties);
+ if (styleHash) {
+ if (geometry.isPoint(_.geometry) && hasMarkerStyle(_.properties)) {
+ if (styleHashesArray.indexOf(styleHash) === -1) {
+ styleDefinition = markerStyle(_.properties, styleHash);
+ styleHashesArray.push(styleHash);
+ }
+ styleReference = tag('styleUrl', '#' + styleHash);
+ } else if ((geometry.isPolygon(_.geometry) || geometry.isLine(_.geometry)) &&
+ hasPolygonAndLineStyle(_.properties)) {
+ if (styleHashesArray.indexOf(styleHash) === -1) {
+ styleDefinition = polygonAndLineStyle(_.properties, styleHash);
+ styleHashesArray.push(styleHash);
+ }
+ styleReference = tag('styleUrl', '#' + styleHash);
+ }
+ // Note that style of GeometryCollection / MultiGeometry is not supported
+ }
}
- if (!_.properties || !geometry.valid(_.geometry)) return '';
- var geometryString = geometry.any(_.geometry);
- if (!geometryString) return '';
+
return styleDefinition + tag('Placemark',
name(_.properties, options) +
description(_.properties, options) +
@@ -46,14 +64,16 @@
function root(_, options) {
if (!_.type) return '';
+ var styleHashesArray = [];
+
switch (_.type) {
case 'FeatureCollection':
if (!_.features) return '';
- return _.features.map(feature(options)).join('');
+ return _.features.map(feature(options, styleHashesArray)).join('');
case 'Feature':
- return feature(options)(_);
+ return feature(options, styleHashesArray)(_);
default:
- return feature(options)({
+ return feature(options, styleHashesArray)({
type: 'Feature',
geometry: _,
properties: {}
@@ -127,7 +147,7 @@
},
valid: function(_) {
return _ && _.type && (_.coordinates ||
- _.type === 'GeometryCollection' && _.geometries.every(geometry.valid));
+ _.type === 'GeometryCollection' && _.geometries && _.geometries.every(geometry.valid));
},
any: function(_) {
if (geometry[_.type]) {
@@ -135,6 +155,18 @@
} else {
return '';
}
+ },
+ isPoint: function(_) {
+ return _.type === 'Point' ||
+ _.type === 'MultiPoint';
+ },
+ isPolygon: function(_) {
+ return _.type === 'Polygon' ||
+ _.type === 'MultiPolygon';
+ },
+ isLine: function(_) {
+ return _.type === 'LineString' ||
+ _.type === 'MultiLineString';
}
};
@@ -151,13 +183,17 @@
return tag('Data', tag('value', encode(_[1])), [['name', encode(_[0])]]);
}
-// ## Icons
-function iconstyle(_) {
+// ## Marker style
+function hasMarkerStyle(_) {
+ return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']);
+}
+
+function markerStyle(_, styleHash) {
return tag('Style',
tag('IconStyle',
tag('Icon',
tag('href', iconUrl(_)))) +
- iconSize(_), [['id', iconHash(_)]]);
+ iconSize(_), [['id', styleHash]]);
}
function iconUrl(_) {
@@ -178,23 +214,85 @@
]);
}
-function hasStyle(_) {
- return !!(_['marker-size'] || _['marker-symbol'] || _['marker-color']);
+// ## Polygon and Line style
+function hasPolygonAndLineStyle(_) {
+ for (var key in _) {
+ if ({
+ "stroke": true,
+ "stroke-opacity": true,
+ "stroke-width": true,
+ "fill": true,
+ "fill-opacity": true
+ }[key]) return true;
+ }
}
-function iconHash(_) {
- return (_['marker-symbol'] || '') +
- (_['marker-color'] || '').replace('#', '') +
- (_['marker-size'] || '');
+function polygonAndLineStyle(_, styleHash) {
+ var lineStyle = tag('LineStyle', [
+ tag('color', hexToKmlColor(_['stroke'], _['stroke-opacity']) || 'ff555555') +
+ tag('width', _['stroke-width'] === undefined ? 2 : _['stroke-width'])
+ ]);
+
+ var polyStyle = '';
+
+ if (_['fill'] || _['fill-opacity']) {
+ polyStyle = tag('PolyStyle', [
+ tag('color', hexToKmlColor(_['fill'], _['fill-opacity']) || '88555555')
+ ]);
+ }
+
+ return tag('Style', lineStyle + polyStyle, [['id', styleHash]]);
}
-// ## Helpers
+// ## Style helpers
+function hashStyle(_) {
+ var hash = '';
+
+ if (_['marker-symbol']) hash = hash + 'ms' + _['marker-symbol'];
+ if (_['marker-color']) hash = hash + 'mc' + _['marker-color'].replace('#', '');
+ if (_['marker-size']) hash = hash + 'ms' + _['marker-size'];
+ if (_['stroke']) hash = hash + 's' + _['stroke'].replace('#', '');
+ if (_['stroke-width']) hash = hash + 'sw' + _['stroke-width'].toString().replace('.', '');
+ if (_['stroke-opacity']) hash = hash + 'mo' + _['stroke-opacity'].toString().replace('.', '');
+ if (_['fill']) hash = hash + 'f' + _['fill'].replace('#', '');
+ if (_['fill-opacity']) hash = hash + 'fo' + _['fill-opacity'].toString().replace('.', '');
+
+ return hash;
+}
+
+function hexToKmlColor(hexColor, opacity) {
+ if (typeof hexColor !== 'string') return '';
+
+ hexColor = hexColor.replace('#', '').toLowerCase();
+
+ if (hexColor.length === 3) {
+ hexColor = hexColor[0] + hexColor[0] +
+ hexColor[1] + hexColor[1] +
+ hexColor[2] + hexColor[2];
+ } else if (hexColor.length !== 6) {
+ return '';
+ }
+
+ var r = hexColor[0] + hexColor[1];
+ var g = hexColor[2] + hexColor[3];
+ var b = hexColor[4] + hexColor[5];
+
+ var o = 'ff';
+ if (typeof opacity === 'number' && opacity >= 0.0 && opacity <= 1.0) {
+ o = (opacity * 255).toString(16);
+ if (o.indexOf('.') > -1) o = o.substr(0, o.indexOf('.'));
+ if (o.length < 2) o = '0' + o;
+ }
+
+ return o + b + g + r;
+}
+
+// ## General helpers
function pairs(_) {
var o = [];
for (var i in _) o.push([i, _[i]]);
return o;
}
-
},{"strxml":2}],2:[function(require,module,exports){
module.exports.attr = attr;
module.exports.tagClose = tagClose;
@@ -242,4 +340,4 @@
}
},{}]},{},[1])(1)
-});
+});
\ No newline at end of file
More information about the Mapbender_commits
mailing list