1 #pragma once
2
3 #include <mapbox/geometry.hpp>
4 #include <mapbox/variant.hpp>
5
6 #include <algorithm>
7 #include <string>
8 #include <unordered_map>
9 #include <vector>
10
11 namespace mapbox {
12 namespace geojsonvt {
13 namespace detail {
14
15 struct vt_point : mapbox::geometry::point<double> {
16 double z = 0.0; // simplification tolerance
17
vt_pointmapbox::geojsonvt::detail::vt_point18 vt_point(double x_, double y_, double z_) : mapbox::geometry::point<double>(x_, y_), z(z_) {
19 }
20
vt_pointmapbox::geojsonvt::detail::vt_point21 vt_point(double x_, double y_) : vt_point(x_, y_, 0.0) {
22 }
23 };
24
25 template <uint8_t I, typename T>
26 inline double get(const T&);
27
28 template <>
get(const vt_point & p)29 inline double get<0>(const vt_point& p) {
30 return p.x;
31 }
32 template <>
get(const vt_point & p)33 inline double get<1>(const vt_point& p) {
34 return p.y;
35 }
36 template <>
get(const mapbox::geometry::point<double> & p)37 inline double get<0>(const mapbox::geometry::point<double>& p) {
38 return p.x;
39 }
40 template <>
get(const mapbox::geometry::point<double> & p)41 inline double get<1>(const mapbox::geometry::point<double>& p) {
42 return p.y;
43 }
44
45 template <uint8_t I>
46 inline vt_point intersect(const vt_point&, const vt_point&, const double);
47
48 template <>
intersect(const vt_point & a,const vt_point & b,const double x)49 inline vt_point intersect<0>(const vt_point& a, const vt_point& b, const double x) {
50 const double y = (x - a.x) * (b.y - a.y) / (b.x - a.x) + a.y;
51 return { x, y, 1.0 };
52 }
53 template <>
intersect(const vt_point & a,const vt_point & b,const double y)54 inline vt_point intersect<1>(const vt_point& a, const vt_point& b, const double y) {
55 const double x = (y - a.y) * (b.x - a.x) / (b.y - a.y) + a.x;
56 return { x, y, 1.0 };
57 }
58
59 using vt_multi_point = std::vector<vt_point>;
60
61 struct vt_line_string : std::vector<vt_point> {
62 using container_type = std::vector<vt_point>;
63 vt_line_string() = default;
vt_line_stringmapbox::geojsonvt::detail::vt_line_string64 vt_line_string(std::initializer_list<vt_point> args)
65 : container_type(std::move(args)) {}
66
67 double dist = 0.0; // line length
68 };
69
70 struct vt_linear_ring : std::vector<vt_point> {
71 using container_type = std::vector<vt_point>;
72 vt_linear_ring() = default;
vt_linear_ringmapbox::geojsonvt::detail::vt_linear_ring73 vt_linear_ring(std::initializer_list<vt_point> args)
74 : container_type(std::move(args)) {}
75
76 double area = 0.0; // polygon ring area
77 };
78
79 using vt_multi_line_string = std::vector<vt_line_string>;
80 using vt_polygon = std::vector<vt_linear_ring>;
81 using vt_multi_polygon = std::vector<vt_polygon>;
82
83 struct vt_geometry_collection;
84
85 using vt_geometry = mapbox::util::variant<vt_point,
86 vt_line_string,
87 vt_polygon,
88 vt_multi_point,
89 vt_multi_line_string,
90 vt_multi_polygon,
91 vt_geometry_collection>;
92
93 struct vt_geometry_collection : std::vector<vt_geometry> {};
94
95 using property_map = mapbox::geometry::property_map;
96 using identifier = mapbox::geometry::identifier;
97
98 template <class T>
99 using optional = std::experimental::optional<T>;
100
101 template <class T>
102 struct vt_geometry_type;
103
104 template <>
105 struct vt_geometry_type<geometry::point<double>> {
106 using type = vt_point;
107 };
108 template <>
109 struct vt_geometry_type<geometry::line_string<double>> {
110 using type = vt_line_string;
111 };
112 template <>
113 struct vt_geometry_type<geometry::polygon<double>> {
114 using type = vt_polygon;
115 };
116 template <>
117 struct vt_geometry_type<geometry::multi_point<double>> {
118 using type = vt_multi_point;
119 };
120 template <>
121 struct vt_geometry_type<geometry::multi_line_string<double>> {
122 using type = vt_multi_line_string;
123 };
124 template <>
125 struct vt_geometry_type<geometry::multi_polygon<double>> {
126 using type = vt_multi_polygon;
127 };
128 template <>
129 struct vt_geometry_type<geometry::geometry<double>> {
130 using type = vt_geometry;
131 };
132 template <>
133 struct vt_geometry_type<geometry::geometry_collection<double>> {
134 using type = vt_geometry_collection;
135 };
136
137 struct vt_feature {
138 vt_geometry geometry;
139 property_map properties;
140 optional<identifier> id;
141
142 mapbox::geometry::box<double> bbox = { { 2, 1 }, { -1, 0 } };
143 uint32_t num_points = 0;
144
vt_featuremapbox::geojsonvt::detail::vt_feature145 vt_feature(const vt_geometry& geom, const property_map& props, const optional<identifier>& id_)
146 : geometry(geom), properties(props), id(id_) {
147
148 mapbox::geometry::for_each_point(geom, [&](const vt_point& p) {
149 bbox.min.x = std::min(p.x, bbox.min.x);
150 bbox.min.y = std::min(p.y, bbox.min.y);
151 bbox.max.x = std::max(p.x, bbox.max.x);
152 bbox.max.y = std::max(p.y, bbox.max.y);
153 ++num_points;
154 });
155 }
156 };
157
158 using vt_features = std::vector<vt_feature>;
159
160 } // namespace detail
161 } // namespace geojsonvt
162 } // namespace mapbox
163