TTK
Loading...
Searching...
No Matches
FTMSegmentation.cpp
Go to the documentation of this file.
1
7// for the merge tree and contour tree
11
12#ifndef TTK_ENABLE_KAMIKAZE
13#include <iostream>
14#endif
15
16#include <algorithm>
17#include <iterator>
18
19#include "FTMSegmentation.h"
20
21using namespace std;
22using namespace ttk;
23using namespace ftm;
24
25// -------
26// Segment
27// -------
28
29Segment::Segment(SimplexId size) : vertices_(size, nullVertex) {
30}
31
33 return vertices_.begin();
34}
35
37 return vertices_.begin();
38}
39
41 list<vector<SimplexId>> &regularList,
42 const bool reverse) {
43 auto vectComp = [&](const vector<SimplexId> &a, const vector<SimplexId> &b) {
44 return s->isLower(a[0], b[0]);
45 };
46
47 SimplexId totalSize = 0;
48 for(const auto &vectReg : regularList) {
49 totalSize += vectReg.size();
50 }
51 vertices_.reserve(totalSize);
52 // TODO parallel
53 regularList.sort(vectComp);
54 // TODO parallel
55 if(reverse) {
56 for(auto it1 = regularList.cbegin(); it1 != regularList.cend(); ++it1) {
57 for(auto it2 = it1->crbegin(); it2 != it1->crend(); ++it2) {
58 vertices_.emplace_back(*it2);
59 }
60 }
61 } else {
62 for(auto it1 = regularList.cbegin(); it1 != regularList.cend(); ++it1) {
63 for(auto it2 = it1->cbegin(); it2 != it1->cend(); ++it2) {
64 vertices_.emplace_back(*it2);
65 }
66 }
67 }
68
69 regularList.clear();
70}
71
73 return vertices_.end();
74}
75
77 return vertices_.end();
78}
79
80SimplexId Segment::operator[](const size_t &idx) const {
81 return vertices_[idx];
82}
83
84SimplexId &Segment::operator[](const size_t &idx) {
85 return vertices_[idx];
86}
87
89 return vertices_.size();
90}
91
92void Segment::sort(const Scalars *s) {
93 // Sort by scalar value
94 auto comp = [&](SimplexId a, SimplexId b) { return s->isLower(a, b); };
95
96 std::sort(vertices_.begin(), vertices_.end(), comp);
97}
98
99// --------
100// Segments
101// --------
102
103Segments::Segments() = default;
104
106 segments_.clear();
107}
108
109const Segment &Segments::operator[](const size_t &idx) const {
110 return segments_[idx];
111}
112
113Segment &Segments::operator[](const size_t &idx) {
114 return segments_[idx];
115}
116
117void Segments::resize(const vector<SimplexId> &sizes) {
118#ifndef TTK_ENABLE_KAMIKAZE
119 if(segments_.size()) {
120 cerr << "Call reserve on an already reserved Segments! " << endl;
121 }
122#endif
123
124 segments_.reserve(sizes.size());
125 for(SimplexId const size : sizes) {
126 segments_.emplace_back(size);
127 }
128}
129
131 return segments_.size();
132}
133
135 const idSegment &nbSegments = size();
136
137 for(idSegment i = 0; i < nbSegments; i++) {
138#ifdef TTK_ENABLE_OPENMP
139#pragma omp task firstprivate(i)
140#endif
141 segments_[i].sort(s);
142 }
143#ifdef TTK_ENABLE_OPENMP
144#pragma omp taskwait
145#endif
146}
147
148// ----------
149// Arc Region
150// ----------
151#ifndef TTK_ENABLE_KAMIKAZE
153 segmented_ = false;
154}
155#else
156ArcRegion::ArcRegion() = default;
157#endif
158
162
164 segmentsIn_.emplace_front(Region{begin, end});
165}
166
168 for(const auto &reg : r.segmentsIn_) {
169 concat(reg.segmentBegin, reg.segmentEnd);
170 }
171}
172
174#ifndef TTK_ENABLE_KAMIKAZE
175 if(segmentation_.size()) {
176 cout << "createSegmentation called on an already segmented region" << endl;
177 }
178#endif
179
180 SimplexId totalSegmSize = 0;
181 vector<segm_const_it> heads, ends;
182 for(const auto &region : segmentsIn_) {
183 totalSegmSize += distance(region.segmentBegin, region.segmentEnd);
184 heads.emplace_back(region.segmentBegin);
185 ends.emplace_back(region.segmentEnd);
186 }
187
188 segmentation_.clear();
189 segmentation_.reserve(
190 totalSegmSize); // max size, including discarded vertices
191
192 idSegment nbSegments = heads.size();
193 int added = 0;
194
195 while(added != -1) {
196 added = -1;
197 SimplexId minVert = -1;
198 for(idSegment i = 0; i < nbSegments; i++) {
199 auto &headIt = heads[i];
200 const auto &endIt = ends[i];
201
202 if(headIt == endIt) {
203 // end of this area
204 heads.erase(heads.begin() + i);
205 ends.erase(ends.begin() + i);
206 --nbSegments;
207 --i;
208 continue;
209 }
210
211 if(added == -1 || s->isLower(*headIt, minVert)) {
212 minVert = *headIt;
213 added = i;
214 }
215 }
216 if(added != -1) {
217 segmentation_.emplace_back(minVert);
218 ++heads[added];
219 }
220 } // end while
221
222#ifndef TTK_ENABLE_KAMIKAZE
223 segmented_ = true;
224#endif
225}
226
228 const Scalars *s,
229 const vector<idCorresp> &vert2treeOther) const {
230 // split at v and return remaining vertices
231
232 auto comp = [s](SimplexId a, SimplexId b) { return s->isLower(a, b); };
233 SimplexId splitVert = nullVertex;
234 const bool chkOther = vert2treeOther.size() > 0;
235
236 for(const auto &reg : segmentsIn_) {
237 if(s->isEqLower(*reg.segmentBegin, v)
238 && s->isEqHigher(*(reg.segmentEnd - 1), v)) {
239 // is v is between beg/end
240 // append once
241 const auto &oldBeg = reg.segmentBegin;
242 auto posV = lower_bound(oldBeg, reg.segmentEnd, v, comp);
243
244 // posV == end() would mean v is not in this range (cf if in for)
245 if(posV != oldBeg && *posV != v) {
246 --posV;
247 }
248
249 if(chkOther) {
250 while(posV != oldBeg && vert2treeOther[*posV] == nullCorresp) {
251 --posV;
252 }
253 if(posV == oldBeg && vert2treeOther[*posV] == nullCorresp) {
254 continue;
255 }
256 }
257
258 if(posV != reg.segmentEnd) {
259 splitVert = *posV;
260 }
261
262 } else if(s->isLower(*(reg.segmentEnd - 1), v)) {
263 // reg is completely below v, we give it to remainingRegion
264 if(splitVert == nullVertex
265 || s->isHigher(*(reg.segmentEnd - 1), splitVert)) {
266 auto posV = reg.segmentEnd - 1;
267 if(chkOther) {
268 const auto &oldBeg = reg.segmentBegin;
269 while(posV != oldBeg && vert2treeOther[*posV] == nullCorresp) {
270 --posV;
271 }
272 if(((posV == oldBeg && vert2treeOther[*posV] != nullCorresp)
273 || posV != oldBeg)
274 && (splitVert == nullVertex || s->isHigher(*posV, splitVert))) {
275 splitVert = *posV;
276 }
277 } else {
278 splitVert = *posV;
279 }
280 }
281 }
282 }
283
284 return splitVert;
285}
286
288 const Region &other = r.segmentsIn_.front();
289 Region &self = segmentsIn_.front();
290
291 if(other.segmentBegin == self.segmentEnd) {
292 self.segmentEnd = other.segmentEnd;
293 return true;
294 } else if(other.segmentEnd == self.segmentBegin) {
295 self.segmentBegin = other.segmentBegin;
296 return true;
297 }
298
299 return false;
300}
301
302tuple<SimplexId, ArcRegion> ArcRegion::splitBack(SimplexId v,
303 const Scalars *s) {
304 // split at v and return remaining vertices
305
306 auto comp = [s](SimplexId a, SimplexId b) { return s->isLower(a, b); };
307 ArcRegion remainingRegion;
308 SimplexId splitVert = nullVertex;
309
310 list<decltype(segmentsIn_)::iterator> willErase;
311
312 for(decltype(segmentsIn_)::iterator it = segmentsIn_.begin();
313 it != segmentsIn_.end(); ++it) {
314 auto &reg = *it;
315 if(s->isEqLower(*reg.segmentBegin, v)
316 && s->isEqHigher(*(reg.segmentEnd - 1), v)) {
317 // is v is between beg/end
318 // append once
319 const auto &oldBeg = reg.segmentBegin;
320 auto posV = lower_bound(oldBeg, reg.segmentEnd, v, comp);
321
322 // posV == end() would mean v is not in this range (cf if in for)
323 if(posV != oldBeg && *posV != v) {
324 --posV;
325 }
326
327 if(posV != oldBeg) {
328 remainingRegion.concat(oldBeg, posV);
329 }
330
331 if(posV == reg.segmentEnd) {
332 willErase.emplace_back(it);
333 } else {
334 splitVert = *posV;
335 reg.segmentBegin = posV;
336 }
337
338 } else if(s->isLower(*(reg.segmentEnd - 1), v)) {
339 // reg is completely below v, we give it to remainingRegion
340 remainingRegion.concat(reg.segmentBegin, reg.segmentEnd);
341 willErase.emplace_back(it);
342 if(splitVert == nullVertex
343 || s->isHigher(*(reg.segmentEnd - 1), splitVert)) {
344 splitVert = *(reg.segmentEnd - 1);
345 }
346 }
347 }
348
349 // remove in this arc segments that have been moved in remaining
350 for(auto &tmpIt : willErase) {
351 segmentsIn_.erase(tmpIt);
352 }
353
354 return make_tuple(splitVert, remainingRegion);
355}
356
357tuple<SimplexId, ArcRegion> ArcRegion::splitFront(SimplexId v,
358 const Scalars *s) {
359 // this function does not create empty region
360
361 auto comp = [s](SimplexId a, SimplexId b) { return s->isLower(a, b); };
362 ArcRegion remainingRegion;
363 SimplexId splitVert = nullVertex;
364
365 list<decltype(segmentsIn_)::iterator> willErase;
366
367 for(decltype(segmentsIn_)::iterator it = segmentsIn_.begin();
368 it != segmentsIn_.end(); ++it) {
369 auto &reg = *it;
370 if(s->isEqLower(*reg.segmentBegin, v)
371 && s->isEqHigher(*(reg.segmentEnd - 1), v)) {
372 // is v is between beg/end
373 // append once
374 const auto &oldEnd = reg.segmentEnd;
375 auto posV = lower_bound(reg.segmentBegin, oldEnd, v, comp);
376
377 if(posV != oldEnd) {
378 splitVert = *posV;
379 remainingRegion.concat(posV, oldEnd);
380 }
381
382 if(posV == reg.segmentBegin) {
383 willErase.emplace_back(it);
384 } else {
385 reg.segmentEnd = posV;
386 }
387
388 } else if(s->isHigher(*reg.segmentBegin, v)) {
389 // reg is completely above v, we give it to remainingRegion
390 remainingRegion.concat(reg.segmentBegin, reg.segmentEnd);
391 willErase.emplace_back(it);
392 if(splitVert == nullVertex || s->isLower(*reg.segmentBegin, splitVert)) {
393 // we ignore vertices that does not come from this arc
394 splitVert = *reg.segmentBegin;
395 }
396 }
397 }
398
399 // remove in this arc segments that have been moved in remaining
400 for(auto &tmpIt : willErase) {
401 segmentsIn_.erase(tmpIt);
402 }
403
404 return make_tuple(splitVert, remainingRegion);
405}
bool merge(const ArcRegion &r)
decltype(segmentation_) ::iterator end()
std::tuple< SimplexId, ArcRegion > splitFront(SimplexId v, const Scalars *s)
SimplexId findBelow(SimplexId v, const Scalars *s, const std::vector< idCorresp > &vert2treeOther=std::vector< idCorresp >()) const
void createSegmentation(const Scalars *s)
void concat(const segm_it &begin, const segm_it &end)
decltype(segmentation_) ::iterator begin()
std::tuple< SimplexId, ArcRegion > splitBack(SimplexId v, const Scalars *s)
segm_const_it begin() const
SimplexId operator[](const size_t &idx) const
void createFromList(const Scalars *s, std::list< std::vector< SimplexId > > &regularsList, const bool reverse)
segm_const_it end() const
Segment(SimplexId size)
void sort(const Scalars *s)
SimplexId size() const
idSegment size() const
void sortAll(const Scalars *s)
Segment & operator[](const size_t &idx)
void resize(const std::vector< SimplexId > &sizes)
idSuperArc idSegment
for the segmentation, we have an array of segment containing area of the mesh
std::vector< SimplexId >::iterator segm_it
std::vector< SimplexId >::const_iterator segm_const_it
The Topology ToolKit.
int SimplexId
Identifier type for simplices of any dimension.
Definition DataTypes.h:22
T end(std::pair< T, T > &p)
Definition ripserpy.cpp:472
T begin(std::pair< T, T > &p)
Definition ripserpy.cpp:468
bool isEqLower(const SimplexId a, const SimplexId b) const
bool isLower(const SimplexId a, const SimplexId b) const
bool isHigher(const SimplexId a, const SimplexId b) const
bool isEqHigher(const SimplexId a, const SimplexId b) const