Project
Loading...
Searching...
No Matches
Polygon.h
Go to the documentation of this file.
1// Copyright 2019-2020 CERN and copyright holders of ALICE O2.
2// See https://alice-o2.web.cern.ch/copyright for details of the copyright holders.
3// All rights not expressly granted are reserved.
4//
5// This software is distributed under the terms of the GNU General Public
6// License v3 (GPL Version 3), copied verbatim in the file "COPYING".
7//
8// In applying this license CERN does not waive the privileges and immunities
9// granted to it by virtue of its status as an Intergovernmental Organization
10// or submit itself to any jurisdiction.
11
14
15#ifndef O2_MCH_CONTOUR_POLYGON_H
16#define O2_MCH_CONTOUR_POLYGON_H
17
18#include <iostream>
19#include <utility>
20#include <vector>
21#include <initializer_list>
22#include <sstream>
23#include <algorithm>
24#include "BBox.h"
25#include "Vertex.h"
26
27namespace o2
28{
29namespace mch
30{
31namespace contour
32{
33
34template <typename T>
35class Polygon;
36
37template <typename T>
38std::vector<o2::mch::contour::Vertex<T>> getVertices(const Polygon<T>& polygon);
39
40template <typename T>
41std::vector<o2::mch::contour::Vertex<T>> getSortedVertices(const Polygon<T>& polygon);
42
43template <typename T>
45{
46 public:
47 using size_type = typename std::vector<o2::mch::contour::Vertex<T>>::size_type;
48
49 Polygon() = default;
50
51 template <typename InputIterator>
52 Polygon(InputIterator first, InputIterator last)
53 {
54 std::copy(first, last, std::back_inserter(mVertices));
55 }
56
57 Polygon(std::initializer_list<o2::mch::contour::Vertex<T>> args) : mVertices{args} {}
58
59 o2::mch::contour::Vertex<T> firstVertex() const { return mVertices.front(); }
60
61 size_type size() const { return mVertices.size(); }
62
63 bool empty() const { return size() == 0; }
64
65 o2::mch::contour::Vertex<T> operator[](int i) const { return mVertices[i]; }
66
67 bool isCounterClockwiseOriented() const { return signedArea() > 0.0; }
68
69 bool isManhattan() const
70 {
71 for (auto i = 0; i < mVertices.size() - 1; ++i) {
72 if (!isVertical(mVertices[i], mVertices[i + 1]) && !isHorizontal(mVertices[i], mVertices[i + 1])) {
73 return false;
74 }
75 }
76 return true;
77 }
78
79 bool isClosed() const { return mVertices.back() == mVertices.front(); }
80
81 bool contains(T x, T y) const;
82
83 double signedArea() const
84 {
88 double area{0.0};
89 for (auto i = 0; i < mVertices.size() - 1; ++i) {
90 auto& current = mVertices[i];
91 auto& next = mVertices[i + 1];
92 area += current.x * next.y - next.x * current.y;
93 }
94 return area * 0.5;
95 }
96
97 void scale(T sx, T sy)
98 {
99 for (auto i = 0; i < mVertices.size(); ++i) {
100 mVertices[i].x *= sx;
101 mVertices[i].y *= sy;
102 }
103 }
104
105 void translate(T dx, T dy)
106 {
107 for (auto i = 0; i < mVertices.size(); ++i) {
108 mVertices[i].x += dx;
109 mVertices[i].y += dy;
110 }
111 }
112
113 friend std::ostream& operator<<(std::ostream& os, const Polygon<T>& polygon)
114 {
115 os << "POLYGON(";
116 os << polygon.mVertices;
117 os << ")";
118 return os;
119 }
120
121 private:
122 std::vector<o2::mch::contour::Vertex<T>> mVertices;
123};
124
125template <typename T>
127{
128 if (!polygon.isClosed()) {
129 auto vertices = getVertices(polygon);
130 vertices.push_back(polygon.firstVertex());
131 Polygon<T> pol(vertices.begin(), vertices.end());
132 if (!pol.isManhattan()) {
133 throw std::logic_error("closing resulted in non Manhattan polygon");
134 }
135 return pol;
136 }
137 return polygon;
138}
139
140template <typename T>
141bool operator!=(const Polygon<T>& lhs, const Polygon<T>& rhs)
142{
143 return !(rhs == lhs);
144}
145
150template <typename T>
151bool operator==(const Polygon<T>& lhs, const Polygon<T>& rhs)
152{
153 if (lhs.size() != rhs.size()) {
154 return false;
155 }
156
157 auto l = getSortedVertices(lhs);
158 auto r = getSortedVertices(rhs);
159
160 if (l.size() != r.size()) {
161 return false;
162 }
163
164 for (auto i = 0; i < l.size(); ++i) {
165 if (l[i] != r[i]) {
166 return false;
167 }
168 }
169 return true;
170}
171
172template <typename T>
173bool Polygon<T>::contains(T xp, T yp) const
174{
175 // Note that this algorithm yields unpredicatable result if the point xp,yp
176 // is on one edge of the polygon. Should not generally matters, except when comparing
177 // two different implementations maybe.
178 //
179 // TODO : look e.g. to http://alienryderflex.com/polygon/ for some possible optimizations
180 // (e.g. pre-computation)
181 //
182 if (!isClosed()) {
183 throw std::invalid_argument("contains method can only work with closed polygons");
184 }
185
186 auto j = mVertices.size() - 1;
187 bool oddNodes{false};
188 for (auto i = 0; i < mVertices.size(); i++) {
189 if ((mVertices[i].y < yp && mVertices[j].y >= yp) || (mVertices[j].y < yp && mVertices[i].y >= yp)) {
190 if (mVertices[i].x +
191 (yp - mVertices[i].y) / (mVertices[j].y - mVertices[i].y) * (mVertices[j].x - mVertices[i].x) <
192 xp) {
193 oddNodes = !oddNodes;
194 }
195 }
196 j = i;
197 }
198 return oddNodes;
199}
200
201template <typename T>
202std::vector<o2::mch::contour::Vertex<T>> getVertices(const Polygon<T>& polygon)
203{
204 std::vector<o2::mch::contour::Vertex<T>> vertices;
205 vertices.reserve(polygon.size());
206 for (auto i = 0; i < polygon.size(); ++i) {
207 vertices.push_back(polygon[i]);
208 }
209 return vertices;
210}
211
212template <typename T>
213std::vector<o2::mch::contour::Vertex<T>> getSortedVertices(const Polygon<T>& polygon)
214{
215 std::vector<o2::mch::contour::Vertex<T>> vertices;
216 auto size = polygon.size();
217 if (polygon.isClosed()) {
218 --size;
219 }
220 vertices.reserve(size);
221 for (auto i = 0; i < size; ++i) {
222 vertices.push_back(polygon[i]);
223 }
224 std::sort(vertices.begin(), vertices.end());
225 return vertices;
226}
227
228template <typename T>
229BBox<T> getBBox(const std::vector<Vertex<T>>& vertices)
230{
231
232 T xmin{std::numeric_limits<T>::max()};
233 T xmax{std::numeric_limits<T>::lowest()};
234 T ymin{std::numeric_limits<T>::max()};
235 T ymax{std::numeric_limits<T>::lowest()};
236
237 for (const auto& v : vertices) {
238 xmin = std::min(xmin, v.x);
239 xmax = std::max(xmax, v.x);
240 ymin = std::min(ymin, v.y);
241 ymax = std::max(ymax, v.y);
242 }
243 return {xmin, ymin, xmax, ymax};
244}
245
246template <typename T>
248{
251
252 auto vertices = getVertices(polygon);
253 return getBBox(vertices);
254}
255
256template <typename T>
257BBox<T> getBBox(const std::vector<Polygon<T>>& polygons)
258{
261
262 T xmin{std::numeric_limits<T>::max()};
263 T xmax{std::numeric_limits<T>::lowest()};
264 T ymin{std::numeric_limits<T>::max()};
265 T ymax{std::numeric_limits<T>::lowest()};
266
267 for (const auto& p : polygons) {
268 auto b = getBBox(p);
269 xmin = std::min(xmin, b.xmin());
270 xmax = std::max(xmax, b.xmax());
271 ymin = std::min(ymin, b.ymin());
272 ymax = std::max(ymax, b.ymax());
273 }
274 return {xmin, ymin, xmax, ymax};
275}
276
277template <typename T>
278auto squaredDistancePointToPolygon(const Vertex<T>& point, const Polygon<T>& polygon) -> decltype(point.x * point.x)
279{
280 T d{std::numeric_limits<T>::max()};
281 for (auto i = 0; i < polygon.size() - 1; ++i) {
282 auto s0 = polygon[i];
283 auto s1 = polygon[i + 1];
284 auto d2 = squaredDistanceOfPointToSegment(point, s0, s1);
285 d = std::min(d2, d);
286 }
287 return d;
288}
289
290} // namespace contour
291} // namespace mch
292} // namespace o2
293
294#endif
int32_t i
uint32_t j
Definition RawData.h:0
void translate(T dx, T dy)
Definition Polygon.h:105
bool isClosed() const
Definition Polygon.h:79
bool isCounterClockwiseOriented() const
Definition Polygon.h:67
double signedArea() const
Definition Polygon.h:83
bool contains(T x, T y) const
Definition Polygon.h:173
size_type size() const
Definition Polygon.h:61
o2::mch::contour::Vertex< T > operator[](int i) const
Definition Polygon.h:65
Polygon(InputIterator first, InputIterator last)
Definition Polygon.h:52
void scale(T sx, T sy)
Definition Polygon.h:97
o2::mch::contour::Vertex< T > firstVertex() const
Definition Polygon.h:59
typename std::vector< o2::mch::contour::Vertex< T > >::size_type size_type
Definition Polygon.h:47
Polygon(std::initializer_list< o2::mch::contour::Vertex< T > > args)
Definition Polygon.h:57
bool isManhattan() const
Definition Polygon.h:69
friend std::ostream & operator<<(std::ostream &os, const Polygon< T > &polygon)
Definition Polygon.h:113
GLint GLenum GLint x
Definition glcorearb.h:403
GLsizeiptr size
Definition glcorearb.h:659
const GLdouble * v
Definition glcorearb.h:832
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s1
Definition glcorearb.h:5034
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLboolean r
Definition glcorearb.h:1233
GLuint GLfloat GLfloat GLfloat GLfloat GLfloat GLfloat s0
Definition glcorearb.h:5034
std::vector< o2::mch::contour::Vertex< T > > getVertices(const std::vector< o2::mch::contour::Polygon< T > > &polygons)
Definition Contour.h:31
auto squaredDistancePointToPolygon(const Vertex< T > &point, const Polygon< T > &polygon) -> decltype(point.x *point.x)
Definition Polygon.h:278
auto squaredDistanceOfPointToSegment(const Vertex< T > &p, const Vertex< T > &p0, const Vertex< T > &p1) -> decltype(p0.x *p1.x)
Definition Vertex.h:117
bool isHorizontal(const Vertex< T > &a, const Vertex< T > &b)
Definition Vertex.h:92
bool operator!=(const Contour< T > &lhs, const Contour< T > &rhs)
Definition Contour.h:126
BBox< T > getBBox(const Contour< T > &contour)
Definition Contour.h:176
Polygon< T > close(Polygon< T > polygon)
Definition Polygon.h:126
bool operator==(const Contour< T > &lhs, const Contour< T > &rhs)
Definition Contour.h:136
std::vector< o2::mch::contour::Vertex< T > > getSortedVertices(const std::vector< o2::mch::contour::Polygon< T > > &polygons)
Definition Contour.h:44
bool isVertical(const Vertex< T > &a, const Vertex< T > &b)
Definition Vertex.h:86
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...