Skip to content

Commit 569a539

Browse files
author
Dane Springmeyer
committed
new dot symbolizer for fast rendering of points - refs mapnik#1651 mapbox/mapnik-vector-tile#62 mapnik#2612
1 parent 1dfdfb3 commit 569a539

15 files changed

+237
-1
lines changed

CHANGELOG.md

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ For a complete change history, see the git log.
88

99
## 3.0.0
1010

11+
- Added new and experimental `dot` symbolizer for fast rendering of points
1112
- Improved support for International Text (now uses harfbuzz library for text shaping)
1213
- Uses latest c++11 features for better performance (especially map loading)
1314
- Expressions everywhere: all symbolizer properties can now be data driven expressions (with the exception of `face-name` and `fontset-name` on the `TextSymbolizer`).

deps/agg/include/agg_ellipse.h

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ namespace agg
4848
void approximation_scale(double scale);
4949
void rewind(unsigned path_id);
5050
unsigned vertex(double* x, double* y);
51+
unsigned num_steps() { return m_num; }
5152

5253
private:
5354
void calc_num_steps();

include/mapnik/agg_renderer.hpp

+3
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,9 @@ class MAPNIK_DECL agg_renderer : public feature_style_processor<agg_renderer<T0>
122122
void process(debug_symbolizer const& sym,
123123
feature_impl & feature,
124124
proj_transform const& prj_trans);
125+
void process(dot_symbolizer const& sym,
126+
mapnik::feature_impl & feature,
127+
proj_transform const& prj_trans);
125128

126129
inline bool process(rule::symbolizers const&,
127130
mapnik::feature_impl&,

include/mapnik/symbolizer_base.hpp

+3-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ struct MAPNIK_DECL raster_symbolizer : public symbolizer_base {};
149149
struct MAPNIK_DECL building_symbolizer : public symbolizer_base {};
150150
struct MAPNIK_DECL group_symbolizer : public symbolizer_base {};
151151
struct MAPNIK_DECL debug_symbolizer : public symbolizer_base {};
152+
struct MAPNIK_DECL dot_symbolizer : public symbolizer_base {};
152153

153154
// symbolizer
154155
using symbolizer = util::variant<point_symbolizer,
@@ -162,7 +163,8 @@ using symbolizer = util::variant<point_symbolizer,
162163
building_symbolizer,
163164
markers_symbolizer,
164165
group_symbolizer,
165-
debug_symbolizer>;
166+
debug_symbolizer,
167+
dot_symbolizer>;
166168

167169
}
168170

include/mapnik/symbolizer_utils.hpp

+6
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,12 @@ struct symbolizer_traits<debug_symbolizer>
120120
static char const* name() { return "DebugSymbolizer";}
121121
};
122122

