basic zoom filters are working

This commit is contained in:
Konstantin Käfer 2011-01-21 11:13:48 -05:00
parent 37f0b8c121
commit 509c260ac5
3 changed files with 132 additions and 90 deletions

View File

@ -4,7 +4,8 @@ var path = require('path'),
Step = require('step'), Step = require('step'),
_ = require('underscore')._, _ = require('underscore')._,
sys = require('sys'), sys = require('sys'),
mess = require('mess'); mess = require('mess'),
tree = require('mess/tree');
require.paths.unshift(path.join(__dirname, '..', 'lib')); require.paths.unshift(path.join(__dirname, '..', 'lib'));
@ -211,7 +212,7 @@ mess.Renderer = function Renderer(env) {
// definitions are ordered in specificity, // definitions are ordered in specificity,
// high to low // high to low
// //
// basically if 'this level' has // basically if 'this level' has
// a filter, then keep going, otherwise // a filter, then keep going, otherwise
// this is the final selector. // this is the final selector.
var winners = []; var winners = [];
@ -244,21 +245,34 @@ mess.Renderer = function Renderer(env) {
}, },
resolve_filters: function(definitions) { resolve_filters: function(definitions) {
var negated_filters = []; var negatedFilters = [];
var negatedZoom = new tree.ZoomFilter('zoom', { value: '>=' }, '0');
for (var i = 0; i < definitions.length; i++) { for (var i = 0; i < definitions.length; i++) {
if (definitions[i].selector.filters.length) { var filters = definitions[i].selector.filters;
// array of the negation of this definition's filters var normal = filters.filter(function(f) { return f instanceof tree.Filter; });
var negation = definitions[i].selector.filters.map( var zoom = filters.filter(function(f) { return f instanceof tree.ZoomFilter; });
function(f) { return f.negate(); });
// add in existing negations var negation = normal.map(function(f) { return f.negate(); });
// TODO: run uniq on this.
definitions[i].selector.filters =
definitions[i].selector.filters.concat(negated_filters);
// add this definition's filter's negations to the list // add in existing negations
negated_filters = negated_filters.concat(negation); // TODO: run uniq on this.
} normal.push.apply(normal, negatedFilters);
// add this definition's filter's negations to the list
negatedFilters.push.apply(negatedFilters, negation);
// Merge all zoom filters without overwriting existing zoom
// filters; they might be referenced in other selectors.
var currentZoom = new tree.ZoomFilter('zoom', { value: '>=' }, '0');
zoom.forEach(function(f) { currentZoom.intersection(f); });
// Only add the negated current zoom when there actually are zoom filters.
var negation = zoom.length ? currentZoom.negated() : false;
currentZoom.intersection(negatedZoom);
if (negation) negatedZoom.intersection(negation);
definitions[i].selector.filters = normal.concat([currentZoom]);
} }
return definitions; return definitions;
}, },
@ -348,14 +362,14 @@ mess.Renderer = function Renderer(env) {
* @param {Array} stylesheets the results of ruleHash(). * @param {Array} stylesheets the results of ruleHash().
* @return Formalized layer definition with .styles = []. * @return Formalized layer definition with .styles = [].
*/ */
var rulesets = _.flatten(stylesheets.map(function(rulesets) { var rulesets = _.flatten(stylesheets.map(function(rulesets) {
return rulesets[2].toMSS(); return rulesets[2].toMSS();
})); }));
var output = [entities(entity_list)]; var output = [entities(entity_list)];
// TODO: must change when background colors are available // TODO: must change when background colors are available
output.push('<Map background-color="' output.push('<Map background-color="'
+ "#ffffff" + "#ffffff"
// findBackground(stylesheets) // findBackground(stylesheets)
+ '" srs="+proj=merc +a=6378137 +b=6378137 ' + '" srs="+proj=merc +a=6378137 +b=6378137 '
@ -369,7 +383,7 @@ mess.Renderer = function Renderer(env) {
var matching = rulesets.filter(function(ruleset) { var matching = rulesets.filter(function(ruleset) {
return ruleset.selector.matches(l.id, classes); return ruleset.selector.matches(l.id, classes);
}); });
// matching is an array of matching selectors, // matching is an array of matching selectors,
// in order from high specificity to low. // in order from high specificity to low.
var by_symbolizer = that.split_symbolizers(matching); var by_symbolizer = that.split_symbolizers(matching);
@ -391,7 +405,7 @@ mess.Renderer = function Renderer(env) {
// output.push(references(entity_list)); // output.push(references(entity_list));
// output.push(stylesheet_tmpl(m)); // output.push(stylesheet_tmpl(m));
output.push('</Map>'); output.push('</Map>');
callback(null, output.join('\n')); callback(null, output.join('\n'));
}, },

View File

@ -58,11 +58,25 @@ tree.Selector.prototype.combinedFilter = function() {
return f instanceof tree.ZoomFilter; return f instanceof tree.ZoomFilter;
}); });
return normal_filters.length ? var filters = [];
'<Filter>' + normal_filters.map(function(f) { if (normal_filters.length) {
filters.push('<Filter>' + normal_filters.map(function(f) {
return '(' + f.toXML().trim() + ')'; return '(' + f.toXML().trim() + ')';
}).join(' and ') + '</Filter>' }).join(' and ') + '</Filter>');
: '<ElseFilter/>'; }
if (zoom_filters.length) {
filters.push(zoom_filters.map(function(f) {
return f.toXML();
}));
}
if (!filters.length) {
return '<ElseFilter/>';
}
else {
return filters.join('');
}
}; };
})(require('mess/tree')); })(require('mess/tree'));

View File

