Rule.js 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. /* Copyright (c) 2006-2011 by OpenLayers Contributors (see authors.txt for
  2. * full list of contributors). Published under the Clear BSD license.
  3. * See http://svn.openlayers.org/trunk/openlayers/license.txt for the
  4. * full text of the license. */
  5. /**
  6. * @requires OpenLayers/BaseTypes/Class.js
  7. * @requires OpenLayers/Util.js
  8. * @requires OpenLayers/Style.js
  9. * @requires OpenLayers/Symbolizer/Point.js
  10. * @requires OpenLayers/Symbolizer/Line.js
  11. * @requires OpenLayers/Symbolizer/Polygon.js
  12. * @requires OpenLayers/Symbolizer/Text.js
  13. * @requires OpenLayers/Symbolizer/Raster.js
  14. */
  15. /**
  16. * Class: OpenLayers.Rule
  17. * This class represents an SLD Rule, as being used for rule-based SLD styling.
  18. */
  19. OpenLayers.Rule = OpenLayers.Class({
  20. /**
  21. * Property: id
  22. * {String} A unique id for this session.
  23. */
  24. id: null,
  25. /**
  26. * APIProperty: name
  27. * {String} name of this rule
  28. */
  29. name: null,
  30. /**
  31. * Property: title
  32. * {String} Title of this rule (set if included in SLD)
  33. */
  34. title: null,
  35. /**
  36. * Property: description
  37. * {String} Description of this rule (set if abstract is included in SLD)
  38. */
  39. description: null,
  40. /**
  41. * Property: context
  42. * {Object} An optional object with properties that the rule should be
  43. * evaluated against. If no context is specified, feature.attributes will
  44. * be used.
  45. */
  46. context: null,
  47. /**
  48. * Property: filter
  49. * {<OpenLayers.Filter>} Optional filter for the rule.
  50. */
  51. filter: null,
  52. /**
  53. * Property: elseFilter
  54. * {Boolean} Determines whether this rule is only to be applied only if
  55. * no other rules match (ElseFilter according to the SLD specification).
  56. * Default is false. For instances of OpenLayers.Rule, if elseFilter is
  57. * false, the rule will always apply. For subclasses, the else property is
  58. * ignored.
  59. */
  60. elseFilter: false,
  61. /**
  62. * Property: symbolizer
  63. * {Object} Symbolizer or hash of symbolizers for this rule. If hash of
  64. * symbolizers, keys are one or more of ["Point", "Line", "Polygon"]. The
  65. * latter if useful if it is required to style e.g. vertices of a line
  66. * with a point symbolizer. Note, however, that this is not implemented
  67. * yet in OpenLayers, but it is the way how symbolizers are defined in
  68. * SLD.
  69. */
  70. symbolizer: null,
  71. /**
  72. * Property: symbolizers
  73. * {Array} Collection of symbolizers associated with this rule. If
  74. * provided at construction, the symbolizers array has precedence
  75. * over the deprecated symbolizer property. Note that multiple
  76. * symbolizers are not currently supported by the vector renderers.
  77. * Rules with multiple symbolizers are currently only useful for
  78. * maintaining elements in an SLD document.
  79. */
  80. symbolizers: null,
  81. /**
  82. * APIProperty: minScaleDenominator
  83. * {Number} or {String} minimum scale at which to draw the feature.
  84. * In the case of a String, this can be a combination of text and
  85. * propertyNames in the form "literal ${propertyName}"
  86. */
  87. minScaleDenominator: null,
  88. /**
  89. * APIProperty: maxScaleDenominator
  90. * {Number} or {String} maximum scale at which to draw the feature.
  91. * In the case of a String, this can be a combination of text and
  92. * propertyNames in the form "literal ${propertyName}"
  93. */
  94. maxScaleDenominator: null,
  95. /**
  96. * Constructor: OpenLayers.Rule
  97. * Creates a Rule.
  98. *
  99. * Parameters:
  100. * options - {Object} An optional object with properties to set on the
  101. * rule
  102. *
  103. * Returns:
  104. * {<OpenLayers.Rule>}
  105. */
  106. initialize: function(options) {
  107. this.symbolizer = {};
  108. OpenLayers.Util.extend(this, options);
  109. if (this.symbolizers) {
  110. delete this.symbolizer;
  111. }
  112. this.id = OpenLayers.Util.createUniqueID(this.CLASS_NAME + "_");
  113. },
  114. /**
  115. * APIMethod: destroy
  116. * nullify references to prevent circular references and memory leaks
  117. */
  118. destroy: function() {
  119. for (var i in this.symbolizer) {
  120. this.symbolizer[i] = null;
  121. }
  122. this.symbolizer = null;
  123. delete this.symbolizers;
  124. },
  125. /**
  126. * APIMethod: evaluate
  127. * evaluates this rule for a specific feature
  128. *
  129. * Parameters:
  130. * feature - {<OpenLayers.Feature>} feature to apply the rule to.
  131. *
  132. * Returns:
  133. * {Boolean} true if the rule applies, false if it does not.
  134. * This rule is the default rule and always returns true.
  135. */
  136. evaluate: function(feature) {
  137. var context = this.getContext(feature);
  138. var applies = true;
  139. if (this.minScaleDenominator || this.maxScaleDenominator) {
  140. var scale = feature.layer.map.getScale();
  141. }
  142. // check if within minScale/maxScale bounds
  143. if (this.minScaleDenominator) {
  144. applies = scale >= OpenLayers.Style.createLiteral(
  145. this.minScaleDenominator, context);
  146. }
  147. if (applies && this.maxScaleDenominator) {
  148. applies = scale < OpenLayers.Style.createLiteral(
  149. this.maxScaleDenominator, context);
  150. }
  151. // check if optional filter applies
  152. if(applies && this.filter) {
  153. // feature id filters get the feature, others get the context
  154. if(this.filter.CLASS_NAME == "OpenLayers.Filter.FeatureId") {
  155. applies = this.filter.evaluate(feature);
  156. } else {
  157. applies = this.filter.evaluate(context);
  158. }
  159. }
  160. return applies;
  161. },
  162. /**
  163. * Method: getContext
  164. * Gets the context for evaluating this rule
  165. *
  166. * Paramters:
  167. * feature - {<OpenLayers.Feature>} feature to take the context from if
  168. * none is specified.
  169. */
  170. getContext: function(feature) {
  171. var context = this.context;
  172. if (!context) {
  173. context = feature.attributes || feature.data;
  174. }
  175. if (typeof this.context == "function") {
  176. context = this.context(feature);
  177. }
  178. return context;
  179. },
  180. /**
  181. * APIMethod: clone
  182. * Clones this rule.
  183. *
  184. * Returns:
  185. * {<OpenLayers.Rule>} Clone of this rule.
  186. */
  187. clone: function() {
  188. var options = OpenLayers.Util.extend({}, this);
  189. if (this.symbolizers) {
  190. // clone symbolizers
  191. var len = this.symbolizers.length;
  192. options.symbolizers = new Array(len);
  193. for (var i=0; i<len; ++i) {
  194. options.symbolizers[i] = this.symbolizers[i].clone();
  195. }
  196. } else {
  197. // clone symbolizer
  198. options.symbolizer = {};
  199. var value, type;
  200. for(var key in this.symbolizer) {
  201. value = this.symbolizer[key];
  202. type = typeof value;
  203. if(type === "object") {
  204. options.symbolizer[key] = OpenLayers.Util.extend({}, value);
  205. } else if(type === "string") {
  206. options.symbolizer[key] = value;
  207. }
  208. }
  209. }
  210. // clone filter
  211. options.filter = this.filter && this.filter.clone();
  212. // clone context
  213. options.context = this.context && OpenLayers.Util.extend({}, this.context);
  214. return new OpenLayers.Rule(options);
  215. },
  216. CLASS_NAME: "OpenLayers.Rule"
  217. });