markers: support offset, geometry-transform, and simplify - closes #2108

This commit is contained in:
Dane Springmeyer 2014-09-06 21:27:15 -07:00
parent bb0df1d6c6
commit 54b2880e53
11 changed files with 162 additions and 130 deletions

View file

@ -54,6 +54,8 @@ namespace agg
m_trans = &tr;
}
unsigned type() const { return m_source->type(); }
private:
conv_transform(const conv_transform<VertexSource>&);
const conv_transform<VertexSource>&

View file

@ -64,6 +64,11 @@ struct MAPNIK_DECL offset_converter
process
};
unsigned type() const
{
return static_cast<unsigned>(geom_.type());
}
double get_offset() const
{
return offset_;

View file

@ -49,11 +49,18 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
using raster_dispatch_type = T1;
using renderer_context_type = T2;
using conv_types = boost::mpl::vector<clip_poly_tag,transform_tag,smooth_tag>;
using svg_attribute_type = agg::pod_bvector<path_attributes>;
using conv_types = boost::mpl::vector<clip_line_tag,
clip_poly_tag,
transform_tag,
affine_transform_tag,
simplify_tag, smooth_tag,
offset_transform_tag>;
std::string filename = get<std::string>(sym, keys::file, feature, common.vars_, "shape://ellipse");
bool clip = get<value_bool>(sym, keys::clip, feature, common.vars_, false);
double offset = get<value_double>(sym, keys::offset, feature, common.vars_, 0.0);
double simplify_tolerance = get<value_double>(sym, keys::simplify_tolerance, feature, common.vars_, 0.0);
double smooth = get<value_double>(sym, keys::smooth, feature, common.vars_, false);
// https://github.com/mapnik/mapnik/issues/1316
@ -63,7 +70,10 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
boost::optional<marker_ptr> mark = mapnik::marker_cache::instance().find(filename, true);
if (mark && *mark)
{
agg::trans_affine tr = agg::trans_affine_scaling(common.scale_factor_);
agg::trans_affine geom_tr;
auto transform = get_optional<transform_type>(sym, keys::geometry_transform);
if (transform) evaluate_transform(geom_tr, feature, common.vars_, *transform, common.scale_factor_);
agg::trans_affine image_tr = agg::trans_affine_scaling(common.scale_factor_);
if ((*mark)->is_vector())
{
@ -84,12 +94,12 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
svg_attribute_type attributes;
bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym, feature, common.vars_);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
box2d<double> bbox = marker_ellipse.bounding_box();
vector_dispatch_type rasterizer_dispatch(svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
bbox,
tr,
image_tr,
sym,
*common.detector_,
common.scale_factor_,
@ -100,27 +110,28 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
vertex_converter<box2d<double>, vector_dispatch_type, markers_symbolizer,
view_transform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_);
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==Point
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}
else
{
box2d<double> const& bbox = (*mark)->bounding_box();
setup_transform_scaling(tr, bbox.width(), bbox.height(), feature, common.vars_, sym);
setup_transform_scaling(image_tr, bbox.width(), bbox.height(), feature, common.vars_, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
vertex_stl_adapter<svg_path_storage> stl_storage((*stock_vector_marker)->source());
svg_path_adapter svg_path(stl_storage);
svg_attribute_type attributes;
@ -128,7 +139,7 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
vector_dispatch_type rasterizer_dispatch(svg_path,
result ? attributes : (*stock_vector_marker)->attributes(),
bbox,
tr,
image_tr,
sym,
*common.detector_,
common.scale_factor_,
@ -139,33 +150,34 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
vertex_converter<box2d<double>, vector_dispatch_type, markers_symbolizer,
view_transform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_);
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==Point
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}
}
else // raster markers
{
setup_transform_scaling(tr, (*mark)->width(), (*mark)->height(), feature, common.vars_, sym);
setup_transform_scaling(image_tr, (*mark)->width(), (*mark)->height(), feature, common.vars_, sym);
auto image_transform = get_optional<transform_type>(sym, keys::image_transform);
if (image_transform) evaluate_transform(tr, feature, common.vars_, *image_transform);
if (image_transform) evaluate_transform(image_tr, feature, common.vars_, *image_transform);
box2d<double> const& bbox = (*mark)->bounding_box();
boost::optional<mapnik::image_ptr> marker = (*mark)->get_bitmap_data();
// - clamp sizes to > 4 pixels of interactivity
coord2d center = bbox.center();
agg::trans_affine_translation recenter(-center.x, -center.y);
agg::trans_affine marker_trans = recenter * tr;
agg::trans_affine marker_trans = recenter * image_tr;
raster_dispatch_type rasterizer_dispatch(**marker,
marker_trans,
sym,
@ -177,19 +189,20 @@ void render_markers_symbolizer(markers_symbolizer const& sym,
vertex_converter<box2d<double>, raster_dispatch_type, markers_symbolizer,
view_transform, proj_transform, agg::trans_affine, conv_types, feature_impl>
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,tr,feature,common.vars_,common.scale_factor_);
converter(clip_box, rasterizer_dispatch, sym,common.t_,prj_trans,geom_tr,feature,common.vars_,common.scale_factor_);
if (clip && feature.paths().size() > 0) // optional clip (default: true)
{
geometry_type::types type = feature.paths()[0].type();
if (type == geometry_type::types::Polygon)
converter.template set<clip_poly_tag>();
// line clipping disabled due to https://github.com/mapnik/mapnik/issues/1426
//else if (type == geometry_type::types::LineString)
// converter.template set<clip_line_tag>();
// don't clip if type==geometry_type::types::Point
else if (type == geometry_type::types::LineString)
converter.template set<clip_line_tag>();
}
converter.template set<transform_tag>(); //always transform
if (std::fabs(offset) > 0.0) converter.template set<offset_transform_tag>(); // parallel offset
converter.template set<affine_transform_tag>(); // optional affine transform
if (simplify_tolerance > 0.0) converter.template set<simplify_tag>(); // optional simplify converter
if (smooth > 0.0) converter.template set<smooth_tag>(); // optional smooth converter
apply_markers_multi(feature, common.vars_, converter, sym);
}

View file

@ -109,6 +109,11 @@ public:
cache
};
unsigned type() const
{
return static_cast<unsigned>(geom_.type());
}
simplify_algorithm_e get_simplify_algorithm()
{
return algorithm_;

View file

@ -969,6 +969,8 @@ void map_parser::parse_markers_symbolizer(rule & rule, xml_node const& node)
set_symbolizer_property<markers_symbolizer,boolean_type>(sym, keys::avoid_edges, node);
// ignore-placement
set_symbolizer_property<markers_symbolizer,boolean_type>(sym, keys::ignore_placement, node);
// offset
set_symbolizer_property<symbolizer_base,double>(sym, keys::offset, node);
// width
//set_symbolizer_property<markers_symbolizer,double>(sym, keys::width, node);
// height
@ -1025,8 +1027,7 @@ void map_parser::parse_line_pattern_symbolizer(rule & rule, xml_node const & nod
set_symbolizer_property<line_pattern_symbolizer,double>(sym, keys::opacity, node);
// offset value
optional<double> offset = node.get_opt_attr<double>("offset");
if (offset) put(sym, keys::offset, *offset);
set_symbolizer_property<symbolizer_base,double>(sym, keys::offset, node);
// image transform
set_symbolizer_property<line_pattern_symbolizer, transform_type>(sym, keys::image_transform, node);
rule.append(std::move(sym));

View file

@ -5,105 +5,105 @@
],
"data": {},
"grid": [
" !!! ",
" !!! ",
" !!!! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" !! ! ",
" !! !!! ",
" ! !!! ",
" ! !! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" !! ! ",
" !!! ! ",
" !! !!! ",
" ! !!! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" !! ! ",
" !!! ",
" !!! !!! ",
" ! !!! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ",
" ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" !!! ! ",
" !!! !! !! ",
" !! !! !!! ",
" ! !! !!! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! ! ! ",
" ! ! ",
" ! !! "
" !!!!!! ",
" ! !! !!!! !! ",
" ! ! !!! ! ! ",
" ! ! !! ! !!! ",
" ! ! !!! ! !! ",
" ! ! ! ! ! ",
" ! ! ! ! !! ",
" ! ! ! ! ! ! ",
" ! ! ! ! ",
" ! ! ! !!! ! !! ",
" !! ! !!! !! ",
" ! !! ! ! ! ",
" ! ! ! !! ",
" ! ! ! ! ! !!! ",
" ! ! ! ! !!! ",
" ! ! ! ! ! ! !! ! ",
" ! ! ! ! !!! ",
" !! ! ! ! ! ! !!! ",
" !! ! ! ! !! ! ",
" ! !! ! ! !!! ! ",
" ! !!!!! ! !! ! ",
" !! !! ! ! ! ",
" ! ! ! !! !! ! ",
" ! ! !!! ! ! ",
" ! ! ! ! ",
" ! ! ! ! ! ",
" ! ! ! ! ! ! ",
" ! ! ! ",
" ! ! ! ! ! ",
" ! ! ! ! ! ",
" ! ! ! ! ! ",
" ! ! !! ! ! ",
" ! ! ! ! !!! ! ! ! ",
" ! ! ! !! ! ! ",
" ! ! ! ! ",
" ! ! ! ! ! ! ",
" ! ! !!! ",
" ! ! ! ! !!!! ",
" ! ! !!! ! ",
" !! ! ! ! !!!! ",
" !!! ! ! !!!!! ",
" !! !!! ! ! !! ",
" ! !!!!!! ! !!! ",
" !!!!! !! !!!! ! ",
" ! ! ! !!! ! ! ",
" ! ! ! !! !!!! ",
" ! ! ! !!!!! ! ",
" ! ! ! ! ! ",
" ! ! ! ! ! ! ",
" ! ! ! ! ",
" ! ! ! ! ! ",
" ! ! ! !! ! ",
" ! ! ! ",
" ! ! ! !! ",
" ! ! !! ! ",
" ! ! ! !!!! ",
" ! ! ! ! ",
" !! ! ! ! ",
" ! ! ! !! ",
" ! ! ! ! ",
" !! ! !! ",
" ! ! !!!! ",
" ! !! ! !!! ",
" !! !! ! !!!! ",
" !! !!! ! !!!! ",
" !! !!! !! !!! ",
" ! !!! !!! !! ",
" !!! !!! !!!! ",
" ! ! ! !!! ",
" ! ! ! ! ! ",
" ! ! ! ! ",
" ! ! !! ",
" ! ! ! ! ",
" ! ! !! ",
" ! !! ",
" ! ! ! ! !! !! ",
" ! ! ! !!! !!! ",
" ! ! ! !!! !!! ",
" ! ! ! ! !!! ",
" ! ! ! !! ! ! ! ",
" !!! ! ! ! !! ",
" ! !! ! ! !! ! ",
" ! !!! ! ! ! !!! ",
" ! !!! !! ! ! !!! ! ",
" ! !!!! ! ! !! ",
" ! ! ! !!! ! !! ! ! !!! ",
" ! ! !!!! !!! ! ! !!! ",
" !!! ! !!!! !!! ! ! ",
" !!!!! !! ! ! ",
" !!!!! !! !! !! ! ! ! ",
" !!!!! !!! !!! ! ! ! ",
" !!!! !!!! !!! ! ! ! ",
" ! !! ! ! ! ! ",
" !!! ! ! ! ! ",
" !! ! ! ! !!! ! ",
" !! ! !!! ! !! ! ! ",
" ! ! ! !! ! ",
" !! ! !! ! ! ! ! ",
" ! ! !! ! ! ! ! ",
" ! ! !!! ! ! ! "
]
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.8 KiB

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 12 KiB

View file

@ -1,13 +1,19 @@
<Map>
<Style name="line" filter-mode="first" >
<Rule>
<LineSymbolizer stroke="#000000" />
<LineSymbolizer stroke="red"/>
<LineSymbolizer stroke="blue" smooth=".5"/>
<LineSymbolizer stroke="orange" smooth="1"/>
<LineSymbolizer stroke="green" smooth="1" geometry-transform="translate(10,10)" />
</Rule>
</Style>
<Style name="point-placement" filter-mode="first" >
<Rule>
<MarkersSymbolizer allow-overlap="false" ignore-placement="true" placement="line" marker-type="ellipse" fill="blue" />
<DebugSymbolizer />
<MarkersSymbolizer stroke-width="0" allow-overlap="true" placement="line" marker-type="ellipse" fill="red" />
<MarkersSymbolizer stroke-width="0" offset="-10" transform="translate(0,-10)" allow-overlap="true" placement="line" marker-type="ellipse" fill="darkred" />
<MarkersSymbolizer stroke-width="0" allow-overlap="true" smooth=".5" transform="translate(10,10) translate(-10,-10)" placement="line" marker-type="ellipse" fill="blue" />
<MarkersSymbolizer stroke-width="0" allow-overlap="true" smooth="1" placement="line" marker-type="ellipse" fill="orange" />
<MarkersSymbolizer stroke-width="0" allow-overlap="true" smooth="1" geometry-transform="translate(10,10)" placement="line" marker-type="ellipse" fill="darkgreen" />
</Rule>
</Style>
<Layer name="carto_tests">