@ -1,11 +1,41 @@
(function(tree) { (function(tree) {
tree.ZoomFilter = function(key, op, val, index) { tree.ZoomFilter = function(key, op, value, index) {
this.key = key; value = parseInt(value);
this.op = op; if (value > tree.ZoomFilter.maxZoom || value < 0) {
this.val = parseInt(val); throw {
this.index = index; message: 'Only zoom levels between 0 and ' + tree.ZoomFilter.maxZoom + ' supported.',
this.zoom_range = tree.ZoomFilter.create_range(this.op.value, this.val); index: index
};
}
this.range = tree.ZoomFilter.createRange(op.value, value);
};
tree.ZoomFilter.maxZoom = 22;
tree.ZoomFilter.ranges = {
1: 500000000,
2: 200000000,
3: 100000000,
4: 50000000,
5: 25000000,
6: 12500000,
7: 6500000,
8: 3000000,
9: 1500000,
10: 750000,
11: 400000,
12: 200000,
13: 100000,
14: 50000,
15: 25000,
16: 12500,
17: 5000,
18: 2500,
19: 1000,
20: 500,
21: 250,
22: 100
}; };
/** /**
@ -13,30 +43,46 @@ tree.ZoomFilter = function(key, op, val, index) {
* which denotes whether this filter should apply * which denotes whether this filter should apply
* to each of the zoom levels from 0-22. * to each of the zoom levels from 0-22.
*/ */
tree.ZoomFilter.create_range = function(op, value) { tree.ZoomFilter.createRange = function(op, value) {
var max_zoom = 22; var range = [];
var zoom_range = [];
if (op === '>' || op === '>=') { if (op === '>' || op === '>=') {
if (op === '>') value++; if (op === '>') value++;
for (var i = 0; i < max_zoom; i++) { for (var i = 0; i < tree.ZoomFilter.maxZoom; i++) {
zoom_range[i] = (i >= value); range[i] = (i >= value);
} }
} else { } else {
if (op === '<') value--; if (op === '<') value--;
for (var i = 0; i < max_zoom; i++) { for (var i = 0; i < tree.ZoomFilter.maxZoom; i++) {
zoom_range[i] = (i <= value); range[i] = (i <= value);
} }
} }
return zoom_range; return range;
}; };
/**
* Returns an array of ranges that are set.
*/
tree.ZoomFilter.getRanges = function(range) {
var ranges = [], start = null;
for (var i = 0; i < range.length; i++) {
if (start == null && range[i]) {
start = i;
} else if (start != null && !range[i]) {
ranges.push([start, i - 1]);
start = null;
}
}
if (start != null) ranges.push([start, 22]);
return ranges;
}
/** /**
* Find the overlap of this and another set * Find the overlap of this and another set
*/ */
tree.ZoomFilter.prototype.intersection = function(filter) { tree.ZoomFilter.prototype.intersection = function(filter) {
if (filter.zoom_range) { if (filter.range) {
for (var i = 0; i < this.max_zoom; i++) { for (var i = 0; i < this.range.length; i++) {
this.zoom_range[i] = this.zoom_range[i] && filter.zoom_range[i]; this.range[i] = this.range[i] && filter.range[i];
} }
} }
}; };
@ -45,9 +91,9 @@ tree.ZoomFilter.prototype.intersection = function(filter) {
* Find the union of this and another set * Find the union of this and another set
*/ */
tree.ZoomFilter.prototype.union = function(filter) { tree.ZoomFilter.prototype.union = function(filter) {
if (filter.zoom_range) { if (filter.range) {
for (var i = 0; i < this.max_zoom; i++) { for (var i = 0; i < this.range.length; i++) {
this.zoom_range[i] = this.zoom_range[i] || filter.zoom_range[i]; this.range[i] = this.range[i] || filter.range[i];
} }
} }
}; };
@ -60,58 +106,26 @@ tree.ZoomFilter.prototype.union = function(filter) {
* Usage is for doing the equivalent of an ElseFilter * Usage is for doing the equivalent of an ElseFilter
* for defaulting to non-zoom-filtered rules * for defaulting to non-zoom-filtered rules
*/ */
tree.ZoomFilter.prototype.negate = function() { tree.ZoomFilter.prototype.negated = function() {
this.zoom_range = this.zoom_range.map(function(i) { var negated = this.clone();
negated.range = this.range.map(function(i) {
return !i; return !i;
}); });
return this; return negated;
}; };
tree.ZoomFilter.prototype.toXML = function(env) { tree.ZoomFilter.prototype.toXML = function(env) {
if (this.val > 22 || this.val < 0) { var ranges = tree.ZoomFilter.getRanges(this.range);
throw { return ranges.map(function(range) {
message: 'Only zoom levels between 0 and 22 supported.', return (range[0] > 0 ? '<MinScaleDenominator>' + /*tree.ZoomFilter.ranges[*/range[0]/*]*/ + '</MinScaleDenominator>' : '') +
index: this.index (range[1] < 22 ? '<MaxScaleDenominator>' + /*tree.ZoomFilter.ranges[*/range[1]/*]*/ + '</MaxScaleDenominator>' : '');
}; });
}
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 '>':
return '<MaxScaleDenominator>' + zooms[this.val][0] +
'</MaxScaleDenominator>';
case '>=':
return '<MaxScaleDenominator>' + zooms[this.val][1] +
'</MaxScaleDenominator>';
case '<':
return '<MinScaleDenominator>' + zooms[this.val][1] +
'</MinScaleDenominator>';
case '<=':
return '<MinScaleDenominator>' + zooms[this.val][0] +
'</MinScaleDenominator>';
}
}; };
tree.ZoomFilter.prototype.clone = function() {
var obj = Object.create(Object.getPrototypeOf(this));
obj.range = this.range.slice();
return obj;
}
})(require('mess/tree')); })(require('mess/tree'));