Skip to content

Commit ea7ba2c

Browse files
committed
add polylabel placement method
1 parent e243e16 commit ea7ba2c

14 files changed

+256
-1
lines changed

.gitmodules

+3
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,6 @@
1818
path = deps/mapbox/protozero
1919
url = https://github.com/mapbox/protozero.git
2020
branch = master
21+
[submodule "deps/mapbox/polylabel"]
22+
path = deps/mapbox/polylabel
23+
url = https://github.com/mapbox/polylabel.git

SConstruct

+1
Original file line numberDiff line numberDiff line change
@@ -1756,6 +1756,7 @@ if not preconfigured:
17561756
env.Prepend(CPPPATH = '#deps/mapbox/variant/include')
17571757
env.Prepend(CPPPATH = '#deps/mapbox/geometry/include')
17581758
env.Prepend(CPPPATH = '#deps/mapbox/protozero/include')
1759+
env.Prepend(CPPPATH = '#deps/mapbox/polylabel/include')
17591760
# prepend deps dir for auxillary headers
17601761
env.Prepend(CPPPATH = '#deps')
17611762

deps/mapbox/polylabel

Submodule polylabel added at 51f09d0
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*****************************************************************************
2+
*
3+
* This file is part of Mapnik (c++ mapping toolkit)
4+
*
5+
* Copyright (C) 2017 Artem Pavlenko
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
*****************************************************************************/
22+
23+
#ifndef MAPNIK_GEOMETRY_POLYGON_VERTEX_PROCESSOR_HPP
24+
#define MAPNIK_GEOMETRY_POLYGON_VERTEX_PROCESSOR_HPP
25+
26+
// geometry
27+
#include <mapnik/geometry/polygon.hpp>
28+
29+
namespace mapnik { namespace geometry {
30+
31+
template <typename T>
32+
struct polygon_vertex_processor
33+
{
34+
template <typename Path>
35+
void add_path(Path & path)
36+
{
37+
point<T> p;
38+
unsigned cmd;
39+
linear_ring<T> ring;
40+
while ((cmd = path.vertex(&p.x, &p.y)) != SEG_END)
41+
{
42+
switch (cmd)
43+
{
44+
case SEG_MOVETO:
45+
case SEG_LINETO:
46+
ring.emplace_back(p);
47+
break;
48+
case SEG_CLOSE:
49+
ring.emplace_back(ring.front());
50+
polygon_.emplace_back(std::move(ring));
51+
ring = linear_ring<T>();
52+
break;
53+
}
54+
}
55+
}
56+
57+
polygon<T> polygon_;
58+
};
59+
60+
} }
61+
62+
#endif // MAPNIK_GEOMETRY_POLYGON_VERTEX_PROCESSOR_HPP

include/mapnik/geometry/polylabel.hpp

+39
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
/*****************************************************************************
2+
*
3+
* This file is part of Mapnik (c++ mapping toolkit)
4+
*
5+
* Copyright (C) 2017 Artem Pavlenko
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
*****************************************************************************/
22+
23+
#ifndef MAPNIK_GEOMETRY_POLYLABEL_HPP
24+
#define MAPNIK_GEOMETRY_POLYLABEL_HPP
25+
26+
#include <mapnik/geometry/polygon.hpp>
27+
#include <mapnik/geometry/point.hpp>
28+
29+
namespace mapnik { namespace geometry {
30+
31+
template <class T>
32+
point<T> polylabel(polygon<T> const& polygon, T precision);
33+
34+
template <class T>
35+
T polylabel_precision(polygon<T> const& polygon, double scale_factor);
36+
37+
} }
38+
39+
#endif // MAPNIK_GEOMETRY_POLYLABEL_HPP

include/mapnik/markers_placement.hpp

+10
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,7 @@
2828
#include <mapnik/markers_placements/interior.hpp>
2929
#include <mapnik/markers_placements/vertex_first.hpp>
3030
#include <mapnik/markers_placements/vertex_last.hpp>
31+
#include <mapnik/markers_placements/polylabel.hpp>
3132
#include <mapnik/symbolizer_enumerations.hpp>
3233

3334
namespace mapnik
@@ -65,6 +66,9 @@ class markers_placement_finder : util::noncopyable
6566
case MARKER_VERTEX_LAST_PLACEMENT:
6667
construct(&vertex_last_, locator, detector, params);
6768
break;
69+
case MARKER_POLYLABEL_PLACEMENT:
70+
construct(&polylabel_, locator, detector, params);
71+
break;
6872
}
6973
}
7074

