Merge pull request #2388 from mapycz/3.x-refactor-markers-placement
refactor marker placements
This commit is contained in:
commit
4ebf1ae114
9 changed files with 68 additions and 167 deletions
|
@ -83,15 +83,9 @@ struct raster_markers_rasterizer_dispatch_grid : mapnik::noncopyable
|
|||
box2d<double> bbox(0,0, src_.width(), src_.height());
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
markers_placement_params params { bbox, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox,
|
||||
marker_trans_,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
@ -200,15 +194,9 @@ struct vector_markers_rasterizer_dispatch_grid : mapnik::noncopyable
|
|||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, Detector> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox_,
|
||||
marker_trans_,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
|
|
@ -117,15 +117,9 @@ struct vector_markers_rasterizer_dispatch : mapnik::noncopyable
|
|||
coord2d center = bbox_.center();
|
||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||
agg::trans_affine tr = recenter * marker_trans_;
|
||||
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, Detector> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox_,
|
||||
tr,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
@ -206,15 +200,9 @@ struct raster_markers_rasterizer_dispatch : mapnik::noncopyable
|
|||
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
|
||||
double spacing = get<double>(sym_, keys::spacing, feature_, vars_, 100.0);
|
||||
double max_error = get<double>(sym_, keys::max_error, feature_, vars_, 0.2);
|
||||
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox_,
|
||||
marker_trans_,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
|
|
@ -67,13 +67,9 @@ public:
|
|||
|
||||
markers_placement_finder(marker_placement_e placement_type,
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
: placement_(create(placement_type, locator, size, tr, detector, spacing, max_error, allow_overlap))
|
||||
markers_placement_params const& params)
|
||||
: placement_(create(placement_type, locator, detector, params))
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -87,21 +83,13 @@ private:
|
|||
// Factory function for particular placement implementations.
|
||||
static markers_placement create(marker_placement_e placement_type,
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
markers_placement_params const& params)
|
||||
{
|
||||
static const std::map<marker_placement_e, boost::function<markers_placement(
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)>> factories =
|
||||
markers_placement_params const& params)>> factories =
|
||||
{
|
||||
{ MARKER_POINT_PLACEMENT, boost::value_factory<markers_point_placement<Locator, Detector>>() },
|
||||
{ MARKER_INTERIOR_PLACEMENT, boost::value_factory<markers_interior_placement<Locator, Detector>>() },
|
||||
|
@ -109,7 +97,7 @@ private:
|
|||
{ MARKER_VERTEX_FIRST_PLACEMENT, boost::value_factory<markers_vertex_first_placement<Locator, Detector>>() },
|
||||
{ MARKER_VERTEX_LAST_PLACEMENT, boost::value_factory<markers_vertex_last_placement<Locator, Detector>>() }
|
||||
};
|
||||
return factories.at(placement_type)(locator, size, tr, detector, spacing, max_error, allow_overlap);
|
||||
return factories.at(placement_type)(locator, detector, params);
|
||||
}
|
||||
|
||||
markers_placement placement_;
|
||||
|
|
|
@ -32,17 +32,8 @@ template <typename Locator, typename Detector>
|
|||
class markers_interior_placement : public markers_point_placement<Locator, Detector>
|
||||
{
|
||||
public:
|
||||
markers_interior_placement(
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
: markers_point_placement<Locator, Detector>(
|
||||
locator, size, tr, detector,
|
||||
spacing, max_error, allow_overlap)
|
||||
markers_interior_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
|
||||
: markers_point_placement<Locator, Detector>(locator, detector, params)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -79,7 +70,7 @@ public:
|
|||
|
||||
box2d<double> box = this->perform_transform(angle, x, y);
|
||||
|
||||
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
|
||||
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -36,32 +36,18 @@ template <typename Locator, typename Detector>
|
|||
class markers_line_placement : public markers_point_placement<Locator, Detector>
|
||||
{
|
||||
public:
|
||||
markers_line_placement(Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
: markers_point_placement<Locator, Detector>(
|
||||
locator, size, tr, detector,
|
||||
spacing, max_error, allow_overlap),
|
||||
last_x(0.0),
|
||||
last_y(0.0),
|
||||
next_x(0.0),
|
||||
next_y(0.0),
|
||||
error_(0.0),
|
||||
spacing_left_(0.0),
|
||||
marker_nr_(0)
|
||||
markers_line_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
|
||||
: markers_point_placement<Locator, Detector>(locator, detector, params),
|
||||
marker_width_((params.size * params.tr).width()),
|
||||
last_x(0.0),
|
||||
last_y(0.0),
|
||||
next_x(0.0),
|
||||
next_y(0.0),
|
||||
error_(0.0),
|
||||
spacing_left_(0.0),
|
||||
marker_nr_(0)
|
||||
{
|
||||
if (spacing >= 1)
|
||||
{
|
||||
this->spacing_ = spacing;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->spacing_ = 100;
|
||||
}
|
||||
spacing_ = params.spacing < 1 ? 100 : params.spacing;
|
||||
rewind();
|
||||
}
|
||||
|
||||
|
@ -103,31 +89,31 @@ public:
|
|||
{
|
||||
//First marker
|
||||
marker_nr_++;
|
||||
this->spacing_left_ = this->spacing_ / 2;
|
||||
spacing_left_ = spacing_ / 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
this->spacing_left_ = this->spacing_;
|
||||
spacing_left_ = spacing_;
|
||||
}
|
||||
spacing_left_ -= error_;
|
||||
error_ = 0.0;
|
||||
double max_err_allowed = this->max_error_ * this->spacing_;
|
||||
double max_err_allowed = this->params_.max_error * spacing_;
|
||||
//Loop exits when a position is found or when no more segments are available
|
||||
while (true)
|
||||
{
|
||||
//Do not place markers too close to the beginning of a segment
|
||||
if (spacing_left_ < this->marker_width_/2)
|
||||
if (spacing_left_ < this->marker_width_ / 2)
|
||||
{
|
||||
set_spacing_left(this->marker_width_/2); //Only moves forward
|
||||
set_spacing_left(this->marker_width_ / 2); //Only moves forward
|
||||
}
|
||||
//Error for this marker is too large. Skip to the next position.
|
||||
if (std::fabs(error_) > max_err_allowed)
|
||||
{
|
||||
while (this->error_ > this->spacing_)
|
||||
while (this->error_ > spacing_)
|
||||
{
|
||||
error_ -= this->spacing_; //Avoid moving backwards
|
||||
error_ -= spacing_; //Avoid moving backwards
|
||||
}
|
||||
spacing_left_ += this->spacing_ - this->error_;
|
||||
spacing_left_ += spacing_ - this->error_;
|
||||
error_ = 0.0;
|
||||
}
|
||||
double dx = next_x - last_x;
|
||||
|
@ -185,10 +171,10 @@ public:
|
|||
x = last_x + dx * (spacing_left_ / segment_length);
|
||||
y = last_y + dy * (spacing_left_ / segment_length);
|
||||
box2d<double> box = this->perform_transform(angle, x, y);
|
||||
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
|
||||
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
|
||||
{
|
||||
//10.0 is the approxmiate number of positions tried and choosen arbitrarily
|
||||
set_spacing_left(spacing_left_ + this->spacing_ * this->max_error_ / 10.0); //Only moves forward
|
||||
set_spacing_left(spacing_left_ + spacing_ * this->params_.max_error / 10.0); //Only moves forward
|
||||
continue;
|
||||
}
|
||||
if (!ignore_placement)
|
||||
|
@ -206,6 +192,8 @@ private:
|
|||
double last_y;
|
||||
double next_x;
|
||||
double next_y;
|
||||
double spacing_;
|
||||
double marker_width_;
|
||||
// If a marker could not be placed at the exact point where it should
|
||||
// go the next marker's distance will be a bit lower.
|
||||
double error_;
|
||||
|
|
|
@ -23,7 +23,6 @@
|
|||
#ifndef MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
|
||||
#define MAPNIK_MARKERS_PLACEMENTS_POINT_HPP
|
||||
|
||||
#include <mapnik/markers_placements/point.hpp>
|
||||
#include <mapnik/geom_util.hpp>
|
||||
|
||||
#include "agg_basics.h"
|
||||
|
@ -31,26 +30,23 @@
|
|||
|
||||
namespace mapnik {
|
||||
|
||||
struct markers_placement_params
|
||||
{
|
||||
box2d<double> const& size;
|
||||
agg::trans_affine const& tr;
|
||||
double spacing;
|
||||
double max_error;
|
||||
bool allow_overlap;
|
||||
};
|
||||
|
||||
template <typename Locator, typename Detector>
|
||||
class markers_point_placement
|
||||
{
|
||||
public:
|
||||
markers_point_placement(
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
markers_point_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
|
||||
: locator_(locator),
|
||||
size_(size),
|
||||
tr_(tr),
|
||||
detector_(detector),
|
||||
spacing_(spacing),
|
||||
max_error_(max_error),
|
||||
allow_overlap_(allow_overlap),
|
||||
marker_width_((size_ * tr_).width()),
|
||||
params_(params),
|
||||
done_(false)
|
||||
{
|
||||
rewind();
|
||||
|
@ -89,11 +85,9 @@ public:
|
|||
}
|
||||
|
||||
angle = 0;
|
||||
agg::trans_affine matrix = tr_;
|
||||
matrix.translate(x,y);
|
||||
box2d<double> box = size_ * matrix;
|
||||
box2d<double> box = perform_transform(angle, x, y);
|
||||
|
||||
if (!allow_overlap_ && !detector_.has_placement(box))
|
||||
if (!params_.allow_overlap && !detector_.has_placement(box))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -109,24 +103,18 @@ public:
|
|||
|
||||
protected:
|
||||
Locator &locator_;
|
||||
box2d<double> size_;
|
||||
agg::trans_affine tr_;
|
||||
Detector &detector_;
|
||||
double spacing_;
|
||||
double max_error_;
|
||||
bool allow_overlap_;
|
||||
double marker_width_;
|
||||
markers_placement_params const& params_;
|
||||
bool done_;
|
||||
|
||||
// Rotates the size_ box and translates the position.
|
||||
box2d<double> perform_transform(double angle, double dx, double dy)
|
||||
{
|
||||
double x1 = size_.minx();
|
||||
double x2 = size_.maxx();
|
||||
double y1 = size_.miny();
|
||||
double y2 = size_.maxy();
|
||||
agg::trans_affine tr = tr_ * agg::trans_affine_rotation(angle)
|
||||
.translate(dx, dy);
|
||||
double x1 = params_.size.minx();
|
||||
double x2 = params_.size.maxx();
|
||||
double y1 = params_.size.miny();
|
||||
double y2 = params_.size.maxy();
|
||||
agg::trans_affine tr = params_.tr * agg::trans_affine_rotation(angle).translate(dx, dy);
|
||||
double xA = x1, yA = y1,
|
||||
xB = x2, yB = y1,
|
||||
xC = x2, yC = y2,
|
||||
|
|
|
@ -31,17 +31,8 @@ template <typename Locator, typename Detector>
|
|||
class markers_vertex_first_placement : public markers_point_placement<Locator, Detector>
|
||||
{
|
||||
public:
|
||||
markers_vertex_first_placement(
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
: markers_point_placement<Locator, Detector>(
|
||||
locator, size, tr, detector,
|
||||
spacing, max_error, allow_overlap)
|
||||
markers_vertex_first_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
|
||||
: markers_point_placement<Locator, Detector>(locator, detector, params)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -78,7 +69,7 @@ public:
|
|||
|
||||
box2d<double> box = this->perform_transform(angle, x, y);
|
||||
|
||||
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
|
||||
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -31,17 +31,8 @@ template <typename Locator, typename Detector>
|
|||
class markers_vertex_last_placement : public markers_point_placement<Locator, Detector>
|
||||
{
|
||||
public:
|
||||
markers_vertex_last_placement(
|
||||
Locator &locator,
|
||||
box2d<double> const& size,
|
||||
agg::trans_affine const& tr,
|
||||
Detector &detector,
|
||||
double spacing,
|
||||
double max_error,
|
||||
bool allow_overlap)
|
||||
: markers_point_placement<Locator, Detector>(
|
||||
locator, size, tr, detector,
|
||||
spacing, max_error, allow_overlap)
|
||||
markers_vertex_last_placement(Locator &locator, Detector &detector, markers_placement_params const& params)
|
||||
: markers_point_placement<Locator, Detector>(locator, detector, params)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -83,7 +74,7 @@ public:
|
|||
|
||||
box2d<double> box = this->perform_transform(angle, x, y);
|
||||
|
||||
if (!this->allow_overlap_ && !this->detector_.has_placement(box))
|
||||
if (!this->params_.allow_overlap && !this->detector_.has_placement(box))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -87,15 +87,9 @@ struct markers_dispatch : mapnik::noncopyable
|
|||
coord2d center = bbox_.center();
|
||||
agg::trans_affine_translation recenter(-center.x, -center.y);
|
||||
agg::trans_affine tr = recenter * marker_trans_;
|
||||
markers_placement_params params { bbox_, tr, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox_,
|
||||
tr,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
@ -156,15 +150,9 @@ struct raster_markers_dispatch : mapnik::noncopyable
|
|||
bool allow_overlap = get<bool>(sym_, keys::allow_overlap, feature_, vars_, false);
|
||||
bool ignore_placement = get<bool>(sym_, keys::ignore_placement, feature_, vars_, false);
|
||||
box2d<double> bbox_(0,0, src_.width(),src_.height());
|
||||
markers_placement_params params { bbox_, marker_trans_, spacing * scale_factor_, max_error, allow_overlap };
|
||||
markers_placement_finder<T, label_collision_detector4> placement_finder(
|
||||
placement_method,
|
||||
path,
|
||||
bbox_,
|
||||
marker_trans_,
|
||||
detector_,
|
||||
spacing * scale_factor_,
|
||||
max_error,
|
||||
allow_overlap);
|
||||
placement_method, path, detector_, params);
|
||||
double x, y, angle = .0;
|
||||
while (placement_finder.get_point(x, y, angle, ignore_placement))
|
||||
{
|
||||
|
|
Loading…
Add table
Reference in a new issue