[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