@@ -89,6 +93,9 @@ class markers_placement_finder : util::noncopyable
8993
case MARKER_VERTEX_LAST_PLACEMENT:
9094
destroy(&vertex_last_);
9195
break;
96+
case MARKER_POLYLABEL_PLACEMENT:
97+
destroy(&polylabel_);
98+
break;
9299
}
93100
}
94101

@@ -109,6 +116,8 @@ class markers_placement_finder : util::noncopyable
109116
return vertex_first_.get_point(x, y, angle, ignore_placement);
110117
case MARKER_VERTEX_LAST_PLACEMENT:
111118
return vertex_last_.get_point(x, y, angle, ignore_placement);
119+
case MARKER_POLYLABEL_PLACEMENT:
120+
return polylabel_.get_point(x, y, angle, ignore_placement);
112121
}
113122
}
114123

@@ -122,6 +131,7 @@ class markers_placement_finder : util::noncopyable
122131
markers_interior_placement<Locator, Detector> interior_;
123132
markers_vertex_first_placement<Locator, Detector> vertex_first_;
124133
markers_vertex_last_placement<Locator, Detector> vertex_last_;
134+
markers_polylabel_placement<Locator, Detector> polylabel_;
125135
};
126136

127137
template <typename T>

include/mapnik/markers_placements/basic.hpp

+1
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ struct markers_placement_params
4646
bool allow_overlap;
4747
bool avoid_edges;
4848
direction_enum direction;
49+
double scale_factor;
4950
};
5051

5152
class markers_basic_placement : util::noncopyable
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/*****************************************************************************
2+
*
3+
* This file is part of Mapnik (c++ mapping toolkit)
4+
*
5+
* Copyright (C) 2017 Artem Pavlenko
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
*****************************************************************************/
22+
23+
#ifndef MAPNIK_MARKERS_PLACEMENTS_POLYLABEL_HPP
24+
#define MAPNIK_MARKERS_PLACEMENTS_POLYLABEL_HPP
25+
26+
#include <mapnik/markers_placements/point.hpp>
27+
#include <mapnik/geom_util.hpp>
28+
#include <mapnik/geometry/geometry_types.hpp>
29+
#include <mapnik/geometry/polygon_vertex_processor.hpp>
30+
31+
#include <mapnik/geometry/point.hpp>
32+
#include <mapnik/geometry/polylabel.hpp>
33+
34+
namespace mapnik {
35+
36+
template <typename Locator, typename Detector>
37+
class markers_polylabel_placement : public markers_point_placement<Locator, Detector>
38+
{
39+
public:
40+
using point_placement = markers_point_placement<Locator, Detector>;
41+
using point_placement::point_placement;
42+
43+
bool get_point(double &x, double &y, double &angle, bool ignore_placement)
44+
{
45+
if (this->done_)
46+
{
47+
return false;
48+
}
49+
50+
if (this->locator_.type() != geometry::geometry_types::Polygon)
51+
{
52+
return point_placement::get_point(x, y, angle, ignore_placement);
53+
}
54+
55+
geometry::polygon_vertex_processor<double> vertex_processor;
56+
vertex_processor.add_path(this->locator_);
57+
double precision = geometry::polylabel_precision(vertex_processor.polygon_,
58+
this->params_.scale_factor);
59+
geometry::point<double> placement = geometry::polylabel(vertex_processor.polygon_, precision);
60+
61+
x = placement.x;
62+
y = placement.y;
63+
angle = 0;
64+
65+
if (!this->push_to_detector(x, y, angle, ignore_placement))
66+
{
67+
return false;
68+
}
69+
70+
this->done_ = true;
71+
return true;
72+
}
73+
};
74+
75+
}
76+
77+
#endif // MAPNIK_MARKERS_PLACEMENTS_POLYLABEL_HPP

include/mapnik/symbolizer_enumerations.hpp

+2
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,7 @@ enum marker_placement_enum : std::uint8_t
106106
MARKER_VERTEX_FIRST_PLACEMENT,
107107
MARKER_VERTEX_LAST_PLACEMENT,
108108
MARKER_ANGLED_POINT_PLACEMENT,
109+
MARKER_POLYLABEL_PLACEMENT,
109110
marker_placement_enum_MAX
110111
};
111112

