-
Notifications
You must be signed in to change notification settings - Fork 0
/
geometry.hpp
150 lines (121 loc) · 4.96 KB
/
geometry.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
// "Copyright 2020 Kirill Konevets"
//!
//! @file geometry.hpp
//! @brief Set of geo detection functions
//!
#ifndef INCLUDE_GEOMETRY_HPP_
#define INCLUDE_GEOMETRY_HPP_
#include <Eigen/Dense>
#include "geometry.hpp"
#include <boost/geometry.hpp>
#include <boost/geometry/geometries/box.hpp>
#include <boost/geometry/geometries/point.hpp>
namespace x_company::geometry {
namespace bg = boost::geometry;
namespace bgi = boost::geometry::index;
using Geometry = Eigen::Matrix<double, Eigen::Dynamic, 2, Eigen::ColMajor>;
using Point = Eigen::Matrix<double, 1, 2>;
using PointXY = bg::model::d2::point_xy<double>;
using Box = bg::model::box<PointXY>;
constexpr double length_meridian = 20004274;
// 1 meter in degrees
constexpr double METER = 180. / length_meridian;
enum class Shape : char { polygon, line, circle };
//! A polygon can contain fully, intersect or not intersect with a circle.
//! If it does not intersect it is outside of a polygon.
struct Condition {
bool intersects = false;
bool contains = false;
bool operator==(const Condition &rhs) const;
friend std::ostream &operator<<(std::ostream &out, const Condition &c);
};
//! Vectorised Ramer–Douglas–Peucker algorithm
//! \param g vector of points representing a 2D geometry
//! \param epsilon throwing away threshold
//! \return simplified geometry with some points thrown away
auto rdp(const Geometry &g, Geometry::Scalar epsilon) -> Geometry;
auto rdp(const Geometry &&g, Geometry::Scalar epsilon) -> Geometry;
//!
//! Calculates adjacent row differences.
//! g:
//! 10 2
//! 5 8
//! 3 4
//!
//! diff(g):
//! -5 6
//! -2 -4
//!
//! \return Geomery object with one number of rows less
auto row_diff(const Geometry &g) -> Geometry;
//! Vector cross product of a 2D `point` by a vector of 2D points `g`.
//! \param g vector of points representin a 2D geometry
//! \return vector of components along `z` axis
auto cross(Point point, const Geometry &g) -> Eigen::VectorXd;
auto cross(Point point, const Geometry &&g) -> Eigen::VectorXd;
//! Calculates distances of every point of `g` to a line connecting
//! beginning and end of `g`
//! \param g vector of points representin a 2D geometry
//! \return vector of distances to the line
auto line_dists(const Geometry &g, const Point &begin, const Point &end)
-> Eigen::VectorXd;
//! Calculate mean L2 distance between adjacent points in geometry
auto mean_distance(const Geometry &g) -> Geometry::value_type;
//! Calculate median L2 distance between adjacent points in geometry
auto median_distance(const Geometry &g) -> Geometry::value_type;
//! Converts wkt text to geometry, type of geometry should be known in advance
//! \param wkt string in wkt format
//! \param s geometry shape enum value
//! \returns geometry data in ColMajor format
auto parse_wkt(std::string_view wkt, Shape s) -> std::vector<double>;
//! Helper function to load points from txt file.
//! \param fname input file name
//! \return geometry from file
auto load_points_csv(const std::string &fname) -> Geometry;
//! make box centered in point with a side length equal to 2*accr
//! \param p center of a box
//! \param accr half length of a box size
//! \returns centered box
inline auto centered_box(const Point p, double accr) -> Box {
static const double root = std::sqrt(2);
double diag = root * accr;
Box box(PointXY(p(0) - diag, p(1) - diag), // left bottom corner
PointXY(p(0) + diag, p(1) + diag)); // top right corner
return box;
}
//! Calculates the envelope of a geometry
//! \param g geometry
//! \returns bounding box around geometry
inline auto envelope(const Geometry &g) -> Box {
double minx = g.col(0).minCoeff();
double maxx = g.col(0).maxCoeff();
double miny = g.col(1).minCoeff();
double maxy = g.col(1).maxCoeff();
// calculate polygon bounding box
return Box(PointXY(minx, miny), PointXY(maxx, maxy));
}
//! `pnpoly` algorithm to find if a point is in a polygon. W. Randolph Franklin
//! \param poly polygon points
//! \param point center of a circle
//! \returns point is in a polygon or not
bool pnpoly(const Geometry &poly, const Point &point);
//! Find minimum distance from a point to a geometry as a minimum
//! distances to all edges
//! \param g geometry points
//! \param point to find distance from
//! \return minimum distance to a polygon
double minimum_distance(const Geometry &g, const Point &point);
//! Detect if polygon contains a circle, if it does't detect intersection.
//! \param poly polygon points
//! \param point center of a circle
//! \param accr circle radius (accuracy)
//! \returns condition of intersection - intesects or/and contains
Condition contains(const Geometry &poly, const Point &point, double accr);
//! Detect if a circle intersects with a polygon
//! \param poly polygon points
//! \param point center of a circle
//! \param accr circle radius (accuracy)
//! \returns true if intersects, false otherwise
bool intersects(const Geometry &poly, const Point &point, double accr);
} // namespace x_company::geometry
#endif // INCLUDE_GEOMETRY_HPP_