From 39a1477eb2147c7f85d2c9f38645e3f71034402f Mon Sep 17 00:00:00 2001 From: Dane Springmeyer Date: Mon, 30 Jul 2012 23:20:20 -0700 Subject: [PATCH] allow marker-width and marker-height to apply directly to ellipse rx/ry - maintaining ability to precisely control ellipse dimensions, combine with transforms, and avoid scaling line-widths - refs #1348 and #1347 --- src/agg/process_markers_symbolizer.cpp | 110 ++++++++++++++++++++----- 1 file changed, 89 insertions(+), 21 deletions(-) diff --git a/src/agg/process_markers_symbolizer.cpp b/src/agg/process_markers_symbolizer.cpp index bec7f92e1..bc5f9c851 100644 --- a/src/agg/process_markers_symbolizer.cpp +++ b/src/agg/process_markers_symbolizer.cpp @@ -32,12 +32,16 @@ #include #include #include +#include +#include #include +#include #include #include // agg #include "agg_basics.h" +#include "agg_ellipse.h" #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_rasterizer_scanline_aa.h" @@ -318,29 +322,92 @@ void agg_renderer::process(markers_symbolizer const& sym, renderer_type, agg::pixfmt_rgba32 > svg_renderer_type; typedef vector_markers_rasterizer_dispatch dispatch_type; - box2d const& bbox = (*mark)->bounding_box(); - setup_label_transform(tr, bbox, feature, sym); - coord2d center = bbox.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine marker_trans = recenter * tr; - boost::optional vector_marker = (*mark)->get_vector_data(); - vertex_stl_adapter stl_storage((*vector_marker)->source()); - svg_path_adapter svg_path(stl_storage); - agg::pod_bvector attributes; - bool result = push_explicit_style( (*vector_marker)->attributes(), attributes, sym); - svg_renderer_type svg_renderer(svg_path, result ? attributes : (*vector_marker)->attributes()); - dispatch_type rasterizer_dispatch(*current_buffer_,svg_renderer,*ras_ptr, - bbox, marker_trans, sym, *detector_, scale_factor_); - vertex_converter, dispatch_type, markers_symbolizer, - CoordTransform, proj_transform, agg::trans_affine, conv_types> - converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); - if (sym.clip()) converter.template set(); //optional clip (default: true) - converter.template set(); //always transform - if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter - BOOST_FOREACH(geometry_type & geom, feature.paths()) + boost::optional const& stock_vector_marker = (*mark)->get_vector_data(); + expression_ptr const& width_expr = sym.get_width(); + expression_ptr const& height_expr = sym.get_height(); + + // special case for simple ellipse markers + // to allow for full control over rx/ry dimensions + if (filename == "shape://ellipse" + && (width_expr || height_expr)) { - converter.apply(geom); + double width = 0; + double height = 0; + if (width_expr && height_expr) + { + width = boost::apply_visitor(evaluate(feature), *width_expr).to_double(); + height = boost::apply_visitor(evaluate(feature), *height_expr).to_double(); + } + else if (width_expr) + { + width = boost::apply_visitor(evaluate(feature), *width_expr).to_double(); + height = width; + } + else if (height_expr) + { + height = boost::apply_visitor(evaluate(feature), *height_expr).to_double(); + width = height; + } + // create a new marker + svg_storage_type marker_ellipse; + vertex_stl_adapter stl_storage(marker_ellipse.source()); + svg_path_adapter svg_path(stl_storage); + svg_converter_type styled_svg(svg_path, marker_ellipse.attributes()); + styled_svg.push_attr(); + styled_svg.begin_path(); + agg::ellipse c(0, 0, width/2.0, height/2.0); + styled_svg.storage().concat_path(c); + styled_svg.end_path(); + styled_svg.pop_attr(); + double lox,loy,hix,hiy; + styled_svg.bounding_rect(&lox, &loy, &hix, &hiy); + marker_ellipse.set_bounding_box(lox,loy,hix,hiy); + agg::pod_bvector attributes; + bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym); + svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes()); + evaluate_transform(tr, feature, sym.get_image_transform()); + box2d bbox = marker_ellipse.bounding_box(); + coord2d center = bbox.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine marker_trans = recenter * tr; + dispatch_type rasterizer_dispatch(*current_buffer_,svg_renderer,*ras_ptr, + bbox, marker_trans, sym, *detector_, scale_factor_); + vertex_converter, dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip()) converter.template set(); //optional clip (default: true) + converter.template set(); //always transform + if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter + BOOST_FOREACH(geometry_type & geom, feature.paths()) + { + converter.apply(geom); + } + } + else + { + box2d const& bbox = (*mark)->bounding_box(); + setup_label_transform(tr, bbox, feature, sym); + coord2d center = bbox.center(); + agg::trans_affine_translation recenter(-center.x, -center.y); + agg::trans_affine marker_trans = recenter * tr; + vertex_stl_adapter stl_storage((*stock_vector_marker)->source()); + svg_path_adapter svg_path(stl_storage); + agg::pod_bvector attributes; + bool result = push_explicit_style( (*stock_vector_marker)->attributes(), attributes, sym); + svg_renderer_type svg_renderer(svg_path, result ? attributes : (*stock_vector_marker)->attributes()); + dispatch_type rasterizer_dispatch(*current_buffer_,svg_renderer,*ras_ptr, + bbox, marker_trans, sym, *detector_, scale_factor_); + vertex_converter, dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_* 1.1,rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip()) converter.template set(); //optional clip (default: true) + converter.template set(); //always transform + if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter + BOOST_FOREACH(geometry_type & geom, feature.paths()) + { + converter.apply(geom); + } } } else // raster markers @@ -357,6 +424,7 @@ void agg_renderer::process(markers_symbolizer const& sym, vertex_converter, dispatch_type, markers_symbolizer, CoordTransform, proj_transform, agg::trans_affine, conv_types> converter(query_extent_* 1.1, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip()) converter.template set(); //optional clip (default: true) converter.template set(); //always transform if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter