allow setting marker width/height together with transform
This commit is contained in:
parent
3d048c5f72
commit
7a5f06656c
5 changed files with 289 additions and 11 deletions
279
include/mapnik/grid/grid_marker_helpers.hpp
Normal file
279
include/mapnik/grid/grid_marker_helpers.hpp
Normal file
|
@ -0,0 +1,279 @@
|
||||||
|
/*****************************************************************************
|
||||||
|
*
|
||||||
|
* This file is part of Mapnik (c++ mapping toolkit)
|
||||||
|
*
|
||||||
|
* Copyright (C) 2012 Artem Pavlenko
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2.1 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, write to the Free Software
|
||||||
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
*
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||||
|
#define MAPNIK_GRID_MARKER_HELPERS_HPP
|
||||||
|
|
||||||
|
// mapnik
|
||||||
|
#include <mapnik/markers_symbolizer.hpp>
|
||||||
|
#include <mapnik/markers_placement.hpp>
|
||||||
|
|
||||||
|
// agg
|
||||||
|
#include "agg_renderer_scanline.h"
|
||||||
|
#include "agg_scanline_bin.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_gray.h"
|
||||||
|
|
||||||
|
|
||||||
|
namespace mapnik {
|
||||||
|
|
||||||
|
template <typename BufferType, typename Rasterizer, typename PixFmt, typename RendererBase, typename RendererType, typename Detector, typename PixMapType>
|
||||||
|
struct raster_markers_rasterizer_dispatch_grid
|
||||||
|
{
|
||||||
|
typedef mapnik::gray32 color_type;
|
||||||
|
typedef typename RendererBase::pixfmt_type pixfmt_type;
|
||||||
|
|
||||||
|
raster_markers_rasterizer_dispatch_grid(BufferType & render_buffer,
|
||||||
|
Rasterizer & ras,
|
||||||
|
image_data_32 const& src,
|
||||||
|
agg::trans_affine const& marker_trans,
|
||||||
|
markers_symbolizer const& sym,
|
||||||
|
Detector & detector,
|
||||||
|
double scale_factor,
|
||||||
|
mapnik::feature_impl & feature,
|
||||||
|
PixMapType & pixmap)
|
||||||
|
: buf_(render_buffer),
|
||||||
|
pixf_(buf_),
|
||||||
|
renb_(pixf_),
|
||||||
|
ras_(ras),
|
||||||
|
src_(src),
|
||||||
|
marker_trans_(marker_trans),
|
||||||
|
sym_(sym),
|
||||||
|
detector_(detector),
|
||||||
|
scale_factor_(scale_factor),
|
||||||
|
feature_(feature),
|
||||||
|
pixmap_(pixmap),
|
||||||
|
placed_(false)
|
||||||
|
{
|
||||||
|
// TODO - support basic binary operators
|
||||||
|
//pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void add_path(T & path)
|
||||||
|
{
|
||||||
|
marker_placement_e placement_method = sym_.get_marker_placement();
|
||||||
|
box2d<double> bbox_(0,0, src_.width(),src_.height());
|
||||||
|
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||||
|
{
|
||||||
|
double x,y;
|
||||||
|
path.rewind(0);
|
||||||
|
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||||
|
{
|
||||||
|
label::interior_position(path, x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label::centroid(path, x, y);
|
||||||
|
}
|
||||||
|
agg::trans_affine matrix = marker_trans_;
|
||||||
|
matrix.translate(x,y);
|
||||||
|
box2d<double> transformed_bbox = bbox_ * matrix;
|
||||||
|
if (sym_.get_allow_overlap() ||
|
||||||
|
detector_.has_placement(transformed_bbox))
|
||||||
|
{
|
||||||
|
render_raster_marker(matrix);
|
||||||
|
if (!sym_.get_ignore_placement())
|
||||||
|
{
|
||||||
|
detector_.insert(transformed_bbox);
|
||||||
|
}
|
||||||
|
if (!placed_)
|
||||||
|
{
|
||||||
|
pixmap_.add_feature(feature_);
|
||||||
|
placed_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
markers_placement<T, label_collision_detector4> placement(path, 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))
|
||||||
|
{
|
||||||
|
agg::trans_affine matrix = marker_trans_;
|
||||||
|
matrix.rotate(angle);
|
||||||
|
matrix.translate(x, y);
|
||||||
|
render_raster_marker(matrix);
|
||||||
|
if (!placed_)
|
||||||
|
{
|
||||||
|
pixmap_.add_feature(feature_);
|
||||||
|
placed_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void render_raster_marker(agg::trans_affine const& marker_tr)
|
||||||
|
{
|
||||||
|
double width = src_.width();
|
||||||
|
double height = src_.height();
|
||||||
|
double p[8];
|
||||||
|
p[0] = 0; p[1] = 0;
|
||||||
|
p[2] = width; p[3] = 0;
|
||||||
|
p[4] = width; p[5] = height;
|
||||||
|
p[6] = 0; p[7] = height;
|
||||||
|
marker_tr.transform(&p[0], &p[1]);
|
||||||
|
marker_tr.transform(&p[2], &p[3]);
|
||||||
|
marker_tr.transform(&p[4], &p[5]);
|
||||||
|
marker_tr.transform(&p[6], &p[7]);
|
||||||
|
ras_.move_to_d(p[0],p[1]);
|
||||||
|
ras_.line_to_d(p[2],p[3]);
|
||||||
|
ras_.line_to_d(p[4],p[5]);
|
||||||
|
ras_.line_to_d(p[6],p[7]);
|
||||||
|
RendererType ren(renb_);
|
||||||
|
ren.color(mapnik::gray32(feature_.id()));
|
||||||
|
agg::render_scanlines(ras_, sl_, ren);
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
agg::scanline_bin sl_;
|
||||||
|
BufferType & buf_;
|
||||||
|
PixFmt pixf_;
|
||||||
|
RendererBase renb_;
|
||||||
|
Rasterizer & ras_;
|
||||||
|
image_data_32 const& src_;
|
||||||
|
agg::trans_affine const& marker_trans_;
|
||||||
|
markers_symbolizer const& sym_;
|
||||||
|
Detector & detector_;
|
||||||
|
double scale_factor_;
|
||||||
|
mapnik::feature_impl & feature_;
|
||||||
|
PixMapType & pixmap_;
|
||||||
|
bool placed_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename BufferType, typename SvgRenderer, typename Rasterizer, typename Detector, typename PixMapType>
|
||||||
|
struct vector_markers_rasterizer_dispatch_grid
|
||||||
|
{
|
||||||
|
typedef typename SvgRenderer::renderer_base renderer_base;
|
||||||
|
typedef typename renderer_base::pixfmt_type pixfmt_type;
|
||||||
|
|
||||||
|
vector_markers_rasterizer_dispatch_grid(BufferType & render_buffer,
|
||||||
|
SvgRenderer & svg_renderer,
|
||||||
|
Rasterizer & ras,
|
||||||
|
box2d<double> const& bbox,
|
||||||
|
agg::trans_affine const& marker_trans,
|
||||||
|
markers_symbolizer const& sym,
|
||||||
|
Detector & detector,
|
||||||
|
double scale_factor,
|
||||||
|
mapnik::feature_impl & feature,
|
||||||
|
PixMapType & pixmap)
|
||||||
|
: buf_(render_buffer),
|
||||||
|
pixf_(buf_),
|
||||||
|
renb_(pixf_),
|
||||||
|
svg_renderer_(svg_renderer),
|
||||||
|
ras_(ras),
|
||||||
|
bbox_(bbox),
|
||||||
|
marker_trans_(marker_trans),
|
||||||
|
sym_(sym),
|
||||||
|
detector_(detector),
|
||||||
|
scale_factor_(scale_factor),
|
||||||
|
feature_(feature),
|
||||||
|
pixmap_(pixmap),
|
||||||
|
placed_(false)
|
||||||
|
{
|
||||||
|
// TODO
|
||||||
|
//pixf_.comp_op(static_cast<agg::comp_op_e>(sym_.comp_op()));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
void add_path(T & path)
|
||||||
|
{
|
||||||
|
marker_placement_e placement_method = sym_.get_marker_placement();
|
||||||
|
if (placement_method != MARKER_LINE_PLACEMENT)
|
||||||
|
{
|
||||||
|
double x,y;
|
||||||
|
path.rewind(0);
|
||||||
|
if (placement_method == MARKER_INTERIOR_PLACEMENT)
|
||||||
|
{
|
||||||
|
label::interior_position(path, x, y);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
label::centroid(path, x, y);
|
||||||
|
}
|
||||||
|
agg::trans_affine matrix = marker_trans_;
|
||||||
|
matrix.translate(x,y);
|
||||||
|
box2d<double> transformed_bbox = bbox_ * matrix;
|
||||||
|
if (sym_.get_allow_overlap() ||
|
||||||
|
detector_.has_placement(transformed_bbox))
|
||||||
|
{
|
||||||
|
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, sym_.get_opacity(), bbox_);
|
||||||
|
if (!sym_.get_ignore_placement())
|
||||||
|
{
|
||||||
|
detector_.insert(transformed_bbox);
|
||||||
|
}
|
||||||
|
if (!placed_)
|
||||||
|
{
|
||||||
|
pixmap_.add_feature(feature_);
|
||||||
|
placed_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
markers_placement<T, Detector> placement(path, 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))
|
||||||
|
{
|
||||||
|
agg::trans_affine matrix = marker_trans_;
|
||||||
|
matrix.rotate(angle);
|
||||||
|
matrix.translate(x, y);
|
||||||
|
svg_renderer_.render_id(ras_, sl_, renb_, feature_.id(), matrix, sym_.get_opacity(), bbox_);
|
||||||
|
if (!placed_)
|
||||||
|
{
|
||||||
|
pixmap_.add_feature(feature_);
|
||||||
|
placed_ = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
agg::scanline_bin sl_;
|
||||||
|
BufferType & buf_;
|
||||||
|
pixfmt_type pixf_;
|
||||||
|
renderer_base renb_;
|
||||||
|
SvgRenderer & svg_renderer_;
|
||||||
|
Rasterizer & ras_;
|
||||||
|
box2d<double> const& bbox_;
|
||||||
|
agg::trans_affine const& marker_trans_;
|
||||||
|
markers_symbolizer const& sym_;
|
||||||
|
Detector & detector_;
|
||||||
|
double scale_factor_;
|
||||||
|
mapnik::feature_impl & feature_;
|
||||||
|
PixMapType & pixmap_;
|
||||||
|
bool placed_;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -359,7 +359,7 @@ bool push_explicit_style(Attr const& src, Attr & dst, markers_symbolizer const&
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
void setup_label_transform(agg::trans_affine & tr, box2d<double> const& bbox, mapnik::feature_impl const& feature, T const& sym)
|
void setup_transform_scaling(agg::trans_affine & tr, box2d<double> const& bbox, mapnik::feature_impl const& feature, T const& sym)
|
||||||
{
|
{
|
||||||
double width = 0;
|
double width = 0;
|
||||||
double height = 0;
|
double height = 0;
|
||||||
|
@ -388,10 +388,6 @@ void setup_label_transform(agg::trans_affine & tr, box2d<double> const& bbox, ma
|
||||||
double sy = height/bbox.height();
|
double sy = height/bbox.height();
|
||||||
tr *= agg::trans_affine_scaling(sy);
|
tr *= agg::trans_affine_scaling(sy);
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
evaluate_transform(tr, feature, sym.get_image_transform());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -82,8 +82,7 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
ras_ptr->gamma(agg::gamma_power());
|
ras_ptr->gamma(agg::gamma_power());
|
||||||
agg::trans_affine geom_tr;
|
agg::trans_affine geom_tr;
|
||||||
evaluate_transform(geom_tr, feature, sym.get_transform());
|
evaluate_transform(geom_tr, feature, sym.get_transform());
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr = agg::trans_affine_scaling(scale_factor_);
|
||||||
tr *= agg::trans_affine_scaling(scale_factor_);
|
|
||||||
|
|
||||||
if ((*mark)->is_vector())
|
if ((*mark)->is_vector())
|
||||||
{
|
{
|
||||||
|
@ -144,7 +143,8 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
box2d<double> const& bbox = (*mark)->bounding_box();
|
box2d<double> const& bbox = (*mark)->bounding_box();
|
||||||
setup_label_transform(tr, bbox, feature, sym);
|
setup_transform_scaling(tr, bbox, feature, sym);
|
||||||
|
evaluate_transform(tr, feature, sym.get_image_transform());
|
||||||
coord2d center = bbox.center();
|
coord2d center = bbox.center();
|
||||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||||
agg::trans_affine marker_trans = recenter * tr;
|
agg::trans_affine marker_trans = recenter * tr;
|
||||||
|
@ -179,7 +179,8 @@ void agg_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
else // raster markers
|
else // raster markers
|
||||||
{
|
{
|
||||||
box2d<double> const& bbox = (*mark)->bounding_box();
|
box2d<double> const& bbox = (*mark)->bounding_box();
|
||||||
setup_label_transform(tr, bbox, feature, sym);
|
setup_transform_scaling(tr, bbox, feature, sym);
|
||||||
|
evaluate_transform(tr, feature, sym.get_image_transform());
|
||||||
coord2d center = bbox.center();
|
coord2d center = bbox.center();
|
||||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||||
agg::trans_affine marker_trans = recenter * tr;
|
agg::trans_affine marker_trans = recenter * tr;
|
||||||
|
|
|
@ -1628,7 +1628,8 @@ void cairo_renderer_base::process(markers_symbolizer const& sym,
|
||||||
agg::trans_affine geom_tr;
|
agg::trans_affine geom_tr;
|
||||||
evaluate_transform(geom_tr, feature, sym.get_transform());
|
evaluate_transform(geom_tr, feature, sym.get_transform());
|
||||||
box2d<double> const& bbox = (*mark)->bounding_box();
|
box2d<double> const& bbox = (*mark)->bounding_box();
|
||||||
setup_label_transform(tr, bbox, feature, sym);
|
setup_transform_scaling(tr, bbox, feature, sym);
|
||||||
|
evaluate_transform(tr, feature, sym.get_image_transform());
|
||||||
|
|
||||||
if ((*mark)->is_vector())
|
if ((*mark)->is_vector())
|
||||||
{
|
{
|
||||||
|
|
|
@ -129,7 +129,8 @@ void grid_renderer<T>::process(markers_symbolizer const& sym,
|
||||||
box2d<double> const& bbox = (*marker)->bounding_box();
|
box2d<double> const& bbox = (*marker)->bounding_box();
|
||||||
|
|
||||||
agg::trans_affine tr;
|
agg::trans_affine tr;
|
||||||
setup_label_transform(tr, bbox, feature, sym);
|
setup_transform_scaling(tr, bbox, feature, sym);
|
||||||
|
evaluate_transform(tr, feature, sym.get_image_transform());
|
||||||
// - clamp sizes to > 4 pixels of interactivity
|
// - clamp sizes to > 4 pixels of interactivity
|
||||||
if (tr.scale() < 0.5)
|
if (tr.scale() < 0.5)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue