Add new angled-point marker placement mode for lines
This adds a new mode called 'angled-point' to the marker-placement modes. The full list of modes is then: point, angled-point, interior, line, vertex-first, vertex-last Angled point is identical to point, except that when placing a marker on a line, the marker's angle is taken from the angle of the line segment. There is another possible use of the "angled-point" concept for polygons, and that is for placing labels on stand (aka erf) polygons. By computing a dominant angle for a mostly rectangular polygon, this can produce quite good results. I'm not sure whether I should implement that now, or if I could do that later.
This commit is contained in:
parent
f02a259011
commit
05849f0da5
5 changed files with 31 additions and 5 deletions
12
include/mapnik/geom_util.hpp
Normal file → Executable file
12
include/mapnik/geom_util.hpp
Normal file → Executable file
|
@ -35,6 +35,12 @@
|
|||
#include <vector>
|
||||
#include <algorithm>
|
||||
|
||||
// boost
|
||||
#pragma GCC diagnostic push
|
||||
#include <mapnik/warning_ignore.hpp>
|
||||
#include <boost/optional.hpp>
|
||||
#pragma GCC diagnostic pop
|
||||
|
||||
namespace mapnik
|
||||
{
|
||||
template <typename T>
|
||||
|
@ -298,7 +304,7 @@ bool hit_test_first(PathType & path, double x, double y)
|
|||
namespace label {
|
||||
|
||||
template <typename PathType>
|
||||
bool middle_point(PathType & path, double & x, double & y)
|
||||
bool middle_point(PathType & path, double & x, double & y, boost::optional<double&> angle = boost::none)
|
||||
{
|
||||
double x0 = 0;
|
||||
double y0 = 0;
|
||||
|
@ -319,6 +325,10 @@ bool middle_point(PathType & path, double & x, double & y)
|
|||
double r = (mid_length - dist)/seg_length;
|
||||
x = x0 + (x1 - x0) * r;
|
||||
y = y0 + (y1 - y0) * r;
|
||||
if (angle)
|
||||
{
|
||||
*angle = atan2(y1 - y0, x1 - x0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
dist += seg_length;
|
||||
|
|
|
@ -49,6 +49,10 @@ public:
|
|||
case MARKER_POINT_PLACEMENT:
|
||||
construct(&point_, locator, detector, params);
|
||||
break;
|
||||
case MARKER_ANGLED_POINT_PLACEMENT:
|
||||
construct(&point_, locator, detector, params);
|
||||
point_.use_angle(true);
|
||||
break;
|
||||
case MARKER_INTERIOR_PLACEMENT:
|
||||
construct(&interior_, locator, detector, params);
|
||||
break;
|
||||
|
@ -70,6 +74,7 @@ public:
|
|||
{
|
||||
default:
|
||||
case MARKER_POINT_PLACEMENT:
|
||||
case MARKER_ANGLED_POINT_PLACEMENT:
|
||||
destroy(&point_);
|
||||
break;
|
||||
case MARKER_INTERIOR_PLACEMENT:
|
||||
|
@ -94,6 +99,7 @@ public:
|
|||
{
|
||||
default:
|
||||
case MARKER_POINT_PLACEMENT:
|
||||
case MARKER_ANGLED_POINT_PLACEMENT:
|
||||
return point_.get_point(x, y, angle, ignore_placement);
|
||||
case MARKER_INTERIOR_PLACEMENT:
|
||||
return interior_.get_point(x, y, angle, ignore_placement);
|
||||
|
|
16
include/mapnik/markers_placements/point.hpp
Normal file → Executable file
16
include/mapnik/markers_placements/point.hpp
Normal file → Executable file
|
@ -38,11 +38,18 @@ public:
|
|||
: markers_basic_placement(params),
|
||||
locator_(locator),
|
||||
detector_(detector),
|
||||
done_(false)
|
||||
done_(false),
|
||||
use_angle_(false)
|
||||
{
|
||||
locator_.rewind(0);
|
||||
}
|
||||
|
||||
// Use angle of line
|
||||
void use_angle(bool enable)
|
||||
{
|
||||
use_angle_ = enable;
|
||||
}
|
||||
|
||||
// Start again at first marker. Returns the same list of markers only works when they were NOT added to the detector.
|
||||
void rewind()
|
||||
{
|
||||
|
@ -58,9 +65,11 @@ public:
|
|||
return false;
|
||||
}
|
||||
|
||||
angle = 0;
|
||||
|
||||
if (this->locator_.type() == geometry::geometry_types::LineString)
|
||||
{
|
||||
if (!label::middle_point(this->locator_, x, y))
|
||||
if (!label::middle_point(this->locator_, x, y, use_angle_ ? boost::optional<double&>(angle) : boost::none))
|
||||
{
|
||||
this->done_ = true;
|
||||
return false;
|
||||
|
@ -75,8 +84,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
angle = 0;
|
||||
|
||||
if (!this->push_to_detector(x, y, angle, ignore_placement))
|
||||
{
|
||||
return false;
|
||||
|
@ -90,6 +97,7 @@ protected:
|
|||
Locator & locator_;
|
||||
Detector & detector_;
|
||||
bool done_;
|
||||
bool use_angle_;
|
||||
|
||||
// Checks transformed box placement with collision detector.
|
||||
// returns false if the box:
|
||||
|
|
|
@ -105,6 +105,7 @@ enum marker_placement_enum : std::uint8_t
|
|||
MARKER_LINE_PLACEMENT,
|
||||
MARKER_VERTEX_FIRST_PLACEMENT,
|
||||
MARKER_VERTEX_LAST_PLACEMENT,
|
||||
MARKER_ANGLED_POINT_PLACEMENT,
|
||||
marker_placement_enum_MAX
|
||||
};
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ static const char * marker_placement_strings[] = {
|
|||
"line",
|
||||
"vertex-first",
|
||||
"vertex-last",
|
||||
"angled-point",
|
||||
""
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue