Adding zoomfilter type to alleviate filter complexity

This commit is contained in:
Tom MacWright 2011-01-20 11:53:28 -05:00
parent 1860ded45e
commit 6571489ef9
4 changed files with 133 additions and 118 deletions

View File

@ -82,7 +82,7 @@ var mess = {
'selector', 'quoted', 'expression', 'rule',
'call', 'url', 'alpha', 'import',
'mixin', 'comment', 'anonymous', 'value', 'javascript',
'comparison', 'reference', 'filter'
'comparison', 'reference', 'filter', 'zoomfilter'
].forEach(function (n) {
require(path.join('mess', 'tree', n));
});

View File

@ -858,7 +858,11 @@ mess.Parser = function Parser(env) {
if ((op = $(this.entities.comparison)) &&
(val = $(this.entities.quoted) || $(/^[\w-]+/))) {
if (! $(']')) return;
return new(tree.Filter)(key, op, val, memo);
if (key == 'zoom') {
return new(tree.ZoomFilter)(key, op, val, memo);
} else {
return new(tree.Filter)(key, op, val, memo);
}
}
}
},

View File

@ -6,126 +6,17 @@ tree.Filter = function(key, op, val, index) {
this.op = op;
this.val = val;
this.index = index;
/**
* Create an array of true, false values
* which denotes whether this filter should apply
* to each of the zoom levels from 0-22.
*/
if (this.key === 'zoom') {
var val = parseInt(this.val, 10);
this.zoom_range = [];
if (this.op.value === '>' || this.op.value === '>=') {
if (this.op.value === '>') val++;
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = (i <= val);
}
} else {
// TODO: non-correct ops will fail here
if (this.op.value === '<') val--;
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = (i >= val);
}
}
}
this.zooms = {
'1': [200000000, 500000000],
'2': [100000000, 200000000],
'3': [50000000, 100000000],
'4': [25000000, 50000000],
'5': [12500000, 25000000],
'6': [6500000, 12500000],
'7': [3000000, 6500000],
'8': [1500000, 3000000],
'9': [750000, 1500000],
'10': [400000, 750000],
'11': [200000, 400000],
'12': [100000, 200000],
'13': [50000, 100000],
'14': [25000, 50000],
'15': [12500, 25000],
'16': [5000, 12500],
'17': [2500, 5000],
'18': [1000, 2500],
'19': [500, 1000],
'20': [250, 500],
'21': [100, 250],
'22': [50, 100]
};
};
/**
* Find the overlap of this and another set
*/
tree.Filter.prototype.intersection = function(filter) {
if (filter.zoom_range) {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = this.zoom_range[i] && filter.zoom_range[i];
}
}
};
/**
* Find the union of this and another set
*/
tree.Filter.prototype.union = function(filter) {
if (filter.zoom_range) {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = this.zoom_range[i] || filter.zoom_range[i];
}
}
};
/**
* Invert this style rule. Apply to all zoom levels
* that the rule previously did not apply to and
* vice versa.
*
* Usage is for doing the equivalent of an ElseFilter
* for defaulting to non-zoom-filtered rules
*/
tree.Filter.prototype.inverse = function() {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = !this.zoom_range[i];
}
};
tree.Filter.prototype.toCSS = function(env) {
if (this.key === 'zoom') {
if (parseInt(this.val) > 22 || parseInt(this.val) < 0) {
throw {
message: 'Only zoom levels between 0 and 22 supported.',
index: this.index
}
}
if (this.op.toCSS() == '&gt;') {
return '<MaxScaleDenominator>' + this.zooms[this.val][0] +
'</MaxScaleDenominator>';
}
if (this.op.toCSS() == '&gt; =') {
return '<MaxScaleDenominator>' + this.zooms[this.val][1] +
'</MaxScaleDenominator>';
}
if (this.op.toCSS() == '&lt;') {
return '<MinScaleDenominator>' + this.zooms[this.val][1] +
'</MinScaleDenominator>';
}
if (this.op.toCSS() == '&lt; =') {
return '<MinScaleDenominator>' + this.zooms[this.val][0] +
'</MinScaleDenominator>';
}
} else {
if (this.val.is) {
this.val = this.val.toCSS((this.val.is == 'string'));
}
return '<Filter>[' + this.key + '] ' +
this.op.toCSS() +
' ' +
this.val +
'</Filter>';
if (this.val.is) {
this.val = this.val.toCSS((this.val.is == 'string'));
}
return '<Filter>[' + this.key + '] ' +
this.op.toCSS() +
' ' +
this.val +
'</Filter>';
};
})(require('mess/tree'));