123+
template<>
124+
struct symbolizer_traits<dot_symbolizer>
125+
{
126+
static char const* name() { return "DotSymbolizer";}
127+
};
128+
123129
// symbolizer name impl
124130
namespace detail {
125131

src/agg/process_dot_symbolizer.cpp

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
/*****************************************************************************
2+
*
3+
* This file is part of Mapnik (c++ mapping toolkit)
4+
*
5+
* Copyright (C) 2014 Artem Pavlenko
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
*****************************************************************************/
22+
23+
// mapnik
24+
#include <mapnik/feature.hpp>
25+
#include <mapnik/agg_renderer.hpp>
26+
#include <mapnik/agg_rasterizer.hpp>
27+
#include <mapnik/symbolizer.hpp>
28+
#include <mapnik/symbolizer_keys.hpp>
29+
#include <mapnik/graphics.hpp>
30+
#include <mapnik/vertex.hpp>
31+
#include <mapnik/renderer_common.hpp>
32+
#include <mapnik/proj_transform.hpp>
33+
#include <mapnik/image_compositing.hpp>
34+
35+
// agg
36+
#include "agg_ellipse.h"
37+
#include "agg_rendering_buffer.h"
38+
#include "agg_pixfmt_rgba.h"
39+
#include "agg_scanline_u.h"
40+
#include "agg_renderer_scanline.h"
41+
#include "agg_color_rgba.h"
42+
#include "agg_renderer_base.h"
43+
44+
namespace mapnik {
45+
46+
template <typename T0, typename T1>
47+
void agg_renderer<T0,T1>::process(dot_symbolizer const& sym,
48+
mapnik::feature_impl & feature,
49+
proj_transform const& prj_trans)
50+
{
51+
double width = 0.0;
52+
double height = 0.0;
53+
bool has_width = has_key(sym,keys::width);
54+
bool has_height = has_key(sym,keys::height);
55+
if (has_width && has_height)
56+
{
57+
width = get<double>(sym, keys::width, feature, common_.vars_, 0.0);
58+
height = get<double>(sym, keys::height, feature, common_.vars_, 0.0);
59+
}
60+
else if (has_width)
61+
{
62+
width = height = get<double>(sym, keys::width, feature, common_.vars_, 0.0);
63+
}
64+
else if (has_height)
65+
{
66+
width = height = get<double>(sym, keys::height, feature, common_.vars_, 0.0);
67+
}
68+
double rx = width/2.0;
69+
double ry = height/2.0;
70+
double opacity = get<double>(sym, keys::opacity, feature, common_.vars_, 1.0);
71+
color const& fill = get<mapnik::color>(sym, keys::fill, feature, common_.vars_, mapnik::color(128,128,128));
72+
ras_ptr->reset();
73+
agg::rendering_buffer buf(current_buffer_->raw_data(),current_buffer_->width(),current_buffer_->height(),current_buffer_->width() * 4);
74+
using blender_type = agg::comp_op_adaptor_rgba_pre<agg::rgba8, agg::order_rgba>;
75+
using pixfmt_comp_type = agg::pixfmt_custom_blend_rgba<blender_type, agg::rendering_buffer>;
76+
using renderer_base = agg::renderer_base<pixfmt_comp_type>;
77+
using renderer_type = agg::renderer_scanline_aa_solid<renderer_base>;
78+
pixfmt_comp_type pixf(buf);
79+
pixf.comp_op(static_cast<agg::comp_op_e>(get<composite_mode_e>(sym, keys::comp_op, feature, common_.vars_, src_over)));
80+
renderer_base renb(pixf);
81+
renderer_type ren(renb);
82+
agg::scanline_u8 sl;
83+
ren.color(agg::rgba8_pre(fill.red(), fill.green(), fill.blue(), int(fill.alpha() * opacity)));
84+
agg::ellipse el(0,0,rx,ry);
85+
unsigned num_steps = el.num_steps();
86+
for (geometry_type const& geom : feature.paths()) {
87+
double x,y,z = 0;
88+
unsigned cmd = 1;
89+
geom.rewind(0);
90+
while ((cmd = geom.vertex(&x, &y)) != mapnik::SEG_END) {
91+
if (cmd == SEG_CLOSE) continue;
92+
prj_trans.backward(x,y,z);
93+
common_.t_.forward(&x,&y);
94+
el.init(x,y,rx,ry,num_steps);
95+
ras_ptr->add_path(el);
96+
agg::render_scanlines(*ras_ptr, sl, ren);
97+
}
98+
}
99+
}
100+
101+
template void agg_renderer<image_32>::process(dot_symbolizer const&,
102+
mapnik::feature_impl &,
103+
proj_transform const&);
104+
105+
}

src/build.py

+1
Original file line numberDiff line numberDiff line change
@@ -301,6 +301,7 @@ def ldconfig(*args,**kwargs):
301301
source += Split(
302302
"""
303303
agg/agg_renderer.cpp
304+
agg/process_dot_symbolizer.cpp
304305
agg/process_building_symbolizer.cpp
305306
agg/process_line_symbolizer.cpp
306307
agg/process_line_pattern_symbolizer.cpp

src/load_map.cpp

+25
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,7 @@ class map_parser : mapnik::noncopyable
119119
void parse_markers_symbolizer(rule & rule, xml_node const& node);
120120
void parse_group_symbolizer(rule &rule, xml_node const& node);
121121
void parse_debug_symbolizer(rule & rule, xml_node const& node);
122+
void parse_dot_symbolizer(rule & rule, xml_node const& node);
122123
void parse_group_rule(group_symbolizer_properties &prop, xml_node const& node);
123124
void parse_simple_layout(group_symbolizer_properties &prop, xml_node const& node);
124125
void parse_pair_layout(group_symbolizer_properties &prop, xml_node const& node);
@@ -853,6 +854,11 @@ void map_parser::parse_symbolizers(rule & rule, xml_node const & node)
853854
parse_debug_symbolizer(rule, sym_node);
854855
sym_node.set_processed(true);
855856
break;
857+
case name2int("DotSymbolizer"):
858+
parse_dot_symbolizer(rule, sym_node);
859+
sym_node.set_processed(true);
860+
break;
861+
856862
default:
857863
break;
858864
}
@@ -908,6 +914,25 @@ void map_parser::parse_point_symbolizer(rule & rule, xml_node const & node)
908914
}
909915
}
910916

917+
void map_parser::parse_dot_symbolizer(rule & rule, xml_node const & node)
918+
{
919+
try
920+
{
921+
dot_symbolizer sym;
922+
set_symbolizer_property<symbolizer_base,color>(sym, keys::fill, node);
923+
set_symbolizer_property<symbolizer_base,double>(sym, keys::opacity, node);
924+
set_symbolizer_property<symbolizer_base,double>(sym, keys::width, node);
925+
set_symbolizer_property<symbolizer_base,double>(sym, keys::height, node);
926+
set_symbolizer_property<symbolizer_base,composite_mode_e>(sym, keys::comp_op, node);
927+
rule.append(std::move(sym));
928+
}
929+
catch (config_error const& ex)
930+
{
931+
ex.append_context(node);
932+
throw;
933+
}
934+
}
935+
911936
void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
912937
{
913938
try
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"keys": [
3+
""
4+
],
5+
"data": {},
6+
"grid": [
7+
" ",
8+
" ",
9+
" ",
10+
" ",
11+
" ",
12+
" ",
13+
" ",
14+
" ",
15+
" ",
16+
" ",
17+
" ",
18+
" ",
19+
" ",
20+
" ",
21+
" ",
22+
" ",
23+
" ",
24+
" ",
25+
" ",
26+
" ",
27+
" ",
28+
" ",
29+
" ",
30+
" ",
31+
" "
32+
]
33+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
{
2+
"keys": [
3+
""
4+
],
5+
"data": {},
6+
"grid": [
7+
" ",
8+
" ",
9+
" ",
10+
" ",
11+
" ",
12+
" ",
13+
" ",
14+
" ",
15+
" ",
16+
" ",
17+
" ",
18+
" ",
19+
" ",
20+
" ",
21+
" ",
22+
" ",
23+
" ",
24+
" ",
25+
" ",
26+
" ",
27+
" ",
28+
" ",
29+
" ",
30+
" ",
31+
" "
32+
]
33+
}
Loading
Loading
Loading
Loading

tests/visual_tests/styles/dots.xml

+26
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
<Map
2+
srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
3+
background-color="white">
4+
5+
<Style name="dots">
6+
<Rule>
7+
<DotSymbolizer height="[height]" width="[width]" fill="[fill]" opacity="[opacity]"/>
8+
</Rule>
9+
</Style>
10+
11+
<Layer name="layer" srs="+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs">
12+
<StyleName>dots</StyleName>
13+
<Datasource>
14+
<Parameter name="type">csv</Parameter>
15+
<Parameter name="extent">0,0,5,5</Parameter>
16+
<Parameter name="inline">
17+
fill, opacity,height, width, wkt
18+
green,.5, 40, 40, "POINT(2.5 2.5)"
19+
red, .5, 20, 20, "MULTIPOINT((2 2.5),(2.5 2.5),(3 2.5))"
20+
blue, .5, 45, 45, "POLYGON((1 1,4 1,4 4,1 4,1 1))"
21+
red, .5, 3, 3, "LINESTRING(3 2.5,3.0472522909029145 2.5549083791557554,3.088039946704745 2.6192015984770367,3.120968717931644 2.692088134329871,3.1447426958020195 2.7725928396160553,3.1581869214177796 2.859569153953152,3.1602684919277424 2.9517139787160285,3.150115859191815 3.0475850341520374,3.1270360384124487 3.1456204818095705,3.090529469857131 3.2441605641461093,3.0403023058681398 3.3414709848078967,2.9762759274968564 3.435767728064507,2.898593529924341 3.525242994563949,2.8076236529182754 3.6080919132297717,2.7039605714802892 3.6825396759861526,2.588421502084629 3.7468687332550683,2.4620406210083243 3.799445683953957,2.3260599327010416 3.838747494110833,2.181917067429678 3.863386683229473,2.0312301280479197 3.872135127146751,1.8757797451792864 3.8639461402385225,1.7174885378702207 3.8379745183057543,1.5583982123914466 3.7935942461113443,1.4006445648882897 3.7304136000915884,1.246430683579882 3.648287406936956,1.0979986727928661 3.547326252181924,0.9576002439358948 3.4279024692786355,0.8274665372684367 3.290652778432585,0.7097775527295491 3.136477485296219,0.606631577958298 2.966536191967265,0.5200150067991092 2.7822400161197343,0.45177294193977735 2.5852403579882455,0.4035809708310185 2.3774142988020817,0.3769184946959401 2.160846757592015,0.37304397632518604 1.9378095755409703,0.3929724535957084 1.7107377376983552,0.4374556424314622 1.4822029804218395,0.5069649254805411 1.2548850688650404,0.6016774914054002 1.0315410617374736,0.7214658547096571 0.8149729099992633,0.8658909478409702 0.6079937617301794,1.0341989363401651 0.4133933667857521,1.2253218645141815 0.23390299172467044,1.437882193988065 0.07216026761394456,1.6702012510582676 -0.06932559950169326,1.920311551565356 -0.18820782357901678,2.185972924581849 -0.2823348101737011,2.4646923091307618 -0.34978128405768727,2.753747051974397 -0.38887736562393815,3.0502114897965984 -0.3982352072417812,3.350986556389679 -0.37677282398941525,3.6528321152745926 -0.3237347810995832,3.9524016810311693 -0.2387094327324748,4.246279158964359 -0.12164244300528804,4.531017203016431 0.027153639820840958,4.803176766446595 0.2069939418962261,5.0593673990838255 0.416820095021341,5.2962878292111855 0.6552034322979141,5.510766357600486 0.9203525899932274,5.6998005860669245 1.2101255063356857,5.860596003276281 1.5220457563037595,5.990602956471176 1.8533231098340628,6.087551549283583 2.200878149857013,6.149484022799466 2.5613707367678797,6.1747841994053125 2.9312320579468265,6.162203596480088 3.306699955329308,6.110883849442411 3.683857181350839,6.02037512070598 4.058672194373903,5.890650212364317 4.427042069440575,5.722114145495159 4.78483706933339,5.515609017373219 5.127946394875156,5.272413999093365 5.4523246125098,4.994240389582243 5.754038241781528,4.683221697131584 6.029311975608545,4.34189877581244 6.2745740024088335,3.9732001007988598 6.486499901292641,3.5804173231036964 6.662054589735392,3.16717629986471 6.798531817364951,2.737403850475655 6.893590719648262,2.2952905409040607 6.945288971186986,1.8452498478612391 6.952112109805218,1.3918741005021504 6.912998639345142,0.9398876394743532 6.827360560726954,0.4940976708866134 6.695099026966764,0.05934332565157785 6.516614868014918,-0.3595565377529124 6.292813784961579,-0.7578562271360596 6.0251060697957435,-1.1309362311473898 5.715400765898583,-1.474355768902115 5.3660942451696325,-1.783904285743506 4.980053239466529,-2.055651309423385 4.560592426208784,-2.285994090762115 4.1114467298642285,-2.4717024691612375 3.636738561911254,-2.6099604260809084 3.1409402810613676,-2.698403818583074 2.6288322123574606,-2.7351538200309866 2.105456617575501,-2.718845635708872 1.5760680595181986,-2.648652107097507 1.0460806487014485,-2.524301869365668 0.5210127020395867,-2.3460917818082168 0.006429378924498685)"
22+
</Parameter>
23+
</Datasource>
24+
</Layer>
25+
26+
</Map>

0 commit comments

Comments
 (0)