diff --git a/src/grid/process_markers_symbolizer.cpp b/src/grid/process_markers_symbolizer.cpp index 823bad284..91d120dc7 100644 --- a/src/grid/process_markers_symbolizer.cpp +++ b/src/grid/process_markers_symbolizer.cpp @@ -24,22 +24,15 @@ porting notes --> - - grid includes - - detector + - rasterizer -> grid_rasterizer + - current_buffer_ -> pixmap_ + - agg::rendering_buffer -> grid_renderering_buffer - no gamma - mapnik::pixfmt_gray32 - agg::scanline_bin sl - grid_rendering_buffer - agg::renderer_scanline_bin_solid - - clamping: - // - clamp sizes to > 4 pixels of interactivity - if (tr.scale() < 0.5) - { - agg::trans_affine tr2; - tr2 *= agg::trans_affine_scaling(0.5); - tr = tr2; - } - tr *= agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution())); + - TODO - clamp sizes to > 4 pixels of interactivity - svg_renderer.render_id - only encode feature if placements are found: if (placed) @@ -55,6 +48,7 @@ porting notes --> #include #include #include +#include #include #include @@ -67,7 +61,6 @@ porting notes --> #include #include #include -#include #include // agg @@ -75,15 +68,6 @@ porting notes --> #include "agg_rendering_buffer.h" #include "agg_pixfmt_rgba.h" #include "agg_rasterizer_scanline_aa.h" -#include "agg_scanline_u.h" -#include "agg_path_storage.h" -#include "agg_conv_clip_polyline.h" -#include "agg_conv_transform.h" -#include "agg_image_filters.h" -#include "agg_trans_bilinear.h" -#include "agg_span_allocator.h" -#include "agg_image_accessors.h" -#include "agg_span_image_filter_rgba.h" // boost #include @@ -99,8 +83,12 @@ void grid_renderer::process(markers_symbolizer const& sym, mapnik::feature_impl & feature, proj_transform const& prj_trans) { - typedef agg::renderer_base renderer_base; + typedef grid_rendering_buffer buf_type; + typedef mapnik::pixfmt_gray32 pixfmt_type; + typedef agg::renderer_base renderer_base; typedef agg::renderer_scanline_bin_solid renderer_type; + typedef label_collision_detector4 detector_type; + typedef boost::mpl::vector conv_types; std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); @@ -109,129 +97,166 @@ void grid_renderer::process(markers_symbolizer const& sym, boost::optional mark = mapnik::marker_cache::instance()->find(filename, true); if (mark && *mark) { - if (!(*mark)->is_vector()) - { - MAPNIK_LOG_DEBUG(agg_renderer) << "agg_renderer: markers_symbolizer does not yet support non-SVG markers"; - return; - } - ras_ptr->reset(); - agg::scanline_bin sl; - grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); - mapnik::pixfmt_gray32 pixf(buf); - renderer_base renb(pixf); - renderer_type ren(renb); - agg::trans_affine geom_tr; evaluate_transform(geom_tr, feature, sym.get_transform()); + agg::trans_affine tr = agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution())); - boost::optional marker = (*mark)->get_vector_data(); - box2d const& bbox = (*marker)->bounding_box(); - - agg::trans_affine tr; - setup_transform_scaling(tr, bbox, feature, sym); - evaluate_transform(tr, feature, sym.get_image_transform()); - // - clamp sizes to > 4 pixels of interactivity - if (tr.scale() < 0.5) + if ((*mark)->is_vector()) { - agg::trans_affine tr2; - tr2 *= agg::trans_affine_scaling(0.5); - tr = tr2; - } - tr *= agg::trans_affine_scaling(scale_factor_*(1.0/pixmap_.get_resolution())); + using namespace mapnik::svg; + typedef agg::pod_bvector svg_attribute_type; + typedef svg_renderer svg_renderer_type; + typedef vector_markers_rasterizer_dispatch_grid dispatch_type; + 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(); - coord2d center = bbox.center(); - agg::trans_affine_translation recenter(-center.x, -center.y); - agg::trans_affine marker_trans = recenter * tr; - - using namespace mapnik::svg; - vertex_stl_adapter stl_storage((*marker)->source()); - svg_path_adapter svg_path(stl_storage); - - agg::pod_bvector attributes; - bool result = push_explicit_style( (*marker)->attributes(), attributes, sym); - - svg_renderer, - renderer_type, - mapnik::pixfmt_gray32 > svg_renderer(svg_path, result ? attributes : (*marker)->attributes()); - - marker_placement_e placement_method = sym.get_marker_placement(); - - bool placed = false; - BOOST_FOREACH( geometry_type & geom, feature.paths()) - { - // TODO - merge this code with point_symbolizer rendering - if (placement_method == MARKER_POINT_PLACEMENT || geom.size() <= 1) + // special case for simple ellipse markers + // to allow for full control over rx/ry dimensions + if (filename == "shape://ellipse" + && (width_expr || height_expr)) { - double x; - double y; - double z=0; - label::interior_position(geom, x, y); - prj_trans.backward(x,y,z); - t_.forward(&x,&y); - geom_tr.transform(&x,&y); - agg::trans_affine matrix = marker_trans; - matrix.translate(x,y); - box2d transformed_bbox = bbox * matrix; - - if (sym.get_allow_overlap() || - detector_->has_placement(transformed_bbox)) + svg_storage_type marker_ellipse; + vertex_stl_adapter stl_storage(marker_ellipse.source()); + svg_path_adapter svg_path(stl_storage); + // TODO - clamping to >= 4 pixels + build_ellipse(sym, feature, marker_ellipse, svg_path); + svg_attribute_type 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; + buf_type render_buf(pixmap_.raw_data(), width_, height_, width_); + dispatch_type rasterizer_dispatch(render_buf, + svg_renderer, + *ras_ptr, + bbox, + marker_trans, + sym, + *detector_, + scale_factor_, + feature, + pixmap_); + vertex_converter, dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) { - placed = true; - svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, 1, bbox); - if (!sym.get_ignore_placement()) - detector_->insert(transformed_bbox); + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.template set(); + else if (type == LineString) + converter.template set(); + // don't clip if type==Point } - } - else if (sym.clip()) - { - typedef agg::conv_clip_polyline clipped_geometry_type; - typedef coord_transform path_type; - typedef agg::conv_transform transformed_path_type; - - clipped_geometry_type clipped(geom); - clipped.clip_box(query_extent_.minx(),query_extent_.miny(),query_extent_.maxx(),query_extent_.maxy()); - path_type path(t_,clipped,prj_trans); - transformed_path_type path_transformed(path,geom_tr); - markers_placement placement(path_transformed, bbox, marker_trans, *detector_, - sym.get_spacing() * scale_factor_, - sym.get_max_error(), - sym.get_allow_overlap()); - double x, y, angle; - while (placement.get_point(x, y, angle)) + converter.template set(); //always transform + if (sym.smooth() > 0.0) converter.template set(); // optional smooth converter + BOOST_FOREACH(geometry_type & geom, feature.paths()) { - placed = true; - agg::trans_affine matrix = marker_trans; - matrix.rotate(angle); - matrix.translate(x, y); - svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, 1, bbox); + converter.apply(geom); } } else { - typedef coord_transform path_type; - typedef agg::conv_transform transformed_path_type; - path_type path(t_,geom,prj_trans); - transformed_path_type path_transformed(path,geom_tr); - markers_placement placement(path_transformed, bbox, marker_trans, *detector_, - sym.get_spacing() * scale_factor_, - sym.get_max_error(), - sym.get_allow_overlap()); - double x, y, angle; - while (placement.get_point(x, y, angle)) + box2d const& bbox = (*mark)->bounding_box(); + setup_transform_scaling(tr, bbox, feature, sym); + evaluate_transform(tr, feature, sym.get_image_transform()); + // TODO - clamping to >= 4 pixels + 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); + svg_attribute_type 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()); + buf_type render_buf(pixmap_.raw_data(), width_, height_, width_); + dispatch_type rasterizer_dispatch(render_buf, + svg_renderer, + *ras_ptr, + bbox, + marker_trans, + sym, + *detector_, + scale_factor_, + feature, + pixmap_); + vertex_converter, dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) { - placed = true; - agg::trans_affine matrix = marker_trans; - matrix.rotate(angle); - matrix.translate(x, y); - svg_renderer.render_id(*ras_ptr, sl, renb, feature.id(), matrix, 1, bbox); + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.template set(); + else if (type == LineString) + converter.template set(); + // don't clip if type==Point + } + 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); } } } - if (placed) + else // raster markers { - pixmap_.add_feature(feature); + box2d const& bbox = (*mark)->bounding_box(); + setup_transform_scaling(tr, bbox, feature, sym); + evaluate_transform(tr, feature, sym.get_image_transform()); + // - 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; + boost::optional marker = (*mark)->get_bitmap_data(); + typedef raster_markers_rasterizer_dispatch_grid dispatch_type; + buf_type render_buf(pixmap_.raw_data(), width_, height_, width_); + dispatch_type rasterizer_dispatch(render_buf, + *ras_ptr, + **marker, + marker_trans, + sym, + *detector_, + scale_factor_, + feature, + pixmap_); + vertex_converter, dispatch_type, markers_symbolizer, + CoordTransform, proj_transform, agg::trans_affine, conv_types> + converter(query_extent_, rasterizer_dispatch, sym,t_,prj_trans,tr,scale_factor_); + if (sym.clip() && feature.paths().size() > 0) // optional clip (default: true) + { + eGeomType type = feature.paths()[0].type(); + if (type == Polygon) + converter.template set(); + else if (type == LineString) + converter.template set(); + // don't clip if type==Point + } + 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); + } } } }