Ticket #1531: 1531-r7060-A0.patch
| File 1531-r7060-A0.patch, 18.4 kB (added by ahocevar, 8 months ago) |
|---|
-
tests/Format/SLD/v1_0_0.html
old new 15 15 '<Name>AAA161</Name>' + 16 16 '<UserStyle>' + 17 17 '<FeatureTypeStyle>' + 18 '<SemanticTypeIdentifier>generic:geometry</SemanticTypeIdentifier>' + 18 19 '<Rule>' + 19 20 '<Name>stortsteen</Name>' + 20 21 '<ogc:Filter>' + -
tests/StyleMap.html
old new 36 36 t.ok(!styleMap.styles, "StyleMap styles successfully destroyed"); 37 37 } 38 38 39 function test_StyleMap_makeGeometryTypeAware(t) { 40 t.plan(7); 41 var styleMap = new OpenLayers.StyleMap({"Point": "foo", "Line": "bar"}); 42 styleMap.styles["default"].addRules([new OpenLayers.Rule({symbolizer: { 43 "Polygon": "foobar"}})]); 44 styleMap.makeGeometryTypeAware(); 45 t.eq(styleMap.styles["default"].rules.length, 3, "correct number of rules created"); 46 t.eq(styleMap.styles["default"].rules[0].symbolizer, "foo", "assigned point symbolizer from defaultStyle correctly to point rule"); 47 t.eq(styleMap.styles["default"].rules[0].geometryType, "generic:point", "assign geometry type correctly to point rule"); 48 t.eq(styleMap.styles["default"].rules[1].symbolizer, "bar", "assigned line symbolizer from defaultStyle correctly to point rule"); 49 t.eq(styleMap.styles["default"].rules[1].geometryType, "generic:line", "assign geometry type correctly to line rule"); 50 t.eq(styleMap.styles["default"].rules[2].symbolizer, "foobar", "assigned polygon symbolizer correctly to polygon rule"); 51 t.eq(styleMap.styles["default"].rules[2].geometryType, "generic:polygon", "assign geometry type correctly to polygon rule"); 52 } 53 39 54 </script> 40 55 </head> 41 56 <body> -
tests/Rule.html
old new 21 21 rule.destroy(); 22 22 t.eq(rule.symbolizer, null, "symbolizer hash nulled properly"); 23 23 } 24 25 function test_Rule_evaluate(t) { 26 t.plan(2); 27 28 var rule = new OpenLayers.Rule(); 29 rule.geometryType = "generic:line"; 24 30 31 var feature = {geometry: new OpenLayers.Geometry.MultiLineString()}; 32 t.eq(rule.evaluate(feature), true, "Rule correctly evaluated for line feature"); 33 34 feature.geometry = new OpenLayers.Geometry.Point(); 35 t.eq(rule.evaluate(feature), false, "Rule correctly evaluated for point feature"); 36 } 37 25 38 </script> 26 39 </head> 27 40 <body> -
tests/Style.html
old new 102 102 } 103 103 104 104 function test_Style_createSymbolizer(t) { 105 t.plan( 2);105 t.plan(4); 106 106 var style = new OpenLayers.Style(); 107 107 var rule = new OpenLayers.Rule({ 108 id: Math.random() 108 symbolizer: { 109 id: Math.random() 110 } 109 111 }); 110 112 var elseRule = new OpenLayers.Rule({ 111 id: Math.random(), 113 symbolizer: { 114 id: Math.random() 115 }, 112 116 elseFilter: true 113 117 }); 114 118 style.addRules([rule, elseRule]); 115 119 116 120 // test that applySymbolizer is only called with rule 117 style.applySymbolizer = function(r) { 118 t.eq(r.id, rule.id, "(plain) applySymbolizer called with correct rule"); 121 style.applySymbolizer = function(m, s) { 122 t.eq(s.id, rule.symbolizer.id, "(plain) applySymbolizer called with correct rule"); 123 return s; 119 124 } 125 style.defaultStyle.id = rule.symbolizer.id; 120 126 style.createSymbolizer(new OpenLayers.Feature.Vector()); 121 127 122 128 rule.evaluate = function() {return false;}; 123 style.applySymbolizer = function(r) { 124 t.eq(r.id, elseRule.id, "(else) applySymbolizer called with correct rule"); 129 style.applySymbolizer = function(m, s) { 130 t.eq(s.id, elseRule.symbolizer.id, "(else) applySymbolizer called with correct rule"); 131 return s; 125 132 } 133 style.defaultStyle.id = elseRule.symbolizer.id; 126 134 style.createSymbolizer(new OpenLayers.Feature.Vector()); 127 135 } 128 136 -
lib/OpenLayers/Format/SLD/v1.js
old new 137 137 }, 138 138 "FeatureTypeStyle": function(node, style) { 139 139 // OpenLayers doesn't have a place for FeatureTypeStyle 140 // Name, Title, Abstract, FeatureTypeName, or 141 // SemanticTypeIdentifier so, we make a temporary object 142 // and later just use the Rule(s). 140 // Name, Title, Abstract, or FeatureTypeName, so we make 141 // a temporary object and later just use the Rule(s), which 142 // will hold the SemanticTypeIdentifier from the 143 // FeatureTypeStyle. 143 144 var obj = { 145 semanticTypeIdentifier: null, 144 146 rules: [] 145 147 }; 146 148 this.readChildNodes(node, obj); 147 149 style.rules = obj.rules; 148 150 }, 151 "SemanticTypeIdentifier": function(node, obj) { 152 obj.semanticTypeIdentifier = this.getChildValue(node); 153 }, 149 154 "Rule": function(node, obj) { 150 155 var rule = new OpenLayers.Rule(); 151 156 this.readChildNodes(node, rule); 157 rule.geometryType = obj.semanticTypeIdentifier; 152 158 obj.rules.push(rule); 153 159 }, 154 160 "ElseFilter": function(node, rule) { … … 602 608 } 603 609 604 610 // add FeatureTypeStyles 605 this.writeNode(node, "FeatureTypeStyle", style); 611 // create one FeatureTypeStyle for each SemanticTypeIdentifier 612 var featureTypeStyles = {}; 613 var rule, geometryType; 614 for(var i=0; i<style.rules.length; ++i) { 615 rule = style.rules[i]; 616 geometryType = rule.geometryType; 617 if (!geometryType) { 618 geometryType = "ol:undefined"; 619 } 620 if (!featureTypeStyles[geometryType]) { 621 featureTypeStyles[geometryType] = [rule]; 622 } else { 623 featureTypeStyles[geometryType].push(rule); 624 } 625 } 626 for (var i in featureTypeStyles) { 627 this.writeNode(node, "FeatureTypeStyle", { 628 rules: featureTypeStyles[i], 629 semanticTypeIdentifier: i 630 }); 631 } 606 632 607 633 return node; 608 634 }, … … 611 637 "IsDefault", {value: (bool) ? "1" : "0"} 612 638 ); 613 639 }, 614 "FeatureTypeStyle": function(style) { 640 "FeatureTypeStyle": function(featureTypeStyle) { 641 var rules = featureTypeStyle.rules; 642 var semanticTypeIdentifier = 643 featureTypeStyle.semanticTypeIdentifier; 644 615 645 var node = this.createElementNSPlus("FeatureTypeStyle"); 616 646 617 647 // OpenLayers currently stores no Name, Title, Abstract, 618 648 // FeatureTypeName, or SemanticTypeIdentifier information 619 // related to FeatureTypeStyle 649 // related to FeatureTypeStyle. So we create one 650 // FeatureTypeStyle for each SemanticTypeIdentifier (i.e. 651 // geometryType) found inside our rules 620 652 653 if (semanticTypeIdentifier != "ol:undefined") { 654 this.writeNode(node, "SemanticTypeIdentifier", 655 semanticTypeIdentifier); 656 } 657 621 658 // add in rules 622 for (var i=0; i<style.rules.length; ++i) {623 this.writeNode(node, "Rule", style.rules[i]);659 for (var i=0; i<rules.length; ++i) { 660 this.writeNode(node, "Rule", rules[i]); 624 661 } 625 662 626 663 return node; 627 664 }, 665 "SemanticTypeIdentifier": function(identifier) { 666 return this.createElementNSPlus( 667 "SemanticTypeIdentifier", {value: identifier}); 668 }, 628 669 "Rule": function(rule) { 629 670 var node = this.createElementNSPlus("Rule"); 630 671 -
lib/OpenLayers/StyleMap.js
old new 144 144 })); 145 145 } 146 146 this.styles[renderIntent].addRules(rules); 147 return this; 147 148 }, 149 150 /** 151 * Method: makeGeometryTypeAware 152 * Convenience method that converts a rule with a symbolizer hash 153 * keyed by geometry types for which the symbolizers are intended, to 154 * geometry type aware rules. In SLD, a rule with different symbolizers 155 * for point, line and polygon means that the feature will be rendered as 156 * point, line and polygon, independent of its original feature type. 157 * This allows us to e.g. render a point symbol at the centroid point of a 158 * polygon. People sometimes define symbolizers like that, hoping that 159 * this means if we have a point, line or polygon feature, only the point, 160 * line or polygon symbolizer will be applied. This method will convert 161 * the whole style map so that rules with such symbolizers become a set of 162 * rules with an according {<OpenLayers.Rule.geometryType>}. 163 * 164 * Parameters: 165 * mapping - {Object} A hash that maps the geometry type keys found in 166 * the symbolizer hash to SemanticTypeIdentifier compliant geometry 167 * type identifiers. If not specified, the following default mapping 168 * will be used: 169 * (code) 170 * { 171 * "Point": "generic:point", 172 * "Line": "generic:line", 173 * "Polygon": "generic:polygon" 174 * } 175 * (end) 176 * 177 * Returns: 178 * {<OpenLayers.StyleMap>} the modified style map (which will also be 179 * modified inline). 180 */ 181 makeGeometryTypeAware: function(mapping) { 182 if (!mapping) { 183 mapping = { 184 "Point": "generic:point", 185 "Line": "generic:line", 186 "Polygon": "generic:polygon" 187 } 188 } 189 190 var modified; 191 var defaultRule, style, rules, rule, symbolizer; 192 for (var s in this.styles) { 193 style = this.styles[s]; 194 rules = style.rules || []; 195 defaultRule = new OpenLayers.Rule( 196 {symbolizer: style.defaultStyle}); 197 rules.push(defaultRule); 198 for (var i=rules.length-1; i>=0; --i) { 199 rule = rules[i]; 200 for (var m in mapping) { 201 symbolizer = rule.symbolizer[m]; 202 modified = false; 203 if (symbolizer) { 204 rules.push(OpenLayers.Util.applyDefaults({ 205 id: OpenLayers.Util.createUniqueID( 206 rule.CLASS_NAME + "_"), 207 symbolizer: symbolizer, 208 geometryType: mapping[m] 209 }, rule)); 210 modified = true; 211 } 212 } 213 if (modified == true || rule == defaultRule) { 214 OpenLayers.Util.removeItem(rules, rule); 215 } 216 } 217 } 218 return this; 219 }, 148 220 149 221 CLASS_NAME: "OpenLayers.StyleMap" 150 222 }); -
lib/OpenLayers/Rule.js
old new 66 66 * Property: symbolizer 67 67 * {Object} Symbolizer or hash of symbolizers for this rule. If hash of 68 68 * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The 69 * latter if useful if it is required to style e.g. vertices of a line70 * with a point symbolizer. Note, however, that this is not implemented71 * yet in OpenLayers, but it is the way how symbolizers are defined in72 * SLD.69 * latter if useful if it is required to style e.g. the centroid of a 70 * polygon with a point symbolizer. Note, however, that this is not 71 * implemented yet in OpenLayers. To specify a rule that only applies 72 * to specific geometry types, the <geometryType> property can be used. 73 73 */ 74 74 symbolizer: null, 75 75 76 76 /** 77 * Property: geometryType 78 * {String} If set, the rule will only be applied to feature geometries of 79 * a specified geometry type. The values used here are the generic values 80 * defined in the SLD spec for the <SemanticTypeIdentifier> property of a 81 * FeatureTypeStyle. Supported values are: 82 * - "generic:point" 83 * - "generic:line" 84 * - "generic:polygon" 85 */ 86 geometryType: null, 87 88 /** 77 89 * APIProperty: minScaleDenominator 78 90 * {Number} or {String} minimum scale at which to draw the feature. 79 91 * In the case of a String, this can be a combination of text and … … 132 144 evaluate: function(feature) { 133 145 var context = this.getContext(feature); 134 146 var applies = true; 147 148 // check geometry type 149 var semanticType = this.geometryType; 150 if (semanticType) { 151 var geomType = semanticType.substring( 152 semanticType.lastIndexOf(":") + 1).toLowerCase(); 153 switch(geomType) { 154 case "point": 155 case "line": 156 case "polygon": 157 if (feature.geometry.CLASS_NAME.toLowerCase().indexOf( 158 geomType) == -1) { 159 return false; 160 } 161 break; 162 } 163 } 135 164 136 165 if (this.minScaleDenominator || this.maxScaleDenominator) { 137 166 var scale = feature.layer.map.getScale(); 138 167 } 139 168 140 169 // check if within minScale/maxScale bounds 141 if ( this.minScaleDenominator) {170 if (applies && this.minScaleDenominator) { 142 171 applies = scale >= OpenLayers.Style.createLiteral( 143 172 this.minScaleDenominator, context); 144 173 } -
lib/OpenLayers/Style.js
old new 127 127 * {Object} symbolizer hash 128 128 */ 129 129 createSymbolizer: function(feature) { 130 var style = this.createLiterals( 131 OpenLayers.Util.extend({}, this.defaultStyle), feature); 130 var style = this.applySymbolizer({}, this.defaultStyle, feature); 132 131 133 132 var rules = this.rules; 134 133 … … 145 144 elseRules.push(rule); 146 145 } else { 147 146 appliedRules = true; 148 this.applySymbolizer( rule, style, feature);147 this.applySymbolizer(style, rule.symbolizer, feature); 149 148 } 150 149 } 151 150 } … … 154 153 if(appliedRules == false && elseRules.length > 0) { 155 154 appliedRules = true; 156 155 for(var i=0; i<elseRules.length; i++) { 157 this.applySymbolizer( elseRules[i], style, feature);156 this.applySymbolizer(style, elseRules[i].symbolizer, feature); 158 157 } 159 158 } 160 159 … … 172 171 * Method: applySymbolizer 173 172 * 174 173 * Parameters: 175 * rule - {OpenLayers.Rule}176 * s tyle- {Object}174 * mergedSymbolizer - {Object} 175 * symbolizer - {Object} 177 176 * feature - {<OpenLayer.Feature.Vector>} 178 177 * 179 178 * Returns: 180 * {Object} A style withnew symbolizer applied.179 * {Object} The merged symbolizer with a new symbolizer applied. 181 180 */ 182 applySymbolizer: function(rule, style, feature) { 181 applySymbolizer: function(mergedSymbolizer, symbolizer, feature) { 182 // TBD This is not the behavior as intended by the SLD spec. 183 // Currently, we only apply PointSymbolizers to points, 184 // LineSymbolizers to lines and so on. In the future, a 185 // PointSymbolizer should also be applyable e.g. to a polygon, which 186 // means we want to render a point at its centroid point. 183 187 var symbolizerPrefix = feature.geometry ? 184 188 this.getSymbolizerPrefix(feature.geometry) : 185 189 OpenLayers.Style.SYMBOLIZER_PREFIXES[0]; 186 190 187 var symbolizer = rule.symbolizer[symbolizerPrefix] || rule.symbolizer;188 189 191 // merge the style with the current style 192 // TBD In the future, we should render a separate geometry for each 193 // symbolizer. This will make it possible to render e.g. a highway 194 // with a narrow black line on top a wide yellow line 190 195 return this.createLiterals( 191 OpenLayers.Util.extend(style, symbolizer), feature); 196 OpenLayers.Util.extend(mergedSymbolizer, 197 symbolizer[symbolizerPrefix] || symbolizer), feature); 192 198 }, 193 199 194 200 /** -
examples/tasmania/sld-tasmania.xml
old new 18 18 <sld:Title>title</sld:Title> 19 19 <sld:Abstract>abstract</sld:Abstract> 20 20 <sld:FeatureTypeName>Feature</sld:FeatureTypeName> 21 <sld:SemanticTypeIdentifier>generic: geometry</sld:SemanticTypeIdentifier>21 <sld:SemanticTypeIdentifier>generic:polygon</sld:SemanticTypeIdentifier> 22 22 <sld:Rule> 23 23 <sld:Name>testRuleName</sld:Name> 24 24 <sld:Title>title</sld:Title>
