void apply_markers_multi(feature_impl const& feature, attributes const& vars, Converter & converter, markers_symbolizer const& sym) { std::size_t geom_count = feature.paths().size(); if (geom_count == 1) { converter.apply(feature.paths()[0]); } else if (geom_count > 1) { marker_multi_policy_enum multi_policy = get<marker_multi_policy_enum>(sym, keys::markers_multipolicy, feature, vars, MARKER_EACH_MULTI); marker_placement_enum placement = get<marker_placement_enum>(sym, keys::markers_placement_type, feature, vars, MARKER_POINT_PLACEMENT); if (placement == MARKER_POINT_PLACEMENT && multi_policy == MARKER_WHOLE_MULTI) { double x, y; if (label::centroid_geoms(feature.paths().begin(), feature.paths().end(), x, y)) { geometry_type pt(geometry_type::types::Point); pt.move_to(x, y); // unset any clipping since we're now dealing with a point converter.template unset<clip_poly_tag>(); converter.apply(pt); } } else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT) && multi_policy == MARKER_LARGEST_MULTI) { // Only apply to path with largest envelope area // TODO: consider using true area for polygon types double maxarea = 0; geometry_type const* largest = 0; for (geometry_type const& geom : feature.paths()) { const box2d<double>& env = geom.envelope(); double area = env.width() * env.height(); if (area > maxarea) { maxarea = area; largest = &geom; } } if (largest) { converter.apply(*largest); } } else { if (multi_policy != MARKER_EACH_MULTI && placement != MARKER_POINT_PLACEMENT) { MAPNIK_LOG_WARN(marker_symbolizer) << "marker_multi_policy != 'each' has no effect with marker_placement != 'point'"; } for (geometry_type const& path : feature.paths()) { converter.apply(path); } } } }
void apply_markers_multi(feature_impl const& feature, attributes const& vars, Converter & converter, symbolizer_base const& sym) { using vertex_converter_type = Converter; using apply_vertex_converter_type = detail::apply_vertex_converter<vertex_converter_type>; using vertex_processor_type = geometry::vertex_processor<apply_vertex_converter_type>; auto const& geom = feature.get_geometry(); geometry::geometry_types type = geometry::geometry_type(geom); if (type == geometry::geometry_types::Point || type == geometry::geometry_types::LineString || type == geometry::geometry_types::Polygon) { apply_vertex_converter_type apply(converter); mapnik::util::apply_visitor(vertex_processor_type(apply), geom); } else { marker_multi_policy_enum multi_policy = get<marker_multi_policy_enum, keys::markers_multipolicy>(sym, feature, vars); marker_placement_enum placement = get<marker_placement_enum, keys::markers_placement_type>(sym, feature, vars); if (placement == MARKER_POINT_PLACEMENT && multi_policy == MARKER_WHOLE_MULTI) { geometry::point<double> pt; // test if centroid is contained by bounding box if (geometry::centroid(geom, pt) && converter.disp_.args_.bbox.contains(pt.x, pt.y)) { // unset any clipping since we're now dealing with a point converter.template unset<clip_poly_tag>(); geometry::point_vertex_adapter<double> va(pt); converter.apply(va); } } else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT) && multi_policy == MARKER_LARGEST_MULTI) { // Only apply to path with largest envelope area // TODO: consider using true area for polygon types if (type == geometry::geometry_types::MultiPolygon) { geometry::multi_polygon<double> const& multi_poly = mapnik::util::get<geometry::multi_polygon<double> >(geom); double maxarea = 0; geometry::polygon<double> const* largest = 0; for (geometry::polygon<double> const& poly : multi_poly) { box2d<double> bbox = geometry::envelope(poly); geometry::polygon_vertex_adapter<double> va(poly); double area = bbox.width() * bbox.height(); if (area > maxarea) { maxarea = area; largest = &poly; } } if (largest) { geometry::polygon_vertex_adapter<double> va(*largest); converter.apply(va); } } else { MAPNIK_LOG_WARN(marker_symbolizer) << "TODO: if you get here -> open an issue"; } } else { if (multi_policy != MARKER_EACH_MULTI && placement != MARKER_POINT_PLACEMENT) { MAPNIK_LOG_WARN(marker_symbolizer) << "marker_multi_policy != 'each' has no effect with marker_placement != 'point'"; } apply_vertex_converter_type apply(converter); mapnik::util::apply_visitor(vertex_processor_type(apply), geom); } } }