plepe / pgmapcss

PGMapCSS is a library for PostgreSQL/PostGIS which works between an osm2pgsql based database and Mapnik (and maybe other renderers). It processes database (usually OpenStreetMap) objects according to MapCSS rules and calculates resulting colors, widths and other properties for Symbolizers, even geometric modifications.
GNU Affero General Public License v3.0
35 stars 8 forks source link

Waiting for Mapnik to implement Expressions for all values #2

Closed plepe closed 10 years ago

plepe commented 11 years ago

An important requirement for pgmapcss to work is, that Mapnik can read all Symbolizer values from database columns. e.g. <LineSymbolizer stroke="[color]" stroke-width="[width]" />

See Mapnik issue mapnik/mapnik#828.

Hope there's a test-branch soon ...

springmeyer commented 11 years ago

there is a branch that does stroke-width: https://github.com/mapnik/mapnik/compare/master...stroke-width-expr but this is a very big endeavour to make all properties expressions without a refactoring in core to make it easier to do (which is where things are somewhat stuck). My best sense is that after we move to requiring c++11 features this will become more feasible.

plepe commented 11 years ago

I know about stroke-width-expr, in fact I'm already using it for testing purposes. And it works fine :-)

If it would be possible to also read line/polygon/text colors from db columns, pgmapcss would start to be usable.

springmeyer commented 11 years ago

thinking out loud: what format(s) for colors should be supported? should colors be forced to be read from a single column or multiple? what happens if the data contains 7 million rows and the stylesheet contains a typo and every single 7 million rows a color is attempted to be parsed and fails? Should mapnik throw an exception on the first one or print a warning for every 7 million or be silent?

plepe commented 11 years ago

formats: not sure; i guess mapnik should be able to read the same formats in expressions as it can read right now. In the case of pgmapcss it would be sufficient to read hex-values (like #ff0000) (pgmapcss could convert other formats).

single column / multiple column: I don't actually now which formats of expressions will be finally implemented, I guess something like "[foo] + [bar]" will be possible. Actually, I don't care, as for pgmapcss single columns are sufficient.

typo: I guess, that remembering whether mapnik already threw a warning on a failed parsed color would be really difficult. Printing a warning every time should be ok - maybe a configuration option to ignore invalid values could be possible - or map them to a default color. The same applies for other expressions too, doesn't it? Like reading a string for a width.

yvecai commented 10 years ago

A few color transformations would be great too: for Opensnowmap, I need to decrease the color luminance or 'luma' for proper rendering of yellow pistes, for instance. Something like:

def deluma(color,factor):
    # reduce color luma by a given factor.
    r,g,b,a=(color.r, color.g, color.b, color.a)
    r=int(r*(1-0.3*factor))
    g=int(g*(1-0.59*factor))
    b=int(b*(1-0.11*factor))

    return mapnik.Color(r,g,b,a)

http://github.com/yvecai/mapnik-opensnowmap.org/blob/master/offset-style/build-relations-style.py

plepe commented 10 years ago

Yeah, only reason why I haven't implemented that, is that Mapnik does not support Expressions for Colors yes (pgmapcss would need to guess all resulting colors). As soon as Mapnik does (and I think it can be only a short period of time, in fact I was already partly successful using the 'expr-v2' branch, I will add those functions).

plepe commented 10 years ago

So, after the release of pgmapcss 0.5.0 I started testing the expr-v2 branch of Mapnik. Mapnik still can't read many values for symbolizers directly from the database, but at least it can read them on LineSymbolizers, PolygonSymbolizers and TextSymbolizers. Therefore the 'expr-v2' template (compile with pgmapcss -texpr-v2) can handle colors on 'color', 'casing-color', 'text-color', 'text-halo-color' and 'fill-color'. I also added eval()-functions for rgb(), rgba(), deluma() and lighten() as requested (use the 'master' branch).

Now you should be able to do something like:

line[piste=ski] {
  width: 5;
  color: eval(tag('piste:color')); // the tag 'piste:color' has to be in hex notation (e.g. #ffff00).
  casing-width: 2;
  casing-color: eval(deluma(tag('piste:color'), 0.5));
}

more examples:

{
  color: eval(rgb(190, 150, 30));
  casing-color: eval(lighten(prop('color'), 1)); // copy prop color to casing-color
}

Have fun!

springmeyer commented 10 years ago

@plepe - thrilled so see you are testing the expr-v2 branch already. You'll hopefully see a lot more movement on it within about 2 weeks.

plepe commented 10 years ago

@springmeyer - Yeah, I knew, when I read the name "symbolizer-expressions", that something big is comping up :) I'm thrilled that it's finally happening!

plepe commented 10 years ago

The experimental expr-v2 branch has been merged to Mapnik master: mapnik/mapnik#2222

pgmapcss supports the upcoming Mapnik release when using the "mapnik-3.0" template.

plepe commented 10 years ago

I forgot: pgmapcss 0.7 (for Mapnik 2.x) tries to predict possible results of eval()-expressions at compile time and will therefore include possible results in the Mapnik stylesheet. This works e.g. for things like eval(cond(zoom() > 6; zoom() * 2; 15)) or eval(lighten(rgb(0.5, 30, 20), 1)).