Skip to content

Commit

Permalink
Merge pull request openlayers#790 from tschaub/expression
Browse files Browse the repository at this point in the history
Expression parsing
  • Loading branch information
tschaub committed Jun 26, 2013
2 parents f062089 + 71153d2 commit a7ca22d
Show file tree
Hide file tree
Showing 40 changed files with 4,833 additions and 1,012 deletions.
21 changes: 7 additions & 14 deletions examples/style-rules.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,8 @@
goog.require('ol.Expression');
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.control.defaults');
goog.require('ol.filter.Filter');
goog.require('ol.filter.Geometry');
goog.require('ol.geom.GeometryType');
goog.require('ol.expr');
goog.require('ol.layer.Vector');
goog.require('ol.parser.GeoJSON');
goog.require('ol.proj');
Expand All @@ -19,44 +16,40 @@ goog.require('ol.style.Text');

var style = new ol.style.Style({rules: [
new ol.style.Rule({
filter: new ol.filter.Filter(function(feature) {
return feature.get('where') == 'outer';
}),
filter: 'where == "outer"',
symbolizers: [
new ol.style.Line({
strokeColor: new ol.Expression('color'),
strokeColor: ol.expr.parse('color'),
strokeWidth: 4,
opacity: 1
})
]
}),
new ol.style.Rule({
filter: new ol.filter.Filter(function(feature) {
return feature.get('where') == 'inner';
}),
filter: 'where == "inner"',
symbolizers: [
new ol.style.Line({
strokeColor: '#013',
strokeWidth: 4,
opacity: 1
}),
new ol.style.Line({
strokeColor: new ol.Expression('color'),
strokeColor: ol.expr.parse('color'),
strokeWidth: 2,
opacity: 1
})
]
}),
new ol.style.Rule({
filter: new ol.filter.Geometry(ol.geom.GeometryType.POINT),
filter: 'geometryType("point")',
symbolizers: [
new ol.style.Shape({
size: 40,
fillColor: '#013'
}),
new ol.style.Text({
color: '#bada55',
text: new ol.Expression('label'),
text: ol.expr.parse('label'),
fontFamily: 'Calibri,sans-serif',
fontSize: 14
})
Expand Down
14 changes: 8 additions & 6 deletions examples/vector-layer.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
goog.require('ol.Expression');
goog.require('ol.Map');
goog.require('ol.RendererHint');
goog.require('ol.View2D');
goog.require('ol.filter.Filter');
goog.require('ol.expr');
goog.require('ol.layer.TileLayer');
goog.require('ol.layer.Vector');
goog.require('ol.parser.GeoJSON');
Expand All @@ -19,6 +18,11 @@ var raster = new ol.layer.TileLayer({
source: new ol.source.MapQuestOpenAerial()
});

// TODO: discuss scale dependent rules
ol.expr.register('resolution', function() {
return map.getView().getView2D().getResolution();
});

var vector = new ol.layer.Vector({
source: new ol.source.Vector({
projection: ol.proj.get('EPSG:4326')
Expand All @@ -32,13 +36,11 @@ var vector = new ol.layer.Vector({
]
}),
new ol.style.Rule({
filter: new ol.filter.Filter(function() {
return map.getView().getResolution() < 5000;
}),
filter: 'resolution() < 5000',
symbolizers: [
new ol.style.Text({
color: '#bada55',
text: new ol.Expression('name'),
text: ol.expr.parse('name'),
fontFamily: 'Calibri,sans-serif',
fontSize: 12
})
Expand Down
69 changes: 35 additions & 34 deletions src/objectliterals.jsdoc
Original file line number Diff line number Diff line change
Expand Up @@ -519,53 +519,54 @@

/**
* @typedef {Object} ol.style.IconOptions
* @property {string|ol.Expression} url Icon image url.
* @property {number|ol.Expression|undefined} width Width of the icon in pixels.
* Default is the width of the icon image.
* @property {number|ol.Expression|undefined} height Height of the icon in
* pixels. Default is the height of the icon image.
* @property {number|ol.Expression|undefined} opacity Icon opacity (0-1).
* @property {number|ol.Expression|undefined} rotation Rotation in degrees
* (0-360).
* @property {string|ol.expr.Expression} url Icon image url.
* @property {number|ol.expr.Expression|undefined} width Width of the icon
* in pixels. Default is the width of the icon image.
* @property {number|ol.expr.Expression|undefined} height Height of the
* icon in pixels. Default is the height of the icon image.
* @property {number|ol.expr.Expression|undefined} opacity Icon opacity
* (0-1).
* @property {number|ol.expr.Expression|undefined} rotation Rotation in
* degrees (0-360).
*/

/**
* @typedef {Object} ol.style.LineOptions
* @property {string|ol.Expression|undefined} strokeColor Stroke color as hex
* color code.
* @property {number|ol.Expression|undefined} strokeWidth Stroke width in
* pixels.
* @property {number|ol.Expression|undefined} opacity Opacity (0-1).
* @property {string|ol.expr.Expression|undefined} strokeColor Stroke
* color as hex color code.
* @property {number|ol.expr.Expression|undefined} strokeWidth Stroke
* width in pixels.
* @property {number|ol.expr.Expression|undefined} opacity Opacity (0-1).
*/

/**
* @typedef {Object} ol.style.PolygonOptions
* @property {string|ol.Expression|undefined} fillColor Fill color as hex color
* code.
* @property {string|ol.Expression|undefined} strokeColor Stroke color as hex
* color code.
* @property {number|ol.Expression|undefined} strokeWidth Stroke width in
* pixels.
* @property {number|ol.Expression|undefined} opacity Opacity (0-1).
* @property {string|ol.expr.Expression|undefined} fillColor Fill color as
* hex color code.
* @property {string|ol.expr.Expression|undefined} strokeColor Stroke
* color as hex color code.
* @property {number|ol.expr.Expression|undefined} strokeWidth Stroke
* width in pixels.
* @property {number|ol.expr.Expression|undefined} opacity Opacity (0-1).
*/

/**
* @typedef {Object} ol.style.RuleOptions
* @property {ol.filter.Filter|undefined} filter Filter.
* @property {ol.expr.Expression|string|undefined} filter Filter.
* @property {Array.<ol.style.Symbolizer>|undefined} symbolizers Symbolizers.
*/

/**
* @typedef {Object} ol.style.ShapeOptions
* @property {ol.style.ShapeType|undefined} type Type.
* @property {number|ol.Expression|undefined} size Size in pixels.
* @property {string|ol.Expression|undefined} fillColor Fill color as hex color
* code.
* @property {string|ol.Expression|undefined} strokeColor Stroke color as hex
* color code.
* @property {number|ol.Expression|undefined} strokeWidth Stroke width in
* pixels.
* @property {number|ol.Expression|undefined} opacity Opacity (0-1).
* @property {number|ol.expr.Expression|undefined} size Size in pixels.
* @property {string|ol.expr.Expression|undefined} fillColor Fill color as
* hex color code.
* @property {string|ol.expr.Expression|undefined} strokeColor Stroke
* color as hex color code.
* @property {number|ol.expr.Expression|undefined} strokeWidth Stroke
* width in pixels.
* @property {number|ol.expr.Expression|undefined} opacity Opacity (0-1).
*/

/**
Expand All @@ -575,11 +576,11 @@

/**
* @typedef {Object} ol.style.TextOptions
* @property {string|ol.Expression|undefined} color Color.
* @property {string|ol.Expression|undefined} fontFamily Font family.
* @property {number|ol.Expression|undefined} fontSize Font size in pixels.
* @property {string|ol.Expression} text Text for the label.
* @property {number|ol.Expression|undefined} opacity Opacity (0-1).
* @property {string|ol.expr.Expression|undefined} color Color.
* @property {string|ol.expr.Expression|undefined} fontFamily Font family.
* @property {number|ol.expr.Expression|undefined} fontSize Font size in pixels.
* @property {string|ol.expr.Expression} text Text for the label.
* @property {number|ol.expr.Expression|undefined} opacity Opacity (0-1).
*/

/**
Expand Down
3 changes: 3 additions & 0 deletions src/ol/expr.jsdoc
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/**
* @namespace ol.expr
*/
2 changes: 2 additions & 0 deletions src/ol/expr/expression.exports
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
@exportSymbol ol.expr.parse
@exportSymbol ol.expr.register
158 changes: 158 additions & 0 deletions src/ol/expr/expression.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,158 @@
goog.provide('ol.expr');
goog.provide('ol.expr.functions');

goog.require('ol.Extent');
goog.require('ol.Feature');
goog.require('ol.expr.Call');
goog.require('ol.expr.Expression');
goog.require('ol.expr.Identifier');
goog.require('ol.expr.Parser');
goog.require('ol.extent');
goog.require('ol.geom.GeometryType');


/**
* Evaluate an expression with a feature. The feature attributes will be used
* as the evaluation scope. The `ol.expr.lib` functions will be used as
* function scope. The feature itself will be used as the `this` argument.
*
* @param {ol.expr.Expression} expr The expression.
* @param {ol.Feature=} opt_feature The feature.
* @return {*} The result of the expression.
*/
ol.expr.evaluateFeature = function(expr, opt_feature) {
var result;
if (goog.isDef(opt_feature)) {
result = expr.evaluate(
opt_feature.getAttributes(), ol.expr.lib, opt_feature);
} else {
result = expr.evaluate();
}
return result;
};


/**
* Parse an expression.
* @param {string} source The expression source (e.g. `'foo + 2'`).
* @return {ol.expr.Expression} An expression instance that can be
* evaluated within some scope to provide a value.
*/
ol.expr.parse = function(source) {
var parser = new ol.expr.Parser();
return parser.parse(source);
};


/**
* Register a library function to be used in expressions.
* @param {string} name The function name (e.g. 'myFunc').
* @param {function(this:ol.Feature)} func The function to be called in an
* expression. This function will be called with a feature as the `this`
* argument when the expression is evaluated in the context of a features.
*/
ol.expr.register = function(name, func) {
ol.expr.lib[name] = func;
};


/**
* Determines whether an expression is a call expression that calls one of the
* `ol.expr.lib` functions.
*
* @param {ol.expr.Expression} expr The candidate expression.
* @return {string|undefined} If the candidate expression is a call to a lib
* function, the return will be the function name. If not, the return will be
* `undefined`.
*/
ol.expr.isLibCall = function(expr) {
var name;
if (expr instanceof ol.expr.Call) {
var callee = expr.getCallee();
if (callee instanceof ol.expr.Identifier) {
name = callee.getName();
if (!ol.expr.lib.hasOwnProperty(name)) {
name = undefined;
}
}
}
return name;
};


/**
* Library of well-known functions. These are available to expressions parsed
* with `ol.expr.parse`.
*
* @type {Object.<string, function(...)>}
*/
ol.expr.lib = {};


/**
* Enumeration of library function names.
*
* @enum {string}
*/
ol.expr.functions = {
EXTENT: 'extent',
FID: 'fid',
GEOMETRY_TYPE: 'geometryType'
};


/**
* Determine if a feature's extent intersects the provided extent.
* @param {number} minX Minimum x-coordinate value.
* @param {number} maxX Maximum x-coordinate value.
* @param {number} minY Minimum y-coordinate value.
* @param {number} maxY Maximum y-coordinate value.
* @return {boolean} The provided extent intersects the feature's extent.
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.EXTENT] = function(minX, maxX, minY, maxY) {
var intersects = false;
var geometry = this.getGeometry();
if (geometry) {
intersects = ol.extent.intersects(geometry.getBounds(),
[minX, maxX, minY, maxY]);
}
return intersects;
};


/**
* Determine if the feature identifier matches any of the provided values.
* @param {...string} var_args Feature identifiers.
* @return {boolean} The feature's identifier matches one of the given values.
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.FID] = function(var_args) {
var matches = false;
var id = this.getFeatureId();
if (goog.isDef(id)) {
for (var i = 0, ii = arguments.length; i < ii; ++i) {
if (arguments[i] === id) {
matches = true;
break;
}
}
}
return matches;
};


/**
* Determine if a feature's default geometry is of the given type.
* @param {ol.geom.GeometryType} type Geometry type.
* @return {boolean} The feature's default geometry is of the given type.
* @this {ol.Feature}
*/
ol.expr.lib[ol.expr.functions.GEOMETRY_TYPE] = function(type) {
var same = false;
var geometry = this.getGeometry();
if (geometry) {
same = geometry.getType() === type;
}
return same;
};
Loading

0 comments on commit a7ca22d

Please sign in to comment.