120
lib/mess/tree/zoomfilter.js Normal file
View File

@ -0,0 +1,120 @@
(function(tree) {
tree.ZoomFilter = function(key, op, val, index) {
this.key = key;
this.op = op;
this.val = parseInt(val);
this.index = index;
this.zoom_range = this.create_range(this.op.value, this.val);
this.zooms = {
};
};
/**
* Create an array of true, false values
* which denotes whether this filter should apply
* to each of the zoom levels from 0-22.
*/
tree.ZoomFilter.prototype.create_range = function(op, value) {
var max_zoom = 22;
var zoom_range = [];
if (op === '>' || op === '>=') {
if (op === '>') val++;
for (var i = 0; i < max_zoom; i++) {
zoom_range[i] = (i >= val);
}
} else {
if (op === '<') val--;
for (var i = 0; i < max_zoom; i++) {
zoom_range[i] = (i <= val);
}
}
return zoom_range;
};
/**
* Find the overlap of this and another set
*/
tree.ZoomFilter.prototype.intersection = function(filter) {
if (filter.zoom_range) {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = this.zoom_range[i] && filter.zoom_range[i];
}
}
};
/**
* Find the union of this and another set
*/
tree.ZoomFilter.prototype.union = function(filter) {
if (filter.zoom_range) {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = this.zoom_range[i] || filter.zoom_range[i];
}
}
};
/**
* Invert this style rule. Apply to all zoom levels
* that the rule previously did not apply to and
* vice versa.
*
* Usage is for doing the equivalent of an ElseFilter
* for defaulting to non-zoom-filtered rules
*/
tree.ZoomFilter.prototype.inverse = function() {
for (var i = 0; i < this.max_zoom; i++) {
this.zoom_range[i] = !this.zoom_range[i];
}
};
tree.ZoomFilter.prototype.toCSS = function(env) {
if (this.val > 22 || this.val < 0) {
throw {
message: 'Only zoom levels between 0 and 22 supported.',
index: this.index
}
}
var zooms = {
'1': [200000000, 500000000],
'2': [100000000, 200000000],
'3': [50000000, 100000000],
'4': [25000000, 50000000],
'5': [12500000, 25000000],
'6': [6500000, 12500000],
'7': [3000000, 6500000],
'8': [1500000, 3000000],
'9': [750000, 1500000],
'10': [400000, 750000],
'11': [200000, 400000],
'12': [100000, 200000],
'13': [50000, 100000],
'14': [25000, 50000],
'15': [12500, 25000],
'16': [5000, 12500],
'17': [2500, 5000],
'18': [1000, 2500],
'19': [500, 1000],
'20': [250, 500],
'21': [100, 250],
'22': [50, 100]};
switch (this.op.value) {
case '&gt;':
return '<MaxScaleDenominator>' + zooms[this.val][0] +
'</MaxScaleDenominator>';
case '&gt;=':
return '<MaxScaleDenominator>' + zooms[this.val][1] +
'</MaxScaleDenominator>';
case '&lt;':
return '<MinScaleDenominator>' + zooms[this.val][1] +
'</MinScaleDenominator>';
case '&lt;=':
return '<MinScaleDenominator>' + zooms[this.val][0] +
'</MinScaleDenominator>';
}
};
})(require('mess/tree'));