void agg_renderer<T>::process(point_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); boost::optional<mapnik::marker_ptr> marker; if ( !filename.empty() ) { marker = marker_cache::instance()->find(filename, true); } else { marker.reset(boost::make_shared<mapnik::marker>()); } if (marker) { for (unsigned i=0; i<feature.num_geometries(); ++i) { geometry_type const& geom = feature.get_geometry(i); double x; double y; double z=0; if (sym.get_point_placement() == CENTROID_POINT_PLACEMENT) geom.label_position(&x, &y); else geom.label_interior_position(&x, &y); prj_trans.backward(x,y,z); t_.forward(&x,&y); int w = (*marker)->width(); int h = (*marker)->height(); int px = int(floor(x - 0.5 * w)); int py = int(floor(y - 0.5 * h)); box2d<double> label_ext (px, py, px + w, py + h); if (sym.get_allow_overlap() || detector_.has_placement(label_ext)) { agg::trans_affine tr; boost::array<double,6> const& m = sym.get_transform(); tr.load_from(&m[0]); render_marker(px,py,**marker,tr, sym.get_opacity()); if (!sym.get_ignore_placement()) detector_.insert(label_ext); metawriter_with_properties writer = sym.get_metawriter(); if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second); } } } }
bool pass(Feature const& feature) { for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.hit_test(x_,y_,tol_)) return true; } return false; }
void agg_renderer<T>::process(line_pattern_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef agg::line_image_pattern<agg::pattern_filter_bilinear_rgba8> pattern_type; typedef agg::renderer_base<agg::pixfmt_rgba32_plain> renderer_base; typedef agg::renderer_outline_image<renderer_base, pattern_type> renderer_type; typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type; agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); boost::optional<marker_ptr> mark = marker_cache::instance()->find(filename,true); if (!mark || !(*mark)->is_bitmap()) return; boost::optional<image_ptr> pat = (*mark)->get_bitmap_data(); if (!pat) return; renderer_base ren_base(pixf); agg::pattern_filter_bilinear_rgba8 filter; pattern_source source(*(*pat)); pattern_type pattern (filter,source); renderer_type ren(ren_base, pattern); ren.clip_box(0,0,width_,height_); rasterizer_type ras(ren); metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 1) { path_type path(t_,geom,prj_trans); ras.add_path(path); if (writer.first) writer.first->add_line(path, feature, t_, writer.second); } } }
void agg_renderer<T>::process(line_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; typedef coord_transform2<CoordTransform,geometry_type> path_type; stroke const& stroke_ = sym.get_stroke(); color const& col = stroke_.get_color(); unsigned r=col.red(); unsigned g=col.green(); unsigned b=col.blue(); unsigned a=col.alpha(); agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); if (sym.get_rasterizer() == RASTERIZER_FAST) { typedef agg::renderer_outline_aa<ren_base> renderer_type; typedef agg::rasterizer_outline_aa<renderer_type> rasterizer_type; agg::line_profile_aa profile; //agg::line_profile_aa profile(stroke_.get_width() * scale_factor_, agg::gamma_none()); profile.width(stroke_.get_width() * scale_factor_); ren_base base_ren(pixf); renderer_type ren(base_ren, profile); ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity()))); //ren.clip_box(0,0,width_,height_); rasterizer_type ras(ren); ras.line_join(agg::outline_miter_accurate_join); ras.round_cap(true); for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 1) { path_type path(t_,geom,prj_trans); ras.add_path(path); } } } else { typedef agg::renderer_scanline_aa_solid<ren_base> renderer; agg::scanline_p8 sl; ren_base renb(pixf); renderer ren(renb); ras_ptr->reset(); switch (stroke_.get_gamma_method()) { case GAMMA_POWER: ras_ptr->gamma(agg::gamma_power(stroke_.get_gamma())); break; case GAMMA_LINEAR: ras_ptr->gamma(agg::gamma_linear(0.0, stroke_.get_gamma())); break; case GAMMA_NONE: ras_ptr->gamma(agg::gamma_none()); break; case GAMMA_THRESHOLD: ras_ptr->gamma(agg::gamma_threshold(stroke_.get_gamma())); break; case GAMMA_MULTIPLY: ras_ptr->gamma(agg::gamma_multiply(stroke_.get_gamma())); break; default: ras_ptr->gamma(agg::gamma_power(stroke_.get_gamma())); } metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 1) { path_type path(t_,geom,prj_trans); if (stroke_.has_dash()) { agg::conv_dash<path_type> dash(path); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); dash_array::const_iterator end = d.end(); for (;itr != end;++itr) { dash.add_dash(itr->first * scale_factor_, itr->second * scale_factor_); } agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); } else { agg::conv_stroke<path_type> stroke(path); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); if (writer.first) writer.first->add_line(path, feature, t_, writer.second); } } } ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); } }
void grid_renderer<T>::process(line_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef agg::renderer_base<mapnik::pixfmt_gray16> ren_base; typedef agg::renderer_scanline_bin_solid<ren_base> renderer; agg::scanline_bin sl; grid_rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_); mapnik::pixfmt_gray16 pixf(buf); ren_base renb(pixf); renderer ren(renb); ras_ptr->reset(); stroke const& stroke_ = sym.get_stroke(); for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 1) { path_type path(t_,geom,prj_trans); if (stroke_.has_dash()) { agg::conv_dash<path_type> dash(path); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); dash_array::const_iterator end = d.end(); for (;itr != end;++itr) { dash.add_dash(itr->first * scale_factor_, itr->second * scale_factor_); } agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); } else { agg::conv_stroke<path_type> stroke(path); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); } } } // render id ren.color(mapnik::gray16(feature.id())); agg::render_scanlines(*ras_ptr, sl, ren); // add feature properties to grid cache pixmap_.add_feature(feature); }
void agg_renderer<T>::process(building_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef coord_transform3<CoordTransform,geometry_type> path_type_roof; typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; typedef agg::renderer_scanline_aa_solid<ren_base> renderer; agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); ren_base renb(pixf); color const& fill_ = sym.get_fill(); unsigned r=fill_.red(); unsigned g=fill_.green(); unsigned b=fill_.blue(); unsigned a=fill_.alpha(); renderer ren(renb); agg::scanline_u8 sl; ras_ptr->reset(); ras_ptr->gamma(agg::gamma_linear()); double height = 0.0; expression_ptr height_expr = sym.height(); if (height_expr) { value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature), *height_expr); height = result.to_double() * scale_factor_; } for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 2) { boost::scoped_ptr<geometry_type> frame(new geometry_type(LineString)); boost::scoped_ptr<geometry_type> roof(new geometry_type(Polygon)); std::deque<segment_t> face_segments; double x0(0); double y0(0); unsigned cm = geom.vertex(&x0,&y0); for (unsigned j=1;j<geom.num_points();++j) { double x(0); double y(0); cm = geom.vertex(&x,&y); if (cm == SEG_MOVETO) { frame->move_to(x,y); } else if (cm == SEG_LINETO) { frame->line_to(x,y); face_segments.push_back(segment_t(x0,y0,x,y)); } x0 = x; y0 = y; } std::sort(face_segments.begin(),face_segments.end(), y_order); std::deque<segment_t>::const_iterator itr=face_segments.begin(); for (;itr!=face_segments.end();++itr) { boost::scoped_ptr<geometry_type> faces(new geometry_type(Polygon)); faces->move_to(itr->get<0>(),itr->get<1>()); faces->line_to(itr->get<2>(),itr->get<3>()); faces->line_to(itr->get<2>(),itr->get<3>() + height); faces->line_to(itr->get<0>(),itr->get<1>() + height); path_type faces_path (t_,*faces,prj_trans); ras_ptr->add_path(faces_path); ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); frame->move_to(itr->get<0>(),itr->get<1>()); frame->line_to(itr->get<0>(),itr->get<1>()+height); } geom.rewind(0); for (unsigned j=0;j<geom.num_points();++j) { double x,y; unsigned cm = geom.vertex(&x,&y); if (cm == SEG_MOVETO) { frame->move_to(x,y+height); roof->move_to(x,y+height); } else if (cm == SEG_LINETO) { frame->line_to(x,y+height); roof->line_to(x,y+height); } } geom.rewind(0); path_type path(t_,*frame,prj_trans); agg::conv_stroke<path_type> stroke(path); ras_ptr->add_path(stroke); ren.color(agg::rgba8(int(r*0.8), int(g*0.8), int(b*0.8), int(255 * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); ras_ptr->reset(); path_type roof_path (t_,*roof,prj_trans); ras_ptr->add_path(roof_path); ren.color(agg::rgba8(r, g, b, int(a * sym.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); } } }
void agg_renderer<T>::process(point_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef agg::pixfmt_rgba32 pixfmt; typedef agg::renderer_base<pixfmt> renderer_base; typedef agg::renderer_scanline_aa_solid<renderer_base> renderer_solid; double x; double y; double z=0; std::string filename = path_processor_type::evaluate(*sym.get_filename(), feature); boost::optional<mapnik::image_ptr> data; if (is_svg(filename)) { // SVG using namespace mapnik::svg; boost::optional<path_ptr> marker; ras_ptr->reset(); ras_ptr->gamma(agg::gamma_linear()); agg::scanline_u8 sl; agg::rendering_buffer buf(pixmap_.raw_data(), width_, height_, width_ * 4); pixfmt pixf(buf); renderer_base renb(pixf); renderer_solid ren(renb); box2d<double> extent; marker = marker_cache::instance()->find(filename, true); if (marker && *marker) { box2d<double> const& bbox = (*marker)->bounding_box(); double x1 = bbox.minx(); double y1 = bbox.miny(); double x2 = bbox.maxx(); double y2 = bbox.maxy(); vertex_stl_adapter<svg_path_storage> stl_storage((*marker)->source()); svg_path_adapter svg_path(stl_storage); svg_renderer<svg_path_adapter, agg::pod_bvector<path_attributes> > svg_renderer(svg_path, (*marker)->attributes()); for (unsigned i=0; i<feature.num_geometries(); ++i) { geometry2d const& geom = feature.get_geometry(i); geom.label_position(&x,&y); prj_trans.backward(x,y,z); t_.forward(&x,&y); agg::trans_affine tr; boost::array<double,6> const& m = sym.get_transform(); tr.load_from(&m[0]); tr *= agg::trans_affine_scaling(scale_factor_); tr *= agg::trans_affine_translation(x, y); tr.transform(&x1,&y1); tr.transform(&x2,&y2); extent.init(x1,y1,x2,y2); if (sym.get_allow_overlap() || detector_.has_placement(extent)) { svg_renderer.render(*ras_ptr, sl, ren, tr, renb.clip_box(), sym.get_opacity()); detector_.insert(extent); metawriter_with_properties writer = sym.get_metawriter(); if (writer.first) { writer.first->add_box(extent, feature, t_, writer.second); } } } } } else { if ( filename.empty() ) { // default OGC 4x4 black square data = boost::optional<mapnik::image_ptr>(new image_data_32(4,4)); (*data)->set(0xff000000); } else { data = mapnik::image_cache::instance()->find(filename,true); } if ( data ) { for (unsigned i=0; i<feature.num_geometries(); ++i) { geometry2d const& geom = feature.get_geometry(i); geom.label_position(&x,&y); prj_trans.backward(x,y,z); t_.forward(&x,&y); int w = (*data)->width(); int h = (*data)->height(); int px = int(floor(x - 0.5 * w)); int py = int(floor(y - 0.5 * h)); box2d<double> label_ext (px, py, px + w, py + h); if (sym.get_allow_overlap() || detector_.has_placement(label_ext)) { pixmap_.set_rectangle_alpha2(*(*data), px, py, sym.get_opacity()); detector_.insert(label_ext); metawriter_with_properties writer = sym.get_metawriter(); if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second); } } } } }
void agg_renderer<T>::process(line_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef agg::renderer_outline_aa<ren_base> renderer_oaa; typedef agg::rasterizer_outline_aa<renderer_oaa> rasterizer_outline_aa; typedef agg::renderer_scanline_aa_solid<ren_base> renderer; agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); ren_base renb(pixf); stroke const& stroke_ = sym.get_stroke(); color const& col = stroke_.get_color(); unsigned r=col.red(); unsigned g=col.green(); unsigned b=col.blue(); unsigned a=col.alpha(); renderer ren(renb); ras_ptr->reset(); ras_ptr->gamma(agg::gamma_linear()); agg::scanline_p8 sl; metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;i<feature.num_geometries();++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 1) { path_type path(t_,geom,prj_trans); if (stroke_.has_dash()) { agg::conv_dash<path_type> dash(path); dash_array const& d = stroke_.get_dash_array(); dash_array::const_iterator itr = d.begin(); dash_array::const_iterator end = d.end(); for (;itr != end;++itr) { dash.add_dash(itr->first * scale_factor_, itr->second * scale_factor_); } agg::conv_stroke<agg::conv_dash<path_type > > stroke(dash); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); } else { agg::conv_stroke<path_type> stroke(path); line_join_e join=stroke_.get_line_join(); if ( join == MITER_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == MITER_REVERT_JOIN) stroke.generator().line_join(agg::miter_join); else if( join == ROUND_JOIN) stroke.generator().line_join(agg::round_join); else stroke.generator().line_join(agg::bevel_join); line_cap_e cap=stroke_.get_line_cap(); if (cap == BUTT_CAP) stroke.generator().line_cap(agg::butt_cap); else if (cap == SQUARE_CAP) stroke.generator().line_cap(agg::square_cap); else stroke.generator().line_cap(agg::round_cap); stroke.generator().miter_limit(4.0); stroke.generator().width(stroke_.get_width() * scale_factor_); ras_ptr->add_path(stroke); if (writer.first) writer.first->add_line(path, feature, t_, writer.second); } } } ren.color(agg::rgba8(r, g, b, int(a*stroke_.get_opacity()))); agg::render_scanlines(*ras_ptr, sl, ren); }
void agg_renderer<T>::process(polygon_pattern_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; typedef agg::renderer_base<agg::pixfmt_rgba32_plain> ren_base; typedef agg::wrap_mode_repeat wrap_x_type; typedef agg::wrap_mode_repeat wrap_y_type; typedef agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32, agg::row_accessor<agg::int8u>, agg::pixel32_type> rendering_buffer; typedef agg::image_accessor_wrap<rendering_buffer, wrap_x_type, wrap_y_type> img_source_type; typedef agg::span_pattern_rgba<img_source_type> span_gen_type; typedef agg::renderer_scanline_aa<ren_base, agg::span_allocator<agg::rgba8>, span_gen_type> renderer_type; agg::rendering_buffer buf(pixmap_.raw_data(),width_,height_, width_ * 4); agg::pixfmt_rgba32_plain pixf(buf); ren_base renb(pixf); agg::scanline_u8 sl; ras_ptr->reset(); ras_ptr->gamma(agg::gamma_linear(0.0, sym.get_gamma())); std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); boost::optional<mapnik::marker_ptr> marker; if ( !filename.empty() ) { marker = marker_cache::instance()->find(filename, true); } else { std::clog << "### Warning: file not found: " << filename << "\n"; } if (!marker || !(*marker)->is_bitmap()) return; boost::optional<image_ptr> pat = (*marker)->get_bitmap_data(); if (!pat) return; unsigned w=(*pat)->width(); unsigned h=(*pat)->height(); agg::row_accessor<agg::int8u> pattern_rbuf((agg::int8u*)(*pat)->getBytes(),w,h,w*4); agg::span_allocator<agg::rgba8> sa; agg::pixfmt_alpha_blend_rgba<agg::blender_rgba32, agg::row_accessor<agg::int8u>, agg::pixel32_type> pixf_pattern(pattern_rbuf); img_source_type img_src(pixf_pattern); unsigned num_geometries = feature.num_geometries(); pattern_alignment_e align = sym.get_alignment(); unsigned offset_x=0; unsigned offset_y=0; if (align == LOCAL_ALIGNMENT) { double x0=0,y0=0; if (num_geometries>0) { path_type path(t_,feature.get_geometry(0),prj_trans); path.vertex(&x0,&y0); } offset_x = unsigned(width_-x0); offset_y = unsigned(height_-y0); } span_gen_type sg(img_src, offset_x, offset_y); renderer_type rp(renb,sa, sg); metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i=0;i<num_geometries;++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 2) { path_type path(t_,geom,prj_trans); ras_ptr->add_path(path); if (writer.first) writer.first->add_polygon(path, feature, t_, writer.second); } } agg::render_scanlines(*ras_ptr, sl, rp); }
void grid_renderer<T>::process(text_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; bool placement_found = false; text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info(); while (!placement_found && placement_options->next()) { expression_ptr name_expr = sym.get_name(); if (!name_expr) return; value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr); UnicodeString text = result.to_unicode(); if ( sym.get_text_transform() == UPPERCASE) { text = text.toUpper(); } else if ( sym.get_text_transform() == LOWERCASE) { text = text.toLower(); } else if ( sym.get_text_transform() == CAPITALIZE) { text = text.toTitle(NULL); } if ( text.length() <= 0 ) continue; color const& fill = sym.get_fill(); face_set_ptr faces; if (sym.get_fontset().size() > 0) { faces = font_manager_.get_face_set(sym.get_fontset()); } else { faces = font_manager_.get_face_set(sym.get_face_name()); } stroker_ptr strk = font_manager_.get_stroker(); if (!(faces->size() > 0 && strk)) { throw config_error("Unable to find specified font face '" + sym.get_face_name() + "'"); } text_renderer<T> ren(pixmap_, faces, *strk); ren.set_pixel_size(placement_options->text_size * (scale_factor_ * (1.0/pixmap_.get_resolution()))); ren.set_fill(fill); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); ren.set_opacity(sym.get_text_opacity()); // /pixmap_.get_resolution() ? box2d<double> dims(0,0,width_,height_); placement_finder<label_collision_detector4> finder(detector_,dims); string_info info(text); faces->get_string_info(info); unsigned num_geom = feature.num_geometries(); for (unsigned i=0; i<num_geom; ++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() == 0) continue; // don't bother with empty geometries while (!placement_found && placement_options->next_position_only()) { placement text_placement(info, sym, scale_factor_); text_placement.avoid_edges = sym.get_avoid_edges(); if (sym.get_label_placement() == POINT_PLACEMENT || sym.get_label_placement() == INTERIOR_PLACEMENT) { double label_x, label_y, z=0.0; if (sym.get_label_placement() == POINT_PLACEMENT) geom.label_position(&label_x, &label_y); else geom.label_interior_position(&label_x, &label_y); prj_trans.backward(label_x,label_y, z); t_.forward(&label_x,&label_y); double angle = 0.0; expression_ptr angle_expr = sym.get_orientation(); if (angle_expr) { // apply rotation value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*angle_expr); angle = result.to_double(); } finder.find_point_placement(text_placement, placement_options, label_x, label_y, angle, sym.get_line_spacing(), sym.get_character_spacing()); finder.update_detector(text_placement); } else if ( geom.num_points() > 1 && sym.get_label_placement() == LINE_PLACEMENT) { path_type path(t_,geom,prj_trans); finder.find_line_placements<path_type>(text_placement, placement_options, path); } if (!text_placement.placements.size()) continue; placement_found = true; for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ii) { double x = text_placement.placements[ii].starting_x; double y = text_placement.placements[ii].starting_y; ren.prepare_glyphs(&text_placement.placements[ii]); ren.render_id(feature.id(),x,y,2); } } } } if (placement_found) pixmap_.add_feature(feature); }
void agg_renderer<T>::process(shield_symbolizer const& sym, Feature const& feature, proj_transform const& prj_trans) { typedef coord_transform2<CoordTransform,geometry_type> path_type; text_placement_info_ptr placement_options = sym.get_placement_options()->get_placement_info(); placement_options->next(); placement_options->next_position_only(); UnicodeString text; if( sym.get_no_text() ) text = UnicodeString( " " ); // TODO: fix->use 'space' as the text to render else { expression_ptr name_expr = sym.get_name(); if (!name_expr) return; value_type result = boost::apply_visitor(evaluate<Feature,value_type>(feature),*name_expr); text = result.to_unicode(); } if ( sym.get_text_transform() == UPPERCASE) { text = text.toUpper(); } else if ( sym.get_text_transform() == LOWERCASE) { text = text.toLower(); } else if ( sym.get_text_transform() == CAPITALIZE) { text = text.toTitle(NULL); } agg::trans_affine tr; boost::array<double,6> const& m = sym.get_transform(); tr.load_from(&m[0]); std::string filename = path_processor_type::evaluate( *sym.get_filename(), feature); boost::optional<mapnik::marker_ptr> marker; if ( !filename.empty() ) { marker = marker_cache::instance()->find(filename, true); } else { marker.reset(boost::make_shared<mapnik::marker>()); } if (text.length() > 0 && marker) { int w = (*marker)->width(); int h = (*marker)->height(); double px0 = - 0.5 * w; double py0 = - 0.5 * h; double px1 = 0.5 * w; double py1 = 0.5 * h; double px2 = px1; double py2 = py0; double px3 = px0; double py3 = py1; tr.transform(&px0,&py0); tr.transform(&px1,&py1); tr.transform(&px2,&py2); tr.transform(&px3,&py3); box2d<double> label_ext (px0, py0, px1, py1); label_ext.expand_to_include(px2, py2); label_ext.expand_to_include(px3, py3); face_set_ptr faces; if (sym.get_fontset().size() > 0) { faces = font_manager_.get_face_set(sym.get_fontset()); } else { faces = font_manager_.get_face_set(sym.get_face_name()); } stroker_ptr strk = font_manager_.get_stroker(); if (strk && faces->size() > 0) { text_renderer<T> ren(pixmap_, faces, *strk); ren.set_pixel_size(sym.get_text_size() * scale_factor_); ren.set_fill(sym.get_fill()); ren.set_halo_fill(sym.get_halo_fill()); ren.set_halo_radius(sym.get_halo_radius() * scale_factor_); ren.set_opacity(sym.get_text_opacity()); placement_finder<label_collision_detector4> finder(detector_); string_info info(text); faces->get_string_info(info); metawriter_with_properties writer = sym.get_metawriter(); for (unsigned i = 0; i < feature.num_geometries(); ++i) { geometry_type const& geom = feature.get_geometry(i); if (geom.num_points() > 0 ) { path_type path(t_,geom,prj_trans); label_placement_enum how_placed = sym.get_label_placement(); if (how_placed == POINT_PLACEMENT || how_placed == VERTEX_PLACEMENT || how_placed == INTERIOR_PLACEMENT) { // for every vertex, try and place a shield/text geom.rewind(0); placement text_placement(info, sym, scale_factor_, w, h, false); text_placement.avoid_edges = sym.get_avoid_edges(); text_placement.allow_overlap = sym.get_allow_overlap(); if (writer.first) text_placement.collect_extents =true; // needed for inmem metawriter position const& pos = sym.get_displacement(); position const& shield_pos = sym.get_shield_displacement(); for( unsigned jj = 0; jj < geom.num_points(); jj++ ) { double label_x; double label_y; double z=0.0; if( how_placed == VERTEX_PLACEMENT ) geom.vertex(&label_x,&label_y); // by vertex else if( how_placed == INTERIOR_PLACEMENT ) geom.label_interior_position(&label_x,&label_y); else geom.label_position(&label_x, &label_y); // by middle of line or by point prj_trans.backward(label_x,label_y, z); t_.forward(&label_x,&label_y); label_x += boost::get<0>(shield_pos); label_y += boost::get<1>(shield_pos); finder.find_point_placement( text_placement, placement_options, label_x, label_y, 0.0, sym.get_line_spacing(), sym.get_character_spacing()); // check to see if image overlaps anything too, there is only ever 1 placement found for points and verticies if( text_placement.placements.size() > 0) { double x = floor(text_placement.placements[0].starting_x); double y = floor(text_placement.placements[0].starting_y); int px; int py; if( !sym.get_unlock_image() ) { // center image at text center position // remove displacement from image label double lx = x - boost::get<0>(pos); double ly = y - boost::get<1>(pos); px=int(floor(lx - (0.5 * w))) + 1; py=int(floor(ly - (0.5 * h))) + 1; label_ext.re_center(lx,ly); } else { // center image at reference location px=int(floor(label_x - 0.5 * w)); py=int(floor(label_y - 0.5 * h)); label_ext.re_center(label_x,label_y); } if ( sym.get_allow_overlap() || detector_.has_placement(label_ext) ) { render_marker(px,py,**marker,tr,sym.get_opacity()); box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[0]); ren.render(x,y); detector_.insert(label_ext); finder.update_detector(text_placement); if (writer.first) { writer.first->add_box(label_ext, feature, t_, writer.second); writer.first->add_text(text_placement, faces, feature, t_, writer.second); } } } } } else if (geom.num_points() > 1 && how_placed == LINE_PLACEMENT) { placement text_placement(info, sym, scale_factor_, w, h, false); position const& pos = sym.get_displacement(); text_placement.avoid_edges = sym.get_avoid_edges(); text_placement.additional_boxes.push_back( box2d<double>(-0.5 * label_ext.width() - boost::get<0>(pos), -0.5 * label_ext.height() - boost::get<1>(pos), 0.5 * label_ext.width() - boost::get<0>(pos), 0.5 * label_ext.height() - boost::get<1>(pos))); finder.find_point_placements<path_type>(text_placement, placement_options, path); for (unsigned int ii = 0; ii < text_placement.placements.size(); ++ ii) { double x = floor(text_placement.placements[ii].starting_x); double y = floor(text_placement.placements[ii].starting_y); double lx = x - boost::get<0>(pos); double ly = y - boost::get<1>(pos); int px=int(floor(lx - (0.5*w))) + 1; int py=int(floor(ly - (0.5*h))) + 1; label_ext.re_center(lx, ly); render_marker(px,py,**marker,tr,sym.get_opacity()); box2d<double> dim = ren.prepare_glyphs(&text_placement.placements[ii]); ren.render(x,y); if (writer.first) writer.first->add_box(label_ext, feature, t_, writer.second); } finder.update_detector(text_placement); if (writer.first) writer.first->add_text(text_placement, faces, feature, t_, writer.second); } } } } } }