Coder Social home page Coder Social logo

cascadenik's Introduction

Cascadenik

Cascadenik implements cascading stylesheets for Mapnik.

It’s an abstraction layer and preprocessor that converts special, CSS-like syntax into Mapnik-compatible style definitions. It’s easier to write complex style rules using the alternative syntax, because it allows for separation of symbolizers and provides a mechanism for inheritance.

Cascadenik supports many of Mapnik’s features in a simple declarative form:

/* Define a few colors */
@black: #000;
@orange: #f90;

/* Start with a white background */
Map
{
    map-bgcolor: #fff;
}

/* Draw roads as orange lines */
#roads
{
    /* Usually, 3px wide */
    line-width: 3;
    line-color: @orange;
    
    /* Make the important ones wider */
    &[kind=major] { line-width: 4 }
    &[kind=highway] { line-width: 5 }
    
    /* Add the road names in black */
    name
    {
        text-placement: line;
        text-face-name: "DejaVu Sans Book";
        text-fill: @black;
        text-size: 12;
    }
}

See more examples at https://github.com/mapnik/Cascadenik/wiki/Examples.

Usage

See INSTALL.md for installation instructions.

See the doc/ folder for more usage examples.

Unroll the rules in example.mss and show their cascade order:

% cascadenik-style.py example.mss > example-ordered-unrolled.mss

Compile example.mml into a Mapnik-suitable XML file:

% cascadenik-compile.py example.mml example-compiled.xml

Render a MML file directly to an image using nik2img.py:

% nik2img.py example.mml example.png

cascadenik's People

Contributors

bwg avatar migurski avatar mojodna avatar ninowalker avatar nvkelso avatar rcoup avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

cascadenik's Issues

text-max-char-angle-delta doesn't output max_char_angle_delta

Targetting mapnik 0.7.1

mss

#course-trail-label trail_name
{
    text-spacing: 256;
    text-placement: line;
    text-max-char-angle-delta: 37;

    text-face-name: 'PT Sans Narrow Regular';
    text-fill: #5a3b00;
    text-size: 8;

    text-halo-fill: #f7f7e6;
    text-halo-radius: 1;

    text-dy: 10;
}

Actual resulting xml snippet:

   <Rule name="rule 4">
      <TextSymbolizer dy="10" face_name="PT Sans Narrow Regular" fill="rgb(90,59,0)" halo_fill="rgb(247,247,230)" halo_radius="1" name="trail_name" placement="line" size="8" spacing="256" />
    </Rule>'

Expected resulting xml snippet:

<Rule name="rule 4">
    <TextSymbolizer dy="10" face_name="PT Sans Narrow Regular" fill="rgb(90,59,0)" halo_fill="rgb(247,247,230)" halo_radius="1" name="trail_name" placement="line" size="8" spacing="256" max_char_angle_delta="37"/>
</Rule>'

Python 2.5.1 os x (leopard) test failures with relative-paths branch

Cascadenik spring$ python test.py 
..................E....
Cascadenik debug: Warning, FontSets will be ignored as they are not yet supported in Mapnik via Python...
.....E..................................FF.F.F...........................................................................................
======================================================================
ERROR: testCompile1 (__main__.CompileXMLTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 1754, in testCompile1
    cfg = tempfile.NamedTemporaryFile('w', delete=False)
TypeError: NamedTemporaryFile() got an unexpected keyword argument 'delete'

======================================================================
ERROR: testLocalDefaultsFromFile (__main__.DataSourcesTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 1602, in testLocalDefaultsFromFile
    cfg = tempfile.NamedTemporaryFile('w', delete=False)
TypeError: NamedTemporaryFile() got an unexpected keyword argument 'delete'

======================================================================
FAIL: testLocalLinkedSheetPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2352, in testLocalLinkedSheetPaths
    assert not os.path.isabs(shp_path)
AssertionError

======================================================================
FAIL: testLocalizedPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2156, in testLocalizedPaths
    assert not os.path.isabs(img_path)
AssertionError

======================================================================
FAIL: testRelativePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2228, in testRelativePaths
    assert not os.path.isabs(img_path)
AssertionError

======================================================================
FAIL: testRemotePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2316, in testRemotePaths
    assert not os.path.isabs(img_path)
AssertionError

----------------------------------------------------------------------
Ran 160 tests in 23.834s

FAILED (failures=4, errors=2)

os.rename() fails in cascadenik-compile.py

os.rename() apparently won't work if the files are on different filesystems. In my case /tmp is on a different filesystem than /home. Switching to shutli.move() (http://docs.python.org/library/shutil.html#shutil.move) fixed it for me.

This is the error I get:

owner@owner-desktop:/Documents/mapnik/mapnik$ cascadenik-compile.py funcls_roads_l.mml out.xml
output file: out.xml /home/owner/Documents/mapnik/mapnik
('/tmp/cascadenik-mapnik-HVy47I.xml', 'out.xml')
owner@owner-desktop:
/Documents/mapnik/mapnik$ cascadenik-compile.py funcls_roads_l.mml out.xml
Traceback (most recent call last):
File "/usr/local/bin/cascadenik-compile.py", line 5, in
pkg_resources.run_script('cascadenik==1.0.2', 'cascadenik-compile.py')
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 467, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1200, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.6/dist-packages/cascadenik-1.0.2-py2.6.egg/EGG-INFO/scripts/cascadenik-compile.py", line 48
os.unlink(dest_file)z
^
SyntaxError: invalid syntax
owner@owner-desktop:~/Documents/mapnik/mapnik$ cascadenik-compile.py funcls_roads_l.mml out.xml
output file: out.xml /home/owner/Documents/mapnik/mapnik
Traceback (most recent call last):
File "/usr/local/bin/cascadenik-compile.py", line 5, in
pkg_resources.run_script('cascadenik==1.0.2', 'cascadenik-compile.py')
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 467, in run_script
self.require(requires)[0].run_script(script_name, ns)
File "/usr/lib/python2.6/dist-packages/pkg_resources.py", line 1200, in run_script
execfile(script_filename, namespace, namespace)
File "/usr/local/lib/python2.6/dist-packages/cascadenik-1.0.2-py2.6.egg/EGG-INFO/scripts/cascadenik-compile.py", line 92, in
sys.exit(main(layersfile, outputfile, **options.dict))
File "/usr/local/lib/python2.6/dist-packages/cascadenik-1.0.2-py2.6.egg/EGG-INFO/scripts/cascadenik-compile.py", line 49, in main
os.rename(tmp_file, dest_file)
OSError: [Errno 18] Invalid cross-device link

* map is not picked up from mss files

try running:

nik2img.py doc/example4.mml image.png

you should see that the background is transparent, but should actually be colored. I can't see what is failing, but I'm pretty sure it has to do with the * value coming from a referenced mss.

Revisit XML bad/good

Has the move to using the Mapnik python bindings (over direct XML authoring) been an overall good move for the project? I admit that it has felt like a mistake at the times when lacking features in the Mapnik python bindings have slowed things down. While the biggest blocker, FontSets, are now fixed, the other big reason I pushed for the move was performance, and that is now radically improved for XML loading: http://mapnik.org/news/2012/04/06/faster-map-loading/. And these XML loading improvements are not going directly benefit the map construction speeds via python.

So I would be interested in @migurski and @rcoup's perspective on this. Any reason we should consider moving back to XML from your perspective?

Map attributes parsing

We should respect map level attributes like 'min_version' when an mml parsed by python, and stuff like 'font_directory' which will be available in mapnik2.

I'll take this on, but it can happen after initial release.

Handling of TextSymbolizer opacity and ratio, and Layer clear_label_cache attributes

I needed transparency (opacity) of text labels, as well as the "clear_label_cache attribute" of layers and noticed, that so far it is not possible to do either using Cascadenik (and ratio was not handled completely, either, it seems). I modified it locally and can use it now. The following is the patch (output of git diff) wrt. branch "mapnik2" (I edited it by removing some changes, because I have other local changes not of general interest here; I hope, it still works with somewhat differing line numbers in the diff specifications):


diff --git a/cascadenik/compile.py b/cascadenik/compile.py                                                                                                                            
index f54d5f2..730d085 100644                                                                                                                                                         
--- a/cascadenik/compile.py                                                                                                                                                           
+++ b/cascadenik/compile.py                                                                                                                                                           
@@ -998,6 +998,7 @@ def get_text_rule_groups(declarations):                                                                                                                           
                     'text-dy': 'dy',                                                                                                                                                 
                     'text-face-name': 'face_name',                                                                                                                                   
                     'text-fill': 'fill',                                                                                                                                             
+                    'text-opacity': 'opacity',                                                                                                                                       
                     'text-fontset': 'fontset',                                                                                                                                       
                     'text-force-odd-labels': 'force_odd_labels',                                                                                                                     
                     'text-halo-fill': 'halo_fill',                                                                                                                                   
@@ -1049,7 +1050,7 @@ def get_text_rule_groups(declarations):
             fontset = values.has_key('text-fontset') and values['text-fontset'].value or None
             size = values.has_key('text-size') and values['text-size'].value
             color = values.has_key('text-fill') and values['text-fill'].value
-            
+            opacity = values.has_key('text-opacity') and values['text-opacity'].value or None
             ratio = values.has_key('text-ratio') and values['text-ratio'].value or None
             wrap_width = values.has_key('text-wrap-width') and values['text-wrap-width'].value or None
             label_spacing = values.has_key('text-spacing') and values['text-spacing'].value or None
@@ -1080,7 +1081,7 @@ def get_text_rule_groups(declarations):
                                               avoid_edges, minimum_distance, allow_overlap, label_placement, \
                                               line_spacing, character_spacing, text_transform, fontset,
                                               anchor_dx, anchor_dy,horizontal_alignment, \
-                                              vertical_alignment, justify_alignment, force_odd_labels)
+                                              vertical_alignment, justify_alignment, force_odd_labels, opacity, ratio)
             
                 rules.append(make_rule(filter, symbolizer))
         
