Project
Loading...
Searching...
No Matches
ContourCreator.inl
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_CONTOURCREATOR_INL
16#define O2_MCH_CONTOUR_CONTOURCREATOR_INL
17
18#include <utility>
19#include <vector>
20#include <iostream>
21#include "Edge.h"
22#include "Polygon.h"
23#include "Contour.h"
24#include "SegmentTree.h"
25#include <algorithm>
26
27namespace o2
28{
29namespace mch
30{
31namespace contour
32{
33namespace impl
34{
35
36template <typename T>
37void sortVerticalEdges(std::vector<VerticalEdge<T>>& edges)
38{
39 // sort vertical edges in ascending x order
40 // if same x, insure that left edges are before right edges
41 // within same x, order by increasing bottommost y
42 // Mind your steps ! This sorting is critical to the contour merging algorithm !
43
44 std::sort(edges.begin(), edges.end(), [](const VerticalEdge<T>& e1, const VerticalEdge<T>& e2) {
45
46 auto x1 = e1.begin().x;
47 auto x2 = e2.begin().x;
48
49 auto y1 = bottom(e1);
50 auto y2 = bottom(e2);
51
52 if (areEqual(x1, x2)) {
53 if (isLeftEdge(e1) && isRightEdge(e2)) {
54 return true;
55 }
56 if (isRightEdge(e1) && isLeftEdge(e2)) {
57 return false;
58 }
59 return y1 < y2;
60 } else if (x1 < x2) {
61 return true;
62 } else {
63 return false;
64 }
65 });
66}
67
68template <typename T>
70{
71 auto y1 = edge.begin().y;
72 auto y2 = edge.end().y;
73 return y2 > y1 ? Interval<T>(y1, y2) : Interval<T>(y2, y1);
74}
75
76template <typename T>
77std::vector<VerticalEdge<T>> getVerticalEdges(const Polygon<T>& polygon)
78{
80 std::vector<VerticalEdge<T>> edges;
81 for (auto i = 0; i < polygon.size() - 1; ++i) {
82 auto current = polygon[i];
83 auto next = polygon[i + 1];
84 if (current.x == next.x) {
85 edges.push_back({ current.x, current.y, next.y });
86 }
87 }
88 return edges;
89}
90
91template <typename T>
92std::vector<VerticalEdge<T>> getVerticalEdges(const std::vector<Polygon<T>>& polygons)
93{
94 std::vector<VerticalEdge<T>> edges;
95 for (const auto& p : polygons) {
96 auto e = getVerticalEdges(p);
97 edges.insert(edges.end(), e.begin(), e.end());
98 }
99 return edges;
100}
101
102template <typename T>
103T getX(const Vertex<T>& v)
104{
105 return v.x;
106}
107
108template <typename T>
109T getY(const Vertex<T>& v)
110{
111 return v.y;
112}
113
114template <typename T>
115using GetVertexPosFunc = T (*)(const Vertex<T>&);
116
117template <typename T>
118std::vector<T> getPositions(const std::vector<Polygon<T>>& polygons, GetVertexPosFunc<T> func)
119{
120 std::vector<T> ypos;
121 for (auto i = 0; i < polygons.size(); ++i) {
122 for (auto j = 0; j < polygons[i].size(); ++j) {
123 ypos.push_back(func(polygons[i][j]));
124 }
125 }
126 std::sort(ypos.begin(), ypos.end());
127 auto last = std::unique(ypos.begin(), ypos.end(), [](const T& a, const T& b) { return areEqual(a, b); });
128 ypos.erase(last, ypos.end());
129 return ypos;
130}
131
132template <typename T>
133std::vector<T> getYPositions(const std::vector<Polygon<T>>& polygons)
134{
135 return getPositions(polygons, getY);
136}
137
138template <typename T>
139std::vector<T> getXPositions(const std::vector<Polygon<T>>& polygons)
140{
141 return getPositions(polygons, getX);
142}
143
144template <typename T>
145std::vector<VerticalEdge<T>> sweep(Node<T>* segmentTree, const std::vector<VerticalEdge<T>>& polygonVerticalEdges)
146{
147 std::vector<VerticalEdge<T>> contourVerticalEdges;
148
149 std::vector<Interval<T>> edgeStack;
150
151 for (auto i = 0; i < polygonVerticalEdges.size(); ++i) {
152
153 const auto& edge = polygonVerticalEdges[i];
154 auto ival = interval(edge);
155
156 if (isLeftEdge(edge)) {
157 segmentTree->contribution(ival, edgeStack);
158 segmentTree->insertInterval(ival);
159 } else {
160 segmentTree->deleteInterval(ival);
161 segmentTree->contribution(ival, edgeStack);
162 }
163
164 auto e1{ edge };
165
166 if (i < polygonVerticalEdges.size() - 1) {
167 e1 = polygonVerticalEdges[i + 1];
168 }
169
170 if ((isLeftEdge(edge) != isLeftEdge(e1)) || (!areEqual(edge.begin().x, e1.begin().x)) ||
171 (i == polygonVerticalEdges.size() - 1)) {
172 for (auto es : edgeStack) {
173 contourVerticalEdges.push_back(isRightEdge(edge) ? VerticalEdge<T>{ edge.begin().x, es.begin(), es.end() }
174 : VerticalEdge<T>{ edge.begin().x, es.end(), es.begin() });
175 }
176 edgeStack.clear();
177 }
178 }
179
180 return contourVerticalEdges;
181}
182
191template <typename T>
192std::vector<HorizontalEdge<T>> verticalsToHorizontals(const std::vector<VerticalEdge<T>>& verticals)
193{
194 std::vector<HorizontalEdge<T>> horizontals(verticals.size());
195
196 using VertexWithRef = std::pair<Vertex<T>, T>;
197 std::vector<VertexWithRef> vertices;
198
199 for (auto i = 0; i < verticals.size(); ++i) {
200 const auto& edge = verticals[i];
201 vertices.push_back({ edge.begin(), i });
202 vertices.push_back({ edge.end(), i });
203 }
204
205 std::sort(vertices.begin(), vertices.end(),
206 [](const VertexWithRef& v1, const VertexWithRef& v2) { return v1.first < v2.first; });
207
208 for (auto i = 0; i < vertices.size() / 2; ++i) {
209 const auto& p1 = vertices[2 * i];
210 const auto& p2 = vertices[2 * i + 1];
211 const VerticalEdge<T>& refEdge = verticals[p1.second];
212 auto e = p1.first.x;
213 auto b = p2.first.x;
214 if ((areEqual(p1.first.y, bottom(refEdge)) && isLeftEdge(refEdge)) ||
215 (areEqual(p1.first.y, top(refEdge)) && isRightEdge(refEdge))) {
216 std::swap(b, e);
217 }
218 HorizontalEdge<T> h{ p1.first.y, b, e };
219 // which vertical edge is preceding this horizontal ?
220 int preceding = p1.second;
221 int next = p2.second;
222 if (b > e) {
223 std::swap(preceding, next);
224 }
225 horizontals[preceding] = h;
226 }
227 return horizontals;
228}
229
230template <typename T>
231Contour<T> finalizeContour(const std::vector<VerticalEdge<T>>& verticals,
232 const std::vector<HorizontalEdge<T>>& horizontals)
233{
234 if (verticals.size() != horizontals.size()) {
235 throw std::invalid_argument("should get the same number of verticals and horizontals");
236 }
237
238 for (auto i = 0; i < verticals.size(); ++i) {
239 if (horizontals[i].begin() != verticals[i].end()) {
240 throw std::invalid_argument("got an horizontal edge not connected to its (supposedly) preceding vertical edge");
241 }
242 }
243
244 std::vector<ManhattanEdge<T>> all;
245
246 for (auto i = 0; i < verticals.size(); ++i) {
247 all.push_back(verticals[i]);
248 all.push_back(horizontals[i]);
249 }
250
251 Contour<T> contour;
252
253 std::vector<bool> alreadyAdded(all.size(), false);
254 std::vector<int> inorder;
255
256 int nofUsed{ 0 };
257 int iCurrent{ 0 };
258
259 ManhattanEdge<T> startSegment{ all[iCurrent] };
260
261 while (nofUsed < all.size()) {
262
263 const ManhattanEdge<T>& currentSegment{ all[iCurrent] };
264 inorder.push_back(iCurrent);
265 alreadyAdded[iCurrent] = true;
266 ++nofUsed;
267 if (currentSegment.end() == startSegment.begin()) {
268 if (inorder.empty()) {
269 throw std::runtime_error("got an empty polygon");
270 }
271 std::vector<Vertex<T>> vertices;
272 vertices.reserve(inorder.size());
273 for (auto i : inorder) {
274 vertices.push_back(all[i].begin());
275 }
276 Polygon<T> polygon(vertices.begin(), vertices.end());
277 contour.addPolygon(close(polygon));
278 iCurrent = std::distance(alreadyAdded.begin(), std::find_if(alreadyAdded.begin(), alreadyAdded.end(),
279 [](bool a) { return a == false; }));
280 if (iCurrent<all.size()) {
281 startSegment = all[iCurrent];
282 inorder.clear();
283 }
284 }
285
286 for (auto i = 0; i < alreadyAdded.size(); ++i) {
287 if (i != iCurrent && alreadyAdded[i] == false) {
288 if (currentSegment.end() == all[i].begin()) {
289 iCurrent = i;
290 break;
291 }
292 }
293 }
294 }
295
296 return contour;
297}
298
299} // namespace impl
300} // namespace contour
301} // namespace mch
302} // namespace o2
303
304#endif // ALO_CONTOURCREATOR_INL
bool areEqual(double a, double b)
int32_t i
constexpr int p2()
constexpr int p1()
constexpr to accelerate the coordinates changing
std::vector< LocalPoint > getPositions(int npoints)
uint32_t j
Definition RawData.h:0
Class for time synchronization of RawReader instances.
Contour< T > & addPolygon(const Polygon< T > &polygon)
Definition Contour.h:78
size_type size() const
Definition Polygon.h:61
Vertex< T > begin() const
Definition Edge.h:46
Vertex< T > end() const
Definition Edge.h:48
void insertInterval(Interval< T > i)
void deleteInterval(Interval< T > i)
void contribution(Interval< T > i, std::vector< o2::mch::contour::impl::Interval< T > > &edgeStack)
GLenum func
Definition glcorearb.h:778
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition glcorearb.h:5034
GLuint GLuint end
Definition glcorearb.h:469
const GLdouble * v
Definition glcorearb.h:832
GLuint GLfloat GLfloat GLfloat x1
Definition glcorearb.h:5034
GLdouble GLdouble GLdouble GLdouble top
Definition glcorearb.h:4077
GLboolean GLboolean GLboolean b
Definition glcorearb.h:1233
GLint GLint bottom
Definition glcorearb.h:1979
GLfloat GLfloat v1
Definition glcorearb.h:812
GLboolean GLboolean GLboolean GLboolean a
Definition glcorearb.h:1233
GLfloat GLfloat GLfloat v2
Definition glcorearb.h:813
bool isLeftEdge(const VerticalEdge< T > &edge)
Definition Edge.h:102
std::vector< VerticalEdge< T > > sweep(Node< T > *segmentTree, const std::vector< VerticalEdge< T > > &polygonVerticalEdges)
std::vector< VerticalEdge< T > > getVerticalEdges(const Polygon< T > &polygon)
Interval< T > interval(const VerticalEdge< T > &edge)
bool isRightEdge(const VerticalEdge< T > &edge)
Definition Edge.h:108
std::vector< HorizontalEdge< T > > verticalsToHorizontals(const std::vector< VerticalEdge< T > > &verticals)
Contour< T > finalizeContour(const std::vector< VerticalEdge< T > > &verticals, const std::vector< HorizontalEdge< T > > &horizontals)
T(*)(const Vertex< T > &) GetVertexPosFunc
std::vector< T > getYPositions(const std::vector< Polygon< T > > &polygons)
std::vector< T > getXPositions(const std::vector< Polygon< T > > &polygons)
void sortVerticalEdges(std::vector< VerticalEdge< T > > &edges)
Polygon< T > close(Polygon< T > polygon)
Definition Polygon.h:126
double * getX(double *xyDxy, int N)
double * getY(double *xyDxy, int N)
a couple of static helper functions to create timestamp values for CCDB queries or override obsolete ...