@@ -139,6 +140,7 @@ enum label_placement_enum : std::uint8_t
139140
LINE_PLACEMENT,
140141
VERTEX_PLACEMENT,
141142
INTERIOR_PLACEMENT,
143+
POLYLABEL_PLACEMENT,
142144
label_placement_enum_MAX
143145
};
144146

src/build.py

+1
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,7 @@ def ldconfig(*args,**kwargs):
173173
geometry/closest_point.cpp
174174
geometry/reprojection.cpp
175175
geometry/envelope.cpp
176+
geometry/polylabel.cpp
176177
expression_node.cpp
177178
expression_string.cpp
178179
expression.cpp

src/geometry/polylabel.cpp

+49
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
/*****************************************************************************
2+
*
3+
* This file is part of Mapnik (c++ mapping toolkit)
4+
*
5+
* Copyright (C) 2017 Artem Pavlenko
6+
*
7+
* This library is free software; you can redistribute it and/or
8+
* modify it under the terms of the GNU Lesser General Public
9+
* License as published by the Free Software Foundation; either
10+
* version 2.1 of the License, or (at your option) any later version.
11+
*
12+
* This library is distributed in the hope that it will be useful,
13+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
14+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
* Lesser General Public License for more details.
16+
*
17+
* You should have received a copy of the GNU Lesser General Public
18+
* License along with this library; if not, write to the Free Software
19+
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
20+
*
21+
*****************************************************************************/
22+
23+
#include <mapnik/geometry/polylabel.hpp>
24+
#include <mapnik/geometry/envelope.hpp>
25+
#include <mapbox/polylabel.hpp>
26+
27+
namespace mapnik { namespace geometry {
28+
29+
template <class T>
30+
T polylabel_precision(polygon<T> const& polygon, double scale_factor)
31+
{
32+
// This precision has been chosen to work well in the map (viewport) coordinates.
33+
return 10.0 * scale_factor;
34+
}
35+
36+
template <class T>
37+
point<T> polylabel(polygon<T> const& polygon, T precision)
38+
{
39+
return mapbox::polylabel(polygon, precision);
40+
}
41+
42+
template
43+
point<double> polylabel(polygon<double> const& polygon, double precision);
44+
45+
template
46+
double polylabel_precision(polygon<double> const& polygon, double scale_factor);
47+
48+
} }
49+

src/marker_helpers.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -250,7 +250,7 @@ void apply_markers_multi(feature_impl const& feature, attributes const& vars,
250250
converter.apply(va, proc);
251251
}
252252
}
253-
else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT) &&
253+
else if ((placement == MARKER_POINT_PLACEMENT || placement == MARKER_INTERIOR_PLACEMENT || placement == MARKER_POLYLABEL_PLACEMENT) &&
254254
multi_policy == MARKER_LARGEST_MULTI)
255255
{
256256
// Only apply to path with largest envelope area

src/symbolizer_enumerations.cpp

+2
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,7 @@ static const char * marker_placement_strings[] = {
6868
"vertex-first",
6969
"vertex-last",
7070
"angled-point",
71+
"polylabel",
7172
""
7273
};
7374

@@ -117,6 +118,7 @@ static const char * label_placement_strings[] = {
117118
"line",
118119
"vertex",
119120
"interior",
121+
"polylabel",
120122
""
121123
};
122124

src/text/symbolizer_helpers.cpp

+7
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131
#include <mapnik/geometry.hpp>
3232
#include <mapnik/geometry/geometry_type.hpp>
3333
#include <mapnik/geometry/centroid.hpp>
34+
#include <mapnik/geometry/polylabel.hpp>
3435
#include <mapnik/vertex_processor.hpp>
3536
#include <mapnik/geom_util.hpp>
3637
#include <mapnik/parse_path.hpp>
@@ -307,6 +308,12 @@ void base_symbolizer_helper::initialize_points() const
307308
points_.emplace_back(label_x, label_y);
308309
}
309310
}
311+
else if (how_placed == POLYLABEL_PLACEMENT)
312+
{
313+
double precision = geometry::polylabel_precision(tranformed_poly, scale_factor_);
314+
geometry::point<double> pt = geometry::polylabel(tranformed_poly, precision);
315+
points_.emplace_back(pt.x, pt.y);
316+
}
310317
continue;
311318
}
312319
else

0 commit comments

Comments
 (0)