@@ -1532,7 +1537,8 @@ def compile(src, dirs, verbose=False, srs=None, datasources_cfg=None):
                                  datasource, styles,
                                  layer_el.get('srs', None),
                                  layer_el.get('min_zoom', None) and int(layer_el.get('min_zoom')) or None,
-                                 layer_el.get('max_zoom', None) and int(layer_el.get('max_zoom')) or None)
+                                 layer_el.get('max_zoom', None) and int(layer_el.get('max_zoom')) or None,
+                                 layer_el.get('clear_label_cache', None))
     
             layers.append(layer)
     
diff --git a/cascadenik/output.py b/cascadenik/output.py
index ca07401..a8e19c1 100644
--- a/cascadenik/output.py
+++ b/cascadenik/output.py
@@ -62,7 +62,8 @@ class Map:
                 lay.srs = layer.srs or lay.srs
                 lay.minzoom = layer.minzoom or lay.minzoom
                 lay.maxzoom = layer.maxzoom or lay.maxzoom
-                
+                lay.clear_label_cache = layer.clear_label_cache if not(layer.clear_label_cache is None) else lay.clear_label_cache
+
                 for style in layer.styles:
                     lay.styles.append(style.name)
     
@@ -98,12 +99,13 @@ class Rule:
         return 'Rule(%s:%s, %s, %s)' % (repr(self.minscale), repr(self.maxscale), repr(self.filter), repr(self.symbolizers))
 
 class Layer:
-    def __init__(self, name, datasource, styles=None, srs=None, minzoom=None, maxzoom=None):
+    def __init__(self, name, datasource, styles=None, srs=None, minzoom=None, maxzoom=None, clearlabelcache=None):
         assert isinstance(name, basestring)
         assert styles is None or type(styles) in (list, tuple)
         assert srs is None or isinstance(srs, basestring)
         assert minzoom is None or type(minzoom) in (int, float)
         assert maxzoom is None or type(maxzoom) in (int, float)
+        assert clearlabelcache is None or isinstance(clearlabelcache, basestring)
         
         self.name = safe_str(name)
         self.datasource = datasource
@@ -111,6 +113,7 @@ class Layer:
         self.srs = safe_str(srs)
         self.minzoom = minzoom
         self.maxzoom = maxzoom
+        self.clear_label_cache = True if (clearlabelcache and (clearlabelcache in ["on", "true", "On", "True", "ON", "TRUE", "1"])) else False
 
     def __repr__(self):
         return 'Layer(%s: %s)' % (self.name, repr(self.styles))
@@ -236,8 +239,8 @@ class TextSymbolizer:
         halo_color=None, halo_radius=None, dx=None, dy=None, avoid_edges=None, \
         minimum_distance=None, allow_overlap=None, label_placement=None, \
         character_spacing=None, line_spacing=None, text_transform=None, fontset=None, \
-        anchor_dx=None, anchor_dy=None,horizontal_alignment=None,vertical_alignment=None,
-        justify_alignment=None, force_odd_labels=None):
+        anchor_dx=None, anchor_dy=None,horizontal_alignment=None,vertical_alignment=None, \
+        justify_alignment=None, force_odd_labels=None, opacity=None, ratio=None):
 
         assert isinstance(name, basestring)
         assert face_name is None or isinstance(face_name, basestring)
@@ -250,6 +253,8 @@ class TextSymbolizer:
         assert max_char_angle_delta is None or type(max_char_angle_delta) is int
         assert halo_color is None or halo_color.__class__ is style.color
         assert halo_radius is None or type(halo_radius) is int
+        assert opacity is None or type(opacity) is float
+        assert ratio is None or type(ratio) is int
         assert dx is None or type(dx) is int
         assert dy is None or type(dy) is int
         assert character_spacing is None or type(character_spacing) is int
@@ -274,6 +279,8 @@ class TextSymbolizer:
         self.max_char_angle_delta = max_char_angle_delta
         self.halo_color = halo_color
         self.halo_radius = halo_radius
+        self.opacity = opacity
+        self.ratio = ratio
         self.dx = dx
         self.dy = dy
         self.character_spacing = character_spacing
@@ -309,6 +316,8 @@ class TextSymbolizer:
         sym.max_char_angle_delta = self.max_char_angle_delta or sym.max_char_angle_delta
         sym.halo_fill = mapnik.Color(str(self.halo_color)) if self.halo_color else sym.halo_fill
         sym.halo_radius = self.halo_radius or sym.halo_radius
+        sym.opacity = self.opacity or sym.opacity
+        sym.text_ratio = self.ratio or sym.text_ratio
         sym.character_spacing = self.character_spacing or sym.character_spacing
         sym.line_spacing = self.line_spacing or sym.line_spacing
         sym.avoid_edges = self.avoid_edges.value if self.avoid_edges else sym.avoid_edges
diff --git a/cascadenik/style.py b/cascadenik/style.py
index b2d5885..11dc019 100644
--- a/cascadenik/style.py
+++ b/cascadenik/style.py
@@ -182,8 +186,8 @@ properties = {
     # Font size
     'text-size': int,
 
-    # ?
-    'text-ratio': None, # ?
+    # target ratio for text bounding box in pixels
+    'text-ratio': int,
 
     # length before wrapping long names
     'text-wrap-width': int,
@@ -206,6 +210,9 @@ properties = {
     # Color of the fill ie #FFFFFF
     'text-fill': color,
 
+    # 0.0 - 1.0 (default 1.0)
+    'text-opacity': float,
+
     # Color of the halo
     'text-halo-fill': color,
 

Btw.: point opacity (image/icons), shield avoid-edges, and shield placement attributes do not seem to be supported yet, either; but I do not have a tested patch for these yet.

Why not reference.json?

Saw recently that @migurski removed Cascadenik from reference.json as a 'soon to implement' supporter. Is there any reason why this decision was made, and whether it's permanent?

Update Changelog

These two commits are not reflected:

Merge pull request #33 from bwg/scaleopacity …
Merge pull request #34 from bwg/scaledasharray …

cascadenik-compile generated files with size 0 under windows

I downloaded the cascadenik and installed it without problem.

But if I run cascadenik-style.py example.mml > example-compiled.xml

the genereated .xml has size 0

I tried other tools with same results.

BTW, I downloaded some .mss files and I assume cascadenik is the tool I should use to generate a new osm.xml for my mapnik rendering for OSM data.

Thanks.

add FieldNameCasing=* to DataSourceConfig

FieldNameCasing={upper,lower,exact}.
Default: exact.

Suggested location: DataSourcesConfig as an option there.

  1. That way I could point my datasources at a new config file, and it would automatically have this UNIVERSAL FOR ALL LAYERS IN THE CONFIG flag set.
  2. Per layer setting in DataSourcesConfig for this would also be super awesome. See OpenOffice example below.

If I pointed it at a PostGIS based list of layers, I could set it to lower and it would automatically turn all my fieldnames in the MSS file to lowercase in the Mapnik XML output.

Note: filters based on fieldnames, text-names based on fieldnames, etc with eye towards Mapnik 2.1 where more properties are data driven.

If I point it a regular SHP file, I would usually leave this property out, since it defaults to exact matching what the fieldnames are already.

But sometimes I edit a file in OpenOffice and that software has a nasty habit of UPPERCASING all my fieldnames. In those cases, if I'd edited all my files that way, I'd set this to be upper. If only some, then I could set that LAYER as upper.

Use case 1 is more important to me than use case 2.

Tnx!

the Cascadenik install

which min version dose the python need ? i use centos5.5 and python2.4 ,but i get error like:

File "setup.py", line 14, in ?
from cascadenik import version as VERSION
File "/opt/Cascadenik/cascadenik/init.py", line 29
from .parse import stylesheet_declarations
^
SyntaxError: invalid syntax

[root@localhost Cascadenik]# python setup.py install
Traceback (most recent call last):
File "setup.py", line 14, in ?
from cascadenik import version as VERSION
File "/opt/Cascadenik/cascadenik/init.py", line 31, in ?
import parse,stylesheet_declarations
File "/opt/Cascadenik/cascadenik/parse.py", line 4, in ?
from itertools import chain, product
ImportError: cannot import name product
[

cascadenik-style.py is broken in 1.0.0 release

A user reported this to me by email. Traveling right now, but if nobody grabs this I can get to it on monday.

$ ./cascadenik-style.py example.mss
Traceback (most recent call last):
File "./cascadenik-style.py", line 49, in
sys.exit(main(stylefile))
File "./cascadenik-style.py", line 17, in main
declarations = cascadenik.stylesheet_declarations(input,is_gym=True)
TypeError: stylesheet_declarations() got an unexpected keyword argument 'is_gym'

Handling of new mapnik2 expression syntax for names, ...

So far there seems to be no way to use the extended mapnik2 expression syntax for specifying the name for TextSymbolizers. Using the old syntax (specifying the name as second element of the selector) gives warnings:
Deprecation Warning: symbolizer value now an expression, please wrap properly in brackets like "[name]"
But when using brackets, nothing changes (they just seem to be stripped away, as can be seen when using nested brackets); if using quotes, then no TextSymbolizer is written to the xml file at all. Without the possibility to specify brackets (and other operators in the expression; this currently leads to an error in cascadenic-compile.py, depending on what expression is tried), the additional capabilities of mapnik2 are not fully exploitable.

This concerns: branch mapnik2 (with latest commit on Nov 30th 2010)

display:none preprocessor

For situations where there is CSS for a class, but the end result is NULL in terms of drawing anything (like line-opacity: 0; where there is no other symbology applied), the data layer should be turned off and the CSS skipped.

windows test failures in relative-paths branch

Microsoft Windows XP [Version 5.1.2600]
(C) Copyright 1985-2001 Microsoft Corp.

C:\Documents and Settings\xp_user>cd Desktop

C:\Documents and Settings\xp_user\Desktop>cd Cascadenik

C:\Documents and Settings\xp_user\Desktop\Cascadenik>python test.py
..................E..EE
Cascadenik debug: Warning, FontSets will be ignored as they are not yet supporte
d in Mapnik via Python...
.....E................................EEEEFEEE.FE...............................
...........................................................
======================================================================
ERROR: testCompile1 (__main__.CompileXMLTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 1754, in testCompile1
    cfg = tempfile.NamedTemporaryFile('w', delete=False)
TypeError: NamedTemporaryFile() got an unexpected keyword argument 'delete'

======================================================================
ERROR: testCompile4 (__main__.CompileXMLTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2007, in testCompile4
    ms.to_mapnik(mmap, self.dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\output.p
y", line 65, in to_mapnik
    lay.datasource = layer.datasource.to_mapnik()
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\output.p
y", line 134, in to_mapnik
    return mapnik.Datasource(**self.parameters)
  File "C:\Program Files\Mapnik\python\2.5\site-packages\mapnik\__init__.py", li
ne 261, in Datasource
    return CreateDatasource(keywords)
RuntimeError: data/test does not exist

======================================================================
ERROR: testCompile5 (__main__.CompileXMLTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2026, in testCompile5
    ms.to_mapnik(mmap, self.dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\output.p
y", line 65, in to_mapnik
    lay.datasource = layer.datasource.to_mapnik()
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\output.p
y", line 134, in to_mapnik
    return mapnik.Datasource(**self.parameters)
  File "C:\Program Files\Mapnik\python\2.5\site-packages\mapnik\__init__.py", li
ne 261, in Datasource
    return CreateDatasource(keywords)
RuntimeError: data/test does not exist

======================================================================
ERROR: testLocalDefaultsFromFile (__main__.DataSourcesTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 1602, in testLocalDefaultsFromFile
    cfg = tempfile.NamedTemporaryFile('w', delete=False)
TypeError: NamedTemporaryFile() got an unexpected keyword argument 'delete'

======================================================================
ERROR: testAbsolutePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2297, in testAbsolutePaths
    map = compile(mml_path, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1446, in compile
    declarations = extract_declarations(map_el, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 622, in extract_declarations
    rulesets = style.stylesheet_rulesets(styles, is_merc_projection(map_el.get('
srs','')))
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\style.py
", line 862, in stylesheet_rulesets
    declaration['value'] = postprocess_value(declaration['value'], declaration['
property'], line, col)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\style.py
", line 1101, in postprocess_value
    raw = str(tokens[0][1])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xca' in position 37:
 ordinal not in range(128)

======================================================================
ERROR: testDistantPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2261, in testDistantPaths
    map = compile(mml_path, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1533, in compile
    get_point_rules(layer_declarations, dirs)))
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1211, in get_point_rules
    and postprocess_symbolizer_image_file(str(values['point-file'].value), dirs)
 \
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1094, in postprocess_symbolizer_image_file
    img = Image.open(path)
  File "C:\Program Files\Mapnik\python\2.5\site-packages\PIL\Image.py", line 198
0, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

======================================================================
ERROR: testDistantPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2124, in tearDown
    shutil.rmtree(self.tmpdir1)
  File "C:\Python25\lib\shutil.py", line 180, in rmtree
    onerror(os.remove, fullname, sys.exc_info())
  File "C:\Python25\lib\shutil.py", line 178, in rmtree
    os.remove(fullname)
WindowsError: [Error 32] The process cannot access the file because it is being
used by another process: 'c:\\docume~1\\xp_user\\locals~1\\temp\\cascadenik-test
s1-pjlenf\\purple-point.png'

======================================================================
ERROR: testLocalLinkedSheetPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2345, in testLocalLinkedSheetPaths
    map = compile(mml_path, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1490, in compile
    file_param = localize_shapefile(file_param, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1358, in localize_shapefile
    path = unzip_shapefile_into(path, dirs.cache)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1302, in unzip_shapefile_into
    zip_file = zipfile.ZipFile(zip_path)
  File "C:\Python25\lib\zipfile.py", line 339, in __init__
    self.fp = open(file, modeDict[mode])
IOError: [Errno 2] No such file or directory: 'c:\\docume~1\\xp_user\\locals~1\\
temp\\cascadenik-tests2-hoxxwa\\mission-points.zip'

======================================================================
ERROR: testReflexivePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2392, in testReflexivePaths
    map = compile(mml_data, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1446, in compile
    declarations = extract_declarations(map_el, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 622, in extract_declarations
    rulesets = style.stylesheet_rulesets(styles, is_merc_projection(map_el.get('
srs','')))
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\style.py
", line 862, in stylesheet_rulesets
    declaration['value'] = postprocess_value(declaration['value'], declaration['
property'], line, col)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\style.py
", line 1101, in postprocess_value
    raw = str(tokens[0][1])
UnicodeEncodeError: 'ascii' codec can't encode character u'\xca' in position 44:
 ordinal not in range(128)

======================================================================
ERROR: testRelativePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2225, in testRelativePaths
    map = compile(mml_path, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1533, in compile
    get_point_rules(layer_declarations, dirs)))
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1211, in get_point_rules
    and postprocess_symbolizer_image_file(str(values['point-file'].value), dirs)
 \
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1094, in postprocess_symbolizer_image_file
    img = Image.open(path)
  File "C:\Program Files\Mapnik\python\2.5\site-packages\PIL\Image.py", line 198
0, in open
    raise IOError("cannot identify image file")
IOError: cannot identify image file

======================================================================
ERROR: testRelativePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2124, in tearDown
    shutil.rmtree(self.tmpdir1)
  File "C:\Python25\lib\shutil.py", line 180, in rmtree
    onerror(os.remove, fullname, sys.exc_info())
  File "C:\Python25\lib\shutil.py", line 178, in rmtree
    os.remove(fullname)
WindowsError: [Error 32] The process cannot access the file because it is being
used by another process: 'c:\\docume~1\\xp_user\\locals~1\\temp\\cascadenik-test
s1-dzznwl\\purple-point.png'

======================================================================
ERROR: testSplitLinkedSheetPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2361, in testSplitLinkedSheetPaths
    map = compile(mml_path, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1490, in compile
    file_param = localize_shapefile(file_param, dirs)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1358, in localize_shapefile
    path = unzip_shapefile_into(path, dirs.cache)
  File "C:\Documents and Settings\xp_user\Desktop\Cascadenik\cascadenik\compile.
py", line 1302, in unzip_shapefile_into
    zip_file = zipfile.ZipFile(zip_path)
  File "C:\Python25\lib\zipfile.py", line 339, in __init__
    self.fp = open(file, modeDict[mode])
IOError: [Errno 2] No such file or directory: 'c:\\docume~1\\xp_user\\locals~1\\
temp\\cascadenik-tests2-iak37h\\mission-points.zip'

======================================================================
FAIL: testLocalizedPaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2156, in testLocalizedPaths
    assert not os.path.isabs(img_path)
AssertionError

======================================================================
FAIL: testRemotePaths (__main__.RelativePathTests)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "test.py", line 2316, in testRemotePaths
    assert not os.path.isabs(img_path)
AssertionError

----------------------------------------------------------------------
Ran 160 tests in 16.093s

FAILED (failures=2, errors=12)

C:\Documents and Settings\xp_user\Desktop\Cascadenik>

test_combinations needs optimization

Even for mapfiles which include only equality testing of the same variable, test_combinations performs with, it appears, n^2 time, scaling by the number of comparisons of any kind made. Some MML files can thus make pure just-processing and this-loop time in the 5+ minute area.

ERROR: relation "coastline" does not exist

When I try to compile an .mml file:

cascadenik-compile.py style.mml style.xml

I get the following error message:

output file: style.xml /home/sumin/maps/OSM-Solar
Traceback (most recent call last):
  File "/usr/local/bin/cascadenik-compile.py", line 100, in <module>
    sys.exit(main(layersfile, outputfile, **options.__dict__))
  File "/usr/local/bin/cascadenik-compile.py", line 33, in main
    cascadenik.load_map(mmap, src_file, dirname(realpath(dest_file)), **load_kwargs)
  File "/usr/local/lib/python2.7/dist-packages/cascadenik/__init__.py", line 90, in load_map
    compile(src_file, dirs, verbose, datasources_cfg=datasources_cfg, user_styles=user_styles, scale=scale).to_mapnik(map, dirs)
  File "/usr/local/lib/python2.7/dist-packages/cascadenik/output.py", line 86, in to_mapnik
    lay.datasource = layer.datasource.to_mapnik()
  File "/usr/local/lib/python2.7/dist-packages/cascadenik/output.py", line 155, in to_mapnik
    return mapnik.Datasource(**self.parameters)
  File "/usr/lib/pymodules/python2.7/mapnik/__init__.py", line 319, in Datasource
    return CreateDatasource(keywords)
RuntimeError: Postgis Plugin: PSQL error:
ERROR:  relation "coastline" does not exist
LINE 1: SELECT * FROM coastline LIMIT 0
                      ^
Full sql was: 'SELECT * FROM coastline LIMIT 0'

Does anyone have any clue?

Problem with line-dasharray

When I try to compile a style with a line-dasharray with more than two elements, I get the following message:

Traceback (most recent call last):
  File "/usr/local/bin/cascadenik-compile.py", line 92, in 
    sys.exit(main(layersfile, outputfile, **options.__dict__))
  File "/usr/local/bin/cascadenik-compile.py", line 33, in main
    cascadenik.load_map(mmap, src_file, dirname(realpath(dest_file)), **load_kwargs)
  File "/usr/local/lib/python2.6/dist-packages/cascadenik/__init__.py", line 65, in load_map
    compile(src_file, dirs, verbose, datasources_cfg=datasources_cfg).to_mapnik(map, dirs)
  File "/usr/local/lib/python2.6/dist-packages/cascadenik/output.py", line 54, in to_mapnik
    sym = symbolizer.to_mapnik()
  File "/usr/local/lib/python2.6/dist-packages/cascadenik/output.py", line 230, in to_mapnik
    stroke.add_dash(*self.dashes.values)
Boost.Python.ArgumentError: Python argument types in
    Stroke.add_dash(Stroke, int, int, int, int)
did not match C++ signature:
    add_dash(mapnik::stroke {lvalue}, float length, float gap)

The problematic rule looks like this:

.admin[admin_level=6][zoom>=14] {
  line-dasharray: 2,2,4,4;
  line-width: 3;
}

If I change the line-dasharray to

    line-dasharray: 2,2;

the compilation works.

I'm using the newest version (commit d607ac0) from Github.

Please fix!

TextSymbolizer attributes with Mapnik 2.1

Mapnik 2.1 (not yet released) seems to have made changes on TextSymbolizer attributes.
The attributes used by Cascadenik are now under "format" and "placements.defaults".
The folowing path applied on branch mapnik2 seems to fix that:

diff --git a/cascadenik/output.py b/cascadenik/output.py
index a696df9..77a9f2b 100644
--- a/cascadenik/output.py
+++ b/cascadenik/output.py
@@ -232,7 +232,7 @@ class LineSymbolizer:

 class TextSymbolizer:
     def __init__(self, name, face_name, size, color, wrap_width=None, \
-        label_spacing=None, label_position_tolerance=None, max_char_angle_delta=None, \
+        label_spacing=None, label_position_tolerance=None, maximum_angle_char_delta=None, \
         halo_color=None, halo_radius=None, dx=None, dy=None, avoid_edges=None, \
         minimum_distance=None, allow_overlap=None, label_placement=None, \
         character_spacing=None, line_spacing=None, text_transform=None, fontset=None, \
@@ -247,7 +247,7 @@ class TextSymbolizer:
         assert wrap_width is None or type(wrap_width) is int
         assert label_spacing is None or type(label_spacing) is int
         assert label_position_tolerance is None or type(label_position_tolerance) is int
-        assert max_char_angle_delta is None or type(max_char_angle_delta) is int
+        assert maximum_angle_char_delta is None or type(maximum_angle_char_delta) is int
         assert halo_color is None or halo_color.__class__ is style.color
         assert halo_radius is None or type(halo_radius) is int
         assert dx is None or type(dx) is int
@@ -271,7 +271,7 @@ class TextSymbolizer:
         self.wrap_width = wrap_width
         self.label_spacing = label_spacing
         self.label_position_tolerance = label_position_tolerance
-        self.max_char_angle_delta = max_char_angle_delta
+        self.maximum_angle_char_delta = maximum_angle_char_delta
         self.halo_color = halo_color
         self.halo_radius = halo_radius
         self.dx = dx
@@ -312,23 +312,23 @@ class TextSymbolizer:
         sym = mapnik.TextSymbolizer(expr, self.face_name, self.size,
                                     mapnik.Color(str(self.color)))

-        sym.wrap_width = self.wrap_width or sym.wrap_width
-        sym.label_spacing = self.label_spacing or sym.label_spacing
-        sym.label_position_tolerance = self.label_position_tolerance or sym.label_position_tolerance
-        sym.max_char_angle_delta = self.max_char_angle_delta or sym.max_char_angle_delta
-        sym.halo_fill = mapnik.Color(str(self.halo_color)) if self.halo_color else sym.halo_fill
-        sym.halo_radius = self.halo_radius or sym.halo_radius
-        sym.character_spacing = self.character_spacing or sym.character_spacing
-        sym.line_spacing = self.line_spacing or sym.line_spacing
-        sym.avoid_edges = self.avoid_edges.value if self.avoid_edges else sym.avoid_edges
-        sym.force_odd_labels = self.force_odd_labels.value if self.force_odd_labels else sym.force_odd_labels
-        sym.minimum_distance = self.minimum_distance or sym.minimum_distance
-        sym.allow_overlap = self.allow_overlap.value if self.allow_overlap else sym.allow_overlap
+        sym.placements.defaults.wrap_width = self.wrap_width or sym.placements.defaults.wrap_width
+        sym.placements.defaults.label_spacing = self.label_spacing or sym.placements.defaults.label_spacing
+        sym.placements.defaults.label_position_tolerance = self.label_position_tolerance or sym.placements.defaults.label_position_tolerance
+        sym.placements.defaults.maximum_angle_char_delta = self.maximum_angle_char_delta or sym.placements.defaults.maximum_angle_char_delta
+        sym.format.halo_fill = mapnik.Color(str(self.halo_color)) if self.halo_color else sym.format.halo_fill
+        sym.format.halo_radius = self.halo_radius or sym.format.halo_radius
+        sym.format.character_spacing = self.character_spacing or sym.format.character_spacing
+        sym.format.line_spacing = self.line_spacing or sym.format.line_spacing
+        sym.placements.defaults.avoid_edges = self.avoid_edges.value if self.avoid_edges else sym.placements.defaults.avoid_edges
+        sym.placements.defaults.force_odd_labels = self.force_odd_labels.value if self.force_odd_labels else sym.placements.defaults.force_odd_labels
+        sym.placements.defaults.minimum_distance = self.minimum_distance or sym.placements.defaults.minimum_distance
+        sym.placements.defaults.allow_overlap = self.allow_overlap.value if self.allow_overlap else sym.placements.defaults.allow_overlap
         if self.label_placement:
-            sym.label_placement = mapnik.label_placement.names.get(self.label_placement,mapnik.label_placement.POINT_PLACEMENT)
+            sym.placements.defaults.label_placement = mapnik.label_placement.names.get(self.label_placement,mapnik.label_placement.POINT_PLACEMENT)
         # note-renamed in Mapnik2 to 'text_transform'
         if self.text_transform:
-            sym.text_transform = convert_enums.get(self.text_transform,mapnik.text_transform.NONE)
+            sym.format.text_transform = convert_enums.get(self.text_transform,mapnik.text_transform.NONE)
         if self.vertical_alignment:
             # match the logic in load_map.cpp for conditionally applying vertical_alignment default
             default_vertical_alignment = mapnik.vertical_alignment.MIDDLE
@@ -337,10 +337,10 @@ class TextSymbolizer:
             elif self.dy < 0.0:
                 default_vertical_alignment = mapnik.vertical_alignment.TOP

-            sym.vertical_alignment = mapnik.vertical_alignment.names.get(self.vertical_alignment,
+            sym.placements.defaults.vertical_alignment = mapnik.vertical_alignment.names.get(self.vertical_alignment,
                 default_vertical_alignment)
         if self.justify_alignment:
-            sym.justify_alignment = mapnik.justify_alignment.names.get(self.justify_alignment,
+            sym.placements.defaults.justify_alignment = mapnik.justify_alignment.names.get(self.justify_alignment,
               mapnik.justify_alignment.MIDDLE)

         if self.fontset:
@@ -349,9 +349,9 @@ class TextSymbolizer:
             sys.stderr.write('\nCascadenik debug: Warning, FontSets will be ignored as they are not yet supported in Mapnik via Python...\n')

         try:
-            sym.displacement = (self.dx or 0.0, self.dy or 0.0)
+            sym.placements.defaults.displacement = (self.dx or 0.0, self.dy or 0.0)
         except:
-            sym.displacement(self.dx or 0.0, self.dy or 0.0)
+            sym.placements.defaults.displacement(self.dx or 0.0, self.dy or 0.0)

         return sym

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.