initial skeleton of glyph_symbolizer (coarsely ported from arrow_symbolizer). Mapnik compiles but symbolizer does nothing useful yet and is going to be heavily modified to make use of expressions to be general enough to be usable for purposes other than rendering arrows representing vector direction/intensity
This commit is contained in:
parent
53876d14a0
commit
fc3a1beeef
19 changed files with 493 additions and 5 deletions
75
bindings/python/mapnik_glyph_symbolizer.cpp
Normal file
75
bindings/python/mapnik_glyph_symbolizer.cpp
Normal file
|
@ -0,0 +1,75 @@
|
|||
#include <boost/python.hpp>
|
||||
#include <boost/tuple/tuple.hpp>
|
||||
#include <mapnik/glyph_symbolizer.hpp>
|
||||
|
||||
using mapnik::glyph_symbolizer;
|
||||
using mapnik::position;
|
||||
using namespace boost::python;
|
||||
|
||||
list get_displacement_list(const glyph_symbolizer& t)
|
||||
{
|
||||
position pos = t.get_displacement();
|
||||
double dx = boost::get<0>(pos);
|
||||
double dy = boost::get<1>(pos);
|
||||
boost::python::list disp;
|
||||
disp.append(dx);
|
||||
disp.append(dy);
|
||||
return disp;
|
||||
}
|
||||
|
||||
void export_glyph_symbolizer()
|
||||
{
|
||||
class_<glyph_symbolizer>("GlyphSymbolizer",
|
||||
init<std::string const&,std::string const&>())
|
||||
.add_property("face_name",
|
||||
make_function(&glyph_symbolizer::get_face_name,return_value_policy<copy_const_reference>()),
|
||||
&glyph_symbolizer::set_face_name)
|
||||
.add_property("char",
|
||||
make_function(&glyph_symbolizer::get_char,return_value_policy<copy_const_reference>()),
|
||||
&glyph_symbolizer::set_char)
|
||||
.add_property("angle_offset",
|
||||
&glyph_symbolizer::get_angle_offset,
|
||||
&glyph_symbolizer::set_angle_offset)
|
||||
.add_property("allow_overlap",
|
||||
&glyph_symbolizer::get_allow_overlap,
|
||||
&glyph_symbolizer::set_allow_overlap)
|
||||
.add_property("avoid_edges",
|
||||
&glyph_symbolizer::get_avoid_edges,
|
||||
&glyph_symbolizer::set_avoid_edges)
|
||||
.def("get_displacement", get_displacement_list)
|
||||
.def("set_displacement", &glyph_symbolizer::set_displacement)
|
||||
.add_property("halo_fill",
|
||||
make_function(&glyph_symbolizer::get_halo_fill,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&glyph_symbolizer::set_halo_fill)
|
||||
.add_property("halo_radius",
|
||||
&glyph_symbolizer::get_halo_radius,
|
||||
&glyph_symbolizer::set_halo_radius)
|
||||
.add_property("value_attr", make_function(
|
||||
&glyph_symbolizer::get_value_attr,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&glyph_symbolizer::set_value_attr)
|
||||
.add_property("azimuth_attr", make_function(
|
||||
&glyph_symbolizer::get_azimuth_attr,
|
||||
return_value_policy<copy_const_reference>()),
|
||||
&glyph_symbolizer::set_azimuth_attr)
|
||||
.add_property("colorizer",
|
||||
&glyph_symbolizer::get_colorizer,
|
||||
&glyph_symbolizer::set_colorizer,
|
||||
"Get/Set the RasterColorizer used to color the arrows.\n"
|
||||
"\n"
|
||||
"Usage:\n"
|
||||
"\n"
|
||||
">>> from mapnik import GlyphSymbolizer, RasterColorizer\n"
|
||||
">>> sym = GlyphSymbolizer()\n"
|
||||
">>> sym.colorizer = RasterColorizer()\n"
|
||||
">>> for value, color in [\n"
|
||||
"... (0, \"#000000\"),\n"
|
||||
"... (10, \"#ff0000\"),\n"
|
||||
"... (40, \"#00ff00\"),\n"
|
||||
"... ]:\n"
|
||||
"... sym.colorizer.append_band(value, color)\n"
|
||||
)
|
||||
;
|
||||
;
|
||||
}
|
|
@ -60,6 +60,7 @@ void export_projection();
|
|||
void export_proj_transform();
|
||||
void export_view_transform();
|
||||
void export_raster_colorizer();
|
||||
void export_glyph_symbolizer();
|
||||
|
||||
#include <mapnik/version.hpp>
|
||||
#include <mapnik/map.hpp>
|
||||
|
@ -333,6 +334,7 @@ BOOST_PYTHON_MODULE(_mapnik2)
|
|||
export_coord();
|
||||
export_map();
|
||||
export_raster_colorizer();
|
||||
export_glyph_symbolizer();
|
||||
|
||||
def("render_to_file",&render_to_file1,
|
||||
"\n"
|
||||
|
|
|
@ -44,6 +44,7 @@ using mapnik::shield_symbolizer;
|
|||
using mapnik::text_symbolizer;
|
||||
using mapnik::building_symbolizer;
|
||||
using mapnik::markers_symbolizer;
|
||||
using mapnik::glyph_symbolizer;
|
||||
using mapnik::symbolizer;
|
||||
using mapnik::to_expression_string;
|
||||
|
||||
|
@ -161,6 +162,7 @@ void export_rule()
|
|||
implicitly_convertible<raster_symbolizer,symbolizer>();
|
||||
implicitly_convertible<shield_symbolizer,symbolizer>();
|
||||
implicitly_convertible<text_symbolizer,symbolizer>();
|
||||
implicitly_convertible<glyph_symbolizer,symbolizer>();
|
||||
|
||||
class_<rule_type::symbolizers>("Symbolizers",init<>("TODO"))
|
||||
.def(vector_indexing_suite<rule_type::symbolizers>())
|
||||
|
|
|
@ -39,6 +39,7 @@ using mapnik::shield_symbolizer;
|
|||
using mapnik::text_symbolizer;
|
||||
using mapnik::building_symbolizer;
|
||||
using mapnik::markers_symbolizer;
|
||||
using mapnik::glyph_symbolizer;
|
||||
|
||||
struct get_symbolizer_type : public boost::static_visitor<std::string>
|
||||
{
|
||||
|
@ -95,6 +96,11 @@ struct get_symbolizer_type : public boost::static_visitor<std::string>
|
|||
return "markers";
|
||||
}
|
||||
|
||||
std::string operator () ( const glyph_symbolizer & sym )
|
||||
{
|
||||
return "glyph";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
std::string get_symbol_type(const symbolizer& symbol)
|
||||
|
|
|
@ -83,6 +83,9 @@ namespace mapnik {
|
|||
void process(markers_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
private:
|
||||
T & pixmap_;
|
||||
unsigned width_;
|
||||
|
|
|
@ -104,6 +104,9 @@ namespace mapnik {
|
|||
void process(markers_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
void process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans);
|
||||
protected:
|
||||
Map const& m_;
|
||||
Cairo::RefPtr<Cairo::Context> context_;
|
||||
|
|
203
include/mapnik/glyph_symbolizer.hpp
Normal file
203
include/mapnik/glyph_symbolizer.hpp
Normal file
|
@ -0,0 +1,203 @@
|
|||
#ifndef ARROW_SYMBOLIZER_HPP
|
||||
#define ARROW_SYMBOLIZER_HPP
|
||||
|
||||
#include <mapnik/raster_colorizer.hpp>
|
||||
#include <mapnik/text_symbolizer.hpp>
|
||||
#include <mapnik/text_path.hpp>
|
||||
#include <mapnik/unicode.hpp>
|
||||
#include <mapnik/config_error.hpp>
|
||||
#include <mapnik/font_engine_freetype.hpp>
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
struct MAPNIK_DECL glyph_symbolizer
|
||||
{
|
||||
glyph_symbolizer(std::string const& face_name, std::string const& c)
|
||||
: face_name_(face_name),
|
||||
char_(c),
|
||||
angle_offset_(0.0),
|
||||
min_size_(10),
|
||||
max_size_(100),
|
||||
min_value_(0),
|
||||
max_value_(1),
|
||||
colorizer_(),
|
||||
allow_overlap_(false),
|
||||
avoid_edges_(false),
|
||||
displacement_(0.0, 0.0),
|
||||
halo_fill_(color(255,255,255)),
|
||||
halo_radius_(0),
|
||||
azimuth_attr_("azimuth"),
|
||||
value_attr_("value")
|
||||
{
|
||||
if (get_min_size() > get_max_size())
|
||||
throw config_error("Invalid size range");
|
||||
}
|
||||
|
||||
std::string const& get_face_name() const
|
||||
{
|
||||
return face_name_;
|
||||
}
|
||||
|
||||
void set_face_name(std::string face_name)
|
||||
{
|
||||
face_name_ = face_name;
|
||||
}
|
||||
|
||||
std::string const& get_char() const
|
||||
{
|
||||
return char_;
|
||||
}
|
||||
|
||||
void set_char(std::string c)
|
||||
{
|
||||
char_ = c;
|
||||
}
|
||||
|
||||
double get_angle_offset() const
|
||||
{
|
||||
return angle_offset_;
|
||||
}
|
||||
void set_angle_offset(double angle)
|
||||
{
|
||||
angle_offset_ = angle;
|
||||
}
|
||||
|
||||
float get_min_value() const
|
||||
{
|
||||
return min_value_;
|
||||
}
|
||||
void set_min_value(float min_value)
|
||||
{
|
||||
min_value_ = min_value;
|
||||
}
|
||||
|
||||
float get_max_value() const
|
||||
{
|
||||
return max_value_;
|
||||
}
|
||||
void set_max_value(float max_value)
|
||||
{
|
||||
max_value_ = max_value;
|
||||
}
|
||||
|
||||
unsigned get_min_size() const
|
||||
{
|
||||
return min_size_;
|
||||
}
|
||||
void set_min_size(unsigned min_size)
|
||||
{
|
||||
min_size_ = min_size;
|
||||
}
|
||||
|
||||
unsigned get_max_size() const
|
||||
{
|
||||
return max_size_;
|
||||
}
|
||||
void set_max_size(unsigned max_size)
|
||||
{
|
||||
max_size_ = max_size;
|
||||
}
|
||||
|
||||
bool get_allow_overlap() const
|
||||
{
|
||||
return allow_overlap_;
|
||||
}
|
||||
void set_allow_overlap(bool allow_overlap)
|
||||
{
|
||||
allow_overlap_ = allow_overlap;
|
||||
}
|
||||
bool get_avoid_edges() const
|
||||
{
|
||||
return avoid_edges_;
|
||||
}
|
||||
void set_avoid_edges(bool avoid_edges)
|
||||
{
|
||||
avoid_edges_ = avoid_edges;
|
||||
}
|
||||
void set_displacement(double x, double y)
|
||||
{
|
||||
displacement_ = boost::make_tuple(x,y);
|
||||
}
|
||||
position const& get_displacement() const
|
||||
{
|
||||
return displacement_;
|
||||
}
|
||||
void set_halo_fill(color const& fill)
|
||||
{
|
||||
halo_fill_ = fill;
|
||||
}
|
||||
color const& get_halo_fill() const
|
||||
{
|
||||
return halo_fill_;
|
||||
}
|
||||
void set_halo_radius(unsigned radius)
|
||||
{
|
||||
halo_radius_ = radius;
|
||||
}
|
||||
|
||||
unsigned get_halo_radius() const
|
||||
{
|
||||
return halo_radius_;
|
||||
}
|
||||
|
||||
std::string const& get_azimuth_attr() const
|
||||
{
|
||||
return azimuth_attr_;
|
||||
}
|
||||
|
||||
void set_azimuth_attr(std::string azimuth_attr)
|
||||
{
|
||||
azimuth_attr_ = azimuth_attr;
|
||||
}
|
||||
|
||||
std::string const& get_value_attr() const
|
||||
{
|
||||
return value_attr_;
|
||||
}
|
||||
|
||||
raster_colorizer_ptr get_colorizer() const
|
||||
{
|
||||
return colorizer_;
|
||||
}
|
||||
void set_colorizer(raster_colorizer_ptr const& colorizer)
|
||||
{
|
||||
colorizer_ = colorizer;
|
||||
}
|
||||
|
||||
void set_value_attr(std::string value_attr)
|
||||
{
|
||||
value_attr_ = value_attr;
|
||||
}
|
||||
|
||||
/*
|
||||
* helpers
|
||||
*/
|
||||
|
||||
text_path_ptr get_text_path(face_set_ptr const& faces,
|
||||
Feature const& feature) const;
|
||||
unsigned int get_size(double value) const;
|
||||
double get_angle(Feature const& feature) const;
|
||||
double get_value(Feature const& feature) const;
|
||||
|
||||
|
||||
|
||||
private:
|
||||
std::string face_name_;
|
||||
std::string char_;
|
||||
double angle_offset_;
|
||||
unsigned min_size_;
|
||||
unsigned max_size_;
|
||||
float min_value_;
|
||||
float max_value_;
|
||||
raster_colorizer_ptr colorizer_;
|
||||
bool allow_overlap_;
|
||||
bool avoid_edges_;
|
||||
position displacement_;
|
||||
color halo_fill_;
|
||||
unsigned halo_radius_;
|
||||
std::string azimuth_attr_;
|
||||
std::string value_attr_;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
|
@ -32,6 +32,7 @@
|
|||
#include <mapnik/shield_symbolizer.hpp>
|
||||
#include <mapnik/text_symbolizer.hpp>
|
||||
#include <mapnik/markers_symbolizer.hpp>
|
||||
#include <mapnik/glyph_symbolizer.hpp>
|
||||
#include <mapnik/feature.hpp>
|
||||
#include <mapnik/expression_grammar.hpp>
|
||||
|
||||
|
@ -101,6 +102,12 @@ namespace mapnik
|
|||
{
|
||||
return (&lhs == &rhs);
|
||||
}
|
||||
|
||||
inline bool operator==(glyph_symbolizer const& lhs,
|
||||
glyph_symbolizer const& rhs)
|
||||
{
|
||||
return (&lhs == &rhs);
|
||||
}
|
||||
typedef boost::variant<point_symbolizer,
|
||||
line_symbolizer,
|
||||
line_pattern_symbolizer,
|
||||
|
@ -110,7 +117,8 @@ namespace mapnik
|
|||
shield_symbolizer,
|
||||
text_symbolizer,
|
||||
building_symbolizer,
|
||||
markers_symbolizer> symbolizer;
|
||||
markers_symbolizer,
|
||||
glyph_symbolizer> symbolizer;
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#define __TEXT_PATH_H__
|
||||
|
||||
#include <boost/utility.hpp>
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <unicode/unistr.h>
|
||||
|
||||
namespace mapnik
|
||||
|
@ -164,6 +165,8 @@ namespace mapnik
|
|||
nodes_.clear();
|
||||
}
|
||||
};
|
||||
|
||||
typedef boost::shared_ptr<text_path> text_path_ptr;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -624,6 +624,37 @@ struct to_expression_string : public boost::static_visitor<std::string>
|
|||
return ss.str();
|
||||
}
|
||||
};
|
||||
|
||||
struct to_double : public boost::static_visitor<double>
|
||||
{
|
||||
double operator() (double val) const
|
||||
{
|
||||
return val;
|
||||
}
|
||||
|
||||
double operator() (std::string const& val) const
|
||||
{
|
||||
std::istringstream stream(val);
|
||||
double t;
|
||||
stream >> t;
|
||||
return t;
|
||||
}
|
||||
double operator() (UnicodeString const& val) const
|
||||
{
|
||||
std::string utf8;
|
||||
to_utf8(val,utf8);
|
||||
std::istringstream stream(utf8);
|
||||
double t;
|
||||
stream >> t;
|
||||
return t;
|
||||
}
|
||||
|
||||
double operator() (value_null const& val) const
|
||||
{
|
||||
boost::ignore_unused_variable_warning(val);
|
||||
return 0.0;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
class value
|
||||
|
@ -696,6 +727,12 @@ public:
|
|||
{
|
||||
return boost::apply_visitor(impl::to_unicode(),base_);
|
||||
}
|
||||
|
||||
double to_double() const
|
||||
{
|
||||
return boost::apply_visitor(impl::to_double(),base_);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
inline const value operator+(value const& p1,value const& p2)
|
||||
|
|
|
@ -109,6 +109,7 @@ source = Split(
|
|||
symbolizer.cpp
|
||||
arrow.cpp
|
||||
unicode.cpp
|
||||
glyph_symbolizer.cpp
|
||||
"""
|
||||
)
|
||||
|
||||
|
|
|
@ -945,5 +945,13 @@ void agg_renderer<T>::process(text_symbolizer const& sym,
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
void agg_renderer<T>::process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
}
|
||||
|
||||
template class agg_renderer<image_32>;
|
||||
}
|
||||
|
|
|
@ -1041,6 +1041,12 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
|||
{
|
||||
}
|
||||
|
||||
void cairo_renderer_base::process(glyph_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
{
|
||||
}
|
||||
|
||||
void cairo_renderer_base::process(text_symbolizer const& sym,
|
||||
Feature const& feature,
|
||||
proj_transform const& prj_trans)
|
||||
|
|
69
src/glyph_symbolizer.cpp
Normal file
69
src/glyph_symbolizer.cpp
Normal file
|
@ -0,0 +1,69 @@
|
|||
#include <mapnik/glyph_symbolizer.hpp>
|
||||
#include <mapnik/value.hpp>
|
||||
|
||||
#include <boost/lexical_cast.hpp>
|
||||
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
text_path_ptr glyph_symbolizer::get_text_path(face_set_ptr const& faces,
|
||||
Feature const& feature) const
|
||||
{
|
||||
// Calculate face rotation angle and box offset adjustments
|
||||
typedef std::pair<unsigned,unsigned> dimension_t;
|
||||
|
||||
// Get string_info with arrow glyph
|
||||
string_info info(UnicodeString(get_char().c_str()));
|
||||
faces->get_string_info(info);
|
||||
if (info.num_characters() != 1)
|
||||
{
|
||||
throw config_error("'char' length must be exactly 1");
|
||||
}
|
||||
|
||||
character_info ci = info.at(0);
|
||||
dimension_t cdim = faces->character_dimensions(ci.character);
|
||||
double cwidth = (static_cast<double>(cdim.first))/2.0;
|
||||
double cheight = (static_cast<double>(cdim.second))/2.0;
|
||||
double angle = get_angle(feature);
|
||||
double xoff = cwidth*cos(angle) - cheight*sin(angle);
|
||||
double yoff = cwidth*sin(angle) + cheight*cos(angle);
|
||||
|
||||
text_path_ptr path_ptr = text_path_ptr(new text_path());
|
||||
path_ptr->add_node(ci.character, -xoff, -yoff, angle);
|
||||
return path_ptr;
|
||||
}
|
||||
|
||||
unsigned int glyph_symbolizer::get_size(double value) const
|
||||
{
|
||||
double scale = (get_max_size()-get_min_size()) /
|
||||
(get_max_value()-get_min_value());
|
||||
double size = get_min_size() + (value - get_min_value())*scale;
|
||||
if (size > get_max_size())
|
||||
{
|
||||
// size too large, clip it
|
||||
size = get_max_size();
|
||||
}
|
||||
return static_cast<unsigned>(floor(size));
|
||||
}
|
||||
|
||||
double glyph_symbolizer::get_angle(Feature const& feature) const
|
||||
{
|
||||
// Returns the angle of rotation of the glyph in radians
|
||||
std::string key = get_azimuth_attr();
|
||||
double azimuth = feature[key].to_double();
|
||||
azimuth = std::fmod(azimuth, 360.0);
|
||||
if (azimuth<0) azimuth += 360.0;
|
||||
azimuth *= (M_PI/180.0);
|
||||
double angle = atan2(cos(azimuth), sin(azimuth));
|
||||
angle += get_angle_offset() * (M_PI/180.0);
|
||||
angle = std::fmod(angle, 2*M_PI);
|
||||
if (angle<0) angle += 2*M_PI;
|
||||
return angle;
|
||||
}
|
||||
|
||||
double glyph_symbolizer::get_value(Feature const& feature) const
|
||||
{
|
||||
std::string key = get_value_attr();
|
||||
return feature[key].to_double();
|
||||
}
|
||||
}
|
|
@ -256,6 +256,11 @@ namespace mapnik
|
|||
{
|
||||
// FIXME!!!!!
|
||||
}
|
||||
|
||||
void operator () ( glyph_symbolizer const& )
|
||||
{
|
||||
// FIXME!!!!!
|
||||
}
|
||||
private:
|
||||
serialize_symbolizer();
|
||||
void add_image_attributes(ptree & node, const symbolizer_with_image & sym)
|
||||
|
|
BIN
tests/data/shp/arrows.dbf
Normal file
BIN
tests/data/shp/arrows.dbf
Normal file
Binary file not shown.
BIN
tests/data/shp/arrows.shp
Normal file
BIN
tests/data/shp/arrows.shp
Normal file
Binary file not shown.
BIN
tests/data/shp/arrows.shx
Normal file
BIN
tests/data/shp/arrows.shx
Normal file
Binary file not shown.
57
tests/python_tests/glyph_symbolizer_test.py
Normal file
57
tests/python_tests/glyph_symbolizer_test.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
from nose.tools import *
|
||||
from utilities import execution_path, save_data
|
||||
|
||||
import os, mapnik2
|
||||
|
||||
def setup():
|
||||
# All of the paths used are relative, if we run the tests
|
||||
# from another directory we need to chdir()
|
||||
os.chdir(execution_path('.'))
|
||||
|
||||
|
||||
def test_arrows_symbolizer():
|
||||
srs = '+init=epsg:32630'
|
||||
lyr = mapnik2.Layer('arrows')
|
||||
lyr.datasource = mapnik2.Shapefile(
|
||||
file = '../data/shp/arrows.shp',
|
||||
)
|
||||
lyr.srs = srs
|
||||
_map = mapnik2.Map(256,256, srs)
|
||||
style = mapnik2.Style()
|
||||
rule = mapnik2.Rule()
|
||||
rule.filter = mapnik2.Expression("[value] > 0 and [azimuth]>-1") #XXX Need to mention an attribute in the expression
|
||||
sym = mapnik2.GlyphSymbolizer("DejaVu Sans Condensed", "A")
|
||||
sym.angle_offset = -90
|
||||
sym.min_value = 1
|
||||
sym.max_value = 100
|
||||
sym.min_size = 1
|
||||
sym.max_size = 100
|
||||
sym.allow_overlap = True
|
||||
# Assigning a colorizer to the RasterSymbolizer tells the later
|
||||
# that it should use it to colorize the raw data raster
|
||||
sym.colorizer = mapnik2.RasterColorizer()
|
||||
for value, color in [
|
||||
( 0, "#0044cc"),
|
||||
( 10, "#00cc00"),
|
||||
( 20, "#ffff00"),
|
||||
( 30, "#ff7f00"),
|
||||
( 40, "#ff0000"),
|
||||
]:
|
||||
sym.colorizer.append_band(value, mapnik2.Color(color))
|
||||
rule.symbols.append(sym)
|
||||
style.rules.append(rule)
|
||||
_map.append_style('foo', style)
|
||||
lyr.styles.append('foo')
|
||||
_map.layers.append(lyr)
|
||||
_map.zoom_to_box(mapnik2.Box2d(0,0,8,8))
|
||||
|
||||
im = mapnik2.Image(_map.width,_map.height)
|
||||
mapnik2.render(_map, im)
|
||||
save_data('test_arrows_symbolizer.png', im.tostring('png'))
|
||||
imdata = im.tostring()
|
||||
assert len(imdata) > 0
|
||||
# we have features with 20 as a value so check that they're colored
|
||||
assert '\xff\xff\xff\x00' in imdata
|
||||
|
Loading…
Reference in a new issue