named style objects

This commit is contained in:
Dane Springmeyer 2014-08-24 13:38:44 -07:00
parent e9d6872764
commit e2171b2b9c
20 changed files with 237 additions and 153 deletions

View file

@ -53,6 +53,11 @@ void insert_style(mapnik::Map & m, std::string const& name, mapnik::feature_type
m.insert_style(name,style);
}
void insert_style2(mapnik::Map & m, mapnik::feature_type_style const& style)
{
m.insert_style(style.name(),style);
}
void insert_fontset(mapnik::Map & m, std::string const& name, mapnik::font_set const& fontset)
{
m.insert_fontset(name,fontset);
@ -188,6 +193,16 @@ void export_map()
"False # you can only append styles with unique names\n"
)
.def("append_style",insert_style2,
(arg("style_object")),
"Insert a Mapnik Style onto the map by appending it.\n"
"\n"
"Usage:\n"
">>> sty\n"
"<mapnik._mapnik.Style object at 0x6a330>\n"
">>> m.append_style(sty)\n"
)
.def("append_fontset",insert_fontset,
(arg("fontset")),
"Add a FontSet to the map."

View file

@ -75,8 +75,19 @@ void export_style()
class_<rules>("Rules",init<>("default ctor"))
.def(vector_indexing_suite<rules>())
;
class_<feature_type_style>("Style",init<>("default style constructor"))
class_<feature_type_style>("Style",init<std::string const&>(
( arg("name")="" ),
"Create a Style with a name\n"
"\n"
"Usage:\n"
">>> from mapnik import Style\n"
">>> s = Style(\"Roads\")\n"
))
.add_property("name",make_function
(&feature_type_style::name,
return_value_policy<copy_const_reference>()),
&feature_type_style::set_name)
.add_property("rules",make_function
(&feature_type_style::get_rules,
return_value_policy<reference_existing_object>()),

View file

@ -2,7 +2,7 @@
*
* This file is part of Mapnik (c++ mapping toolkit)
*
* Copyright (C) 2013 Artem Pavlenko
* Copyright (C) 2014 Artem Pavlenko
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@ -29,21 +29,28 @@
#include <mapnik/text/text_properties.hpp>
#include <mapnik/datasource_cache.hpp>
#include <mapnik/font_engine_freetype.hpp>
#include <mapnik/agg_renderer.hpp>
#include <mapnik/expression.hpp>
#include <mapnik/color_factory.hpp>
#include <mapnik/image_util.hpp>
#include <mapnik/unicode.hpp>
#include <mapnik/save_map.hpp>
#include <mapnik/agg_renderer.hpp>
#if defined(HAVE_CAIRO)
#include <mapnik/cairo/cairo_renderer.hpp>
#endif
#if defined(SVG_RENDERER)
#include <mapnik/svg/output/svg_renderer.hpp>
#endif
#include <exception>
#include <memory>
#include <iostream>
#include <fstream>
int main ( int argc , char** argv)
int main(int argc, char** argv)
{
using namespace mapnik;
const std::string srs_lcc="+proj=lcc +ellps=GRS80 +lat_0=49 +lon_0=-95 +lat+1=49 +lat_2=77 \
@ -62,7 +69,8 @@ int main ( int argc , char** argv)
// create styles
// Provinces (polygon)
feature_type_style provpoly_style;
{
feature_type_style style("provinces");
{
rule r;
r.set_filter(parse_expression("[NAME_EN] = 'Ontario'"));
@ -71,7 +79,7 @@ int main ( int argc , char** argv)
put(poly_sym, keys::fill, color(250, 190, 183));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
{
rule r;
@ -81,12 +89,14 @@ int main ( int argc , char** argv)
put(poly_sym, keys::fill, color(217, 235, 203));
r.append(std::move(poly_sym));
}
provpoly_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("provinces", std::move(provpoly_style));
// Provinces (polyline)
feature_type_style provlines_style;
{
feature_type_style style("provlines");
{
rule r;
{
@ -100,12 +110,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_dasharray,dash);
r.append(std::move(line_sym));
}
provlines_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("provlines", std::move(provlines_style));
// Drainage
feature_type_style qcdrain_style;
{
feature_type_style style("drainage");
{
rule r;
r.set_filter(parse_expression("[HYC] = 8"));
@ -114,12 +126,14 @@ int main ( int argc , char** argv)
put(poly_sym, keys::fill, color(153, 204, 255));
r.append(std::move(poly_sym));
}
qcdrain_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("drainage", std::move(qcdrain_style));
// Roads 3 and 4 (The "grey" roads)
feature_type_style roads34_style;
{
feature_type_style style("smallroads");
{
rule r;
r.set_filter(parse_expression("[CLASS] = 3 or [CLASS] = 4"));
@ -131,12 +145,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads34_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("smallroads", std::move(roads34_style));
// Roads 2 (The thin yellow ones)
feature_type_style roads2_style_1;
{
feature_type_style style("road-border");
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
@ -148,11 +164,13 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_1.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("road-border", std::move(roads2_style_1));
feature_type_style roads2_style_2;
{
feature_type_style style("road-fill");
{
rule r;
r.set_filter(parse_expression("[CLASS] = 2"));
@ -164,12 +182,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads2_style_2.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("road-fill", std::move(roads2_style_2));
// Roads 1 (The big orange ones, the highways)
feature_type_style roads1_style_1;
{
feature_type_style style("highway-border");
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
@ -181,11 +201,13 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_1.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("highway-border", std::move(roads1_style_1));
feature_type_style roads1_style_2;
{
feature_type_style style("highway-fill");
{
rule r;
r.set_filter(parse_expression("[CLASS] = 1"));
@ -197,12 +219,14 @@ int main ( int argc , char** argv)
put(line_sym,keys::stroke_linejoin,ROUND_JOIN);
r.append(std::move(line_sym));
}
roads1_style_2.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("highway-fill", std::move(roads1_style_2));
// Populated Places
feature_type_style popplaces_style;
{
feature_type_style style("popplaces");
{
rule r;
{
@ -217,10 +241,10 @@ int main ( int argc , char** argv)
put<text_placements_ptr>(text_sym, keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
}
popplaces_style.add_rule(std::move(r));
style.add_rule(std::move(r));
}
m.insert_style(style.name(), style);
}
m.insert_style("popplaces", std::move(popplaces_style));
// layers
// Provincial polygons
@ -229,7 +253,6 @@ int main ( int argc , char** argv)
p["type"]="shape";
p["file"]="demo/data/boundaries";
p["encoding"]="latin1";
layer lyr("Provinces");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.add_style("provinces");
@ -238,17 +261,6 @@ int main ( int argc , char** argv)
}
// Drainage
{
parameters p;
p["type"]="shape";
p["file"]="demo/data/qcdrainage";
layer lyr("Quebec Hydrography");
lyr.set_datasource(datasource_cache::instance().create(p));
lyr.set_srs(srs_lcc);
lyr.add_style("drainage");
m.add_layer(lyr);
}
{
parameters p;
p["type"]="shape";
@ -285,7 +297,6 @@ int main ( int argc , char** argv)
lyr.add_style("road-fill");
lyr.add_style("highway-border");
lyr.add_style("highway-fill");
m.add_layer(lyr);
}
// popplaces
@ -362,6 +373,24 @@ int main ( int argc , char** argv)
"- cairo-demo.svg\n"
"Have a look!\n";
#endif
#if defined(SVG_RENDERER)
std::ofstream output_stream("demo-inkscape.svg",std::ios::out|std::ios::trunc|std::ios::binary);
if (output_stream)
{
using svg_iter_type = std::ostream_iterator<char>;
svg_iter_type output_stream_iterator(output_stream);
mapnik::svg_renderer<svg_iter_type> ren(m,output_stream_iterator);
ren.apply();
output_stream.close();
std::cout << "One SVG has been rendered by native SVG renderer targeting inkscape/illustrator:\n"
"- demo-inkscape.png\n";
}
else
{
std::clog << "could not open for writing 'demo-inkscape.svg'\n";
}
#endif
// save map definition (data + style)
save_map(m, "map.xml");
}

Binary file not shown.

View file

@ -1 +0,0 @@
PROJCS["Atlas of Canada Lambert Conformal Conic",GEOGCS["GCS_North_American_1983",DATUM["D_North_American_1983",SPHEROID["GRS_1980",6378137.0,298.257222101]],PRIMEM["Greenwich",0.0],UNIT["Degree",0.0174532925199433]],PROJECTION["Lambert_Conformal_Conic"],PARAMETER["False_Easting",0.0],PARAMETER["False_Northing",0.0],PARAMETER["Central_Meridian",-95.0],PARAMETER["Standard_Parallel_1",49.0],PARAMETER["Standard_Parallel_2",77.0],PARAMETER["Latitude_Of_Origin",49.0],UNIT["Meter",1.0]]

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -54,6 +54,7 @@ using rules = std::vector<rule>;
class MAPNIK_DECL feature_type_style
{
private:
std::string name_;
rules rules_;
filter_mode_e filter_mode_;
// image_filters
@ -66,10 +67,12 @@ private:
friend void swap(feature_type_style& lhs, feature_type_style & rhs);
public:
// ctor
feature_type_style();
feature_type_style(std::string const& name);
feature_type_style(feature_type_style const& rhs);
feature_type_style(feature_type_style &&) = default;
feature_type_style& operator=(feature_type_style rhs);
std::string const& name() const;
void set_name(std::string const& name);
// comparison
bool operator==(feature_type_style const& rhs) const;

View file

@ -77,8 +77,8 @@ public:
void end_map_processing(Map const& map);
void start_layer_processing(layer const& lay, box2d<double> const& query_extent);
void end_layer_processing(layer const& lay);
void start_style_processing(feature_type_style const& /*st*/) {}
void end_style_processing(feature_type_style const& /*st*/) {}
void start_style_processing(feature_type_style const& st);
void end_style_processing(feature_type_style const& st);
/*!
* @brief Overloads that process each kind of symbolizer individually.

View file

@ -39,8 +39,9 @@ static const char * filter_mode_strings[] = {
IMPLEMENT_ENUM( filter_mode_e, filter_mode_strings )
feature_type_style::feature_type_style()
: rules_(),
feature_type_style::feature_type_style(std::string const& name)
: name_(name),
rules_(),
filter_mode_(FILTER_ALL),
filters_(),
direct_filters_(),
@ -50,7 +51,8 @@ feature_type_style::feature_type_style()
{}
feature_type_style::feature_type_style(feature_type_style const& rhs)
: rules_(rhs.rules_),
: name_(rhs.name_),
rules_(rhs.rules_),
filter_mode_(rhs.filter_mode_),
filters_(rhs.filters_),
direct_filters_(rhs.direct_filters_),
@ -69,6 +71,7 @@ feature_type_style& feature_type_style::operator=(feature_type_style rhs)
void swap( feature_type_style & lhs, feature_type_style & rhs)
{
using std::swap;
std::swap(lhs.name_, rhs.name_);
std::swap(lhs.rules_, rhs.rules_);
std::swap(lhs.filter_mode_, rhs.filter_mode_);
std::swap(lhs.filters_, rhs.filters_);
@ -80,7 +83,8 @@ void swap( feature_type_style & lhs, feature_type_style & rhs)
bool feature_type_style::operator==(feature_type_style const& rhs) const
{
return (rules_ == rhs.rules_) &&
return (name_ == rhs.name_) &&
(rules_ == rhs.rules_) &&
(filter_mode_ == rhs.filter_mode_) &&
(filters_ == rhs.filters_) &&
(direct_filters_ == rhs.direct_filters_) &&
@ -89,6 +93,16 @@ bool feature_type_style::operator==(feature_type_style const& rhs) const
(image_filters_inflate_ == rhs.image_filters_inflate_);
}
std::string const& feature_type_style::name() const
{
return name_;
}
void feature_type_style::set_name(std::string const& name)
{
name_ = name;
}
void feature_type_style::add_rule(rule && rule)
{
rules_.push_back(std::move(rule));

View file

@ -406,7 +406,7 @@ void map_parser::parse_style(Map & map, xml_node const& node)
try
{
name = node.get_attr<std::string>("name");
feature_type_style style;
feature_type_style style(name);
filter_mode_e filter_mode = node.get_attr<filter_mode_e>("filter-mode", FILTER_ALL);
style.set_filter_mode(filter_mode);

View file

@ -395,7 +395,7 @@ void serialize_style( ptree & map_node, std::string const& name, feature_type_st
set_attr(style_node, "name", name);
feature_type_style dfl;
feature_type_style dfl(name);
filter_mode_e filter_mode = style.get_filter_mode();
if (filter_mode != dfl.get_filter_mode() || explicit_defaults)
{

View file

@ -103,6 +103,18 @@ void svg_renderer<T>::end_layer_processing(layer const& lay)
MAPNIK_LOG_DEBUG(svg_renderer) << "svg_renderer: End layer processing=" << lay.name();
}
template <typename T>
void svg_renderer<T>::start_style_processing(feature_type_style const& st)
{
generator_.generate_opening_group(st.name());
}
template <typename T>
void svg_renderer<T>::end_style_processing(feature_type_style const&)
{
generator_.generate_closing_group();
}
template class svg_renderer<std::ostream_iterator<char> >;
}

View file

@ -57,9 +57,9 @@ int main(int argc, char** argv)
mapnik::rule r;
r.set_filter(mapnik::parse_expression("[foo]='bar'"));
r.append(std::move(mapnik::markers_symbolizer()));
mapnik::feature_type_style style;
mapnik::feature_type_style style("style");
style.add_rule(std::move(r));
map.insert_style("style",style);
map.insert_style(style.name(),std::move(style));
std::string csv_plugin("./plugins/input/csv.input");
if (mapnik::util::exists(csv_plugin)) {

View file

@ -66,7 +66,7 @@ int main(int argc, char** argv)
lyr.set_datasource(ds);
lyr.add_style("style");
m.add_layer(lyr);
mapnik::feature_type_style the_style;
mapnik::feature_type_style style("style");
mapnik::rule r;
mapnik::text_symbolizer text_sym;
mapnik::text_placements_ptr placement_finder = std::make_shared<mapnik::text_placements_dummy>();
@ -77,8 +77,8 @@ int main(int argc, char** argv)
placement_finder->defaults.set_old_style_expression(mapnik::parse_expression("[name]"));
mapnik::put<mapnik::text_placements_ptr>(text_sym, mapnik::keys::text_placements_, placement_finder);
r.append(std::move(text_sym));
the_style.add_rule(std::move(r));
m.insert_style("style",the_style );
style.add_rule(std::move(r));
m.insert_style(style.name(),style);
m.zoom_to_box(mapnik::box2d<double>(-256,-256,
256,256));
mapnik::image_32 buf(m.width(),m.height());

View file

@ -14,7 +14,7 @@ def test_that_coordinates_do_not_overflow_and_polygon_is_rendered():
ds = mapnik.MemoryDatasource()
context = mapnik.Context()
ds.add_feature(mapnik.Feature.from_geojson(json.dumps(geojson),context))
s = mapnik.Style()
s = mapnik.Style('style')
r = mapnik.Rule()
sym = mapnik.PolygonSymbolizer()
sym.fill = expected_color
@ -23,10 +23,10 @@ def test_that_coordinates_do_not_overflow_and_polygon_is_rendered():
s.rules.append(r)
lyr = mapnik.Layer('Layer')
lyr.datasource = ds
lyr.styles.append('style')
lyr.styles.append(s.name)
m = mapnik.Map(256,256)
m.background_color = mapnik.Color('black')
m.append_style('style',s)
m.append_style(s)
m.layers.append(lyr)
# 17/20864/45265.png
m.zoom_to_box(mapnik.Box2d(-13658379.710221574,6197514.253362091,-13657768.213995293,6198125.749588372))

View file

@ -30,17 +30,17 @@ def make_map():
f['Name'] = str(pixel_key)
f.add_geometries_from_wkt('POLYGON ((0 0, 0 256, 256 256, 256 0, 0 0))')
ds.add_feature(f)
s = mapnik.Style()
s = mapnik.Style('places_labels')
r = mapnik.Rule()
symb = mapnik.PolygonSymbolizer()
r.symbols.append(symb)
s.rules.append(r)
lyr = mapnik.Layer('Places')
lyr.datasource = ds
lyr.styles.append('places_labels')
lyr.styles.append(s.name)
width,height = 256,256
m = mapnik.Map(width,height)
m.append_style('places_labels',s)
m.append_style(s)
m.layers.append(lyr)
m.zoom_all()
return m

View file

@ -133,7 +133,7 @@ def test_render_points():
ds.add_feature(f)
# create layer/rule/style
s = mapnik.Style()
s = mapnik.Style('places_labels')
r = mapnik.Rule()
symb = mapnik.PointSymbolizer()
symb.allow_overlap = True
@ -141,7 +141,7 @@ def test_render_points():
s.rules.append(r)
lyr = mapnik.Layer('Places','+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs')
lyr.datasource = ds
lyr.styles.append('places_labels')
lyr.styles.append(s.name)
# latlon bounding box corners
ul_lonlat = mapnik.Coord(142.30,-38.20)
lr_lonlat = mapnik.Coord(143.40,-38.80)
@ -154,7 +154,7 @@ def test_render_points():
}
for projdescr in projs.iterkeys():
m = mapnik.Map(1000, 500, projs[projdescr])
m.append_style('places_labels',s)
m.append_style(s)
m.layers.append(lyr)
dest_proj = mapnik.Projection(projs[projdescr])
src_proj = mapnik.Projection('+init=epsg:4326')
@ -179,17 +179,17 @@ def test_render_with_detector():
context = mapnik.Context()
geojson = '{ "type": "Feature", "geometry": { "type": "Point", "coordinates": [ 0, 0 ] } }'
ds.add_feature(mapnik.Feature.from_geojson(geojson,context))
s = mapnik.Style()
s = mapnik.Style('point')
r = mapnik.Rule()
lyr = mapnik.Layer('point')
lyr.datasource = ds
lyr.styles.append('point')
lyr.styles.append(s.name)
symb = mapnik.MarkersSymbolizer()
symb.allow_overlap = False
r.symbols.append(symb)
s.rules.append(r)
m = mapnik.Map(256,256)
m.append_style('point',s)
m.append_style(s)
m.layers.append(lyr)
m.zoom_to_box(mapnik.Box2d(-180,-85,180,85))
im = mapnik.Image(256, 256)

View file

@ -7,7 +7,8 @@ from utilities import execution_path, run_all
import mapnik
def test_style_init():
s = mapnik.Style()
s = mapnik.Style("style")
eq_(s.name,"style")
eq_(s.filter_mode,mapnik.filter_mode.ALL)
eq_(len(s.rules),0)
eq_(s.opacity,1)