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