OGS
Polyline.cpp
Go to the documentation of this file.
1
15#include "Polyline.h"
16
17#include <algorithm>
18
19#include "AnalyticalGeometry.h"
20#include "BaseLib/Error.h"
21#include "BaseLib/Logging.h"
23#include "MathLib/MathTools.h"
24#include "PointVec.h"
25
26namespace GeoLib
27{
28Polyline::Polyline(const std::vector<Point*>& pnt_vec) : _ply_pnts(pnt_vec) {}
29
31 : _ply_pnts(ply._ply_pnts), _ply_pnt_ids(ply._ply_pnt_ids)
32{
33}
34
35bool Polyline::addPoint(std::size_t pnt_id)
36{
37 if (pnt_id >= _ply_pnts.size())
38 {
39 return false;
40 }
41 std::size_t const n_pnts(_ply_pnt_ids.size());
42
43 // don't insert point if this would result in identical IDs for two adjacent
44 // points
45 if (n_pnts > 0 && _ply_pnt_ids.back() == pnt_id)
46 {
47 return false;
48 }
49
50 _ply_pnt_ids.push_back(pnt_id);
51
52 return true;
53}
54
55bool Polyline::insertPoint(std::size_t pos, std::size_t pnt_id)
56{
57 if (pnt_id >= _ply_pnts.size())
58 {
59 return false;
60 }
61 if (pos > _ply_pnt_ids.size())
62 {
63 return false;
64 }
65
66 if (pos == _ply_pnt_ids.size())
67 {
68 return addPoint(pnt_id);
69 }
70
71 // check if inserting pnt_id would result in two identical IDs for adjacent
72 // points
73 if (pos == 0 && pnt_id == _ply_pnt_ids[0])
74 {
75 return false;
76 }
77 if (pos != 0)
78 {
79 if (pos == (_ply_pnt_ids.size() - 1) && pnt_id == _ply_pnt_ids[pos])
80 {
81 return false;
82 }
83 if (pnt_id == _ply_pnt_ids[pos - 1] || pnt_id == _ply_pnt_ids[pos])
84 {
85 return false;
86 }
87 }
88
89 auto const pos_dt(
90 static_cast<std::vector<std::size_t>::difference_type>(pos));
91 auto it(_ply_pnt_ids.begin() + pos_dt);
92 _ply_pnt_ids.insert(it, pnt_id);
93
94 return true;
95}
96
97void Polyline::removePoint(std::size_t pos)
98{
99 if (pos >= _ply_pnt_ids.size())
100 {
101 return;
102 }
103
104 auto const pos_dt(
105 static_cast<std::vector<std::size_t>::difference_type>(pos));
106 _ply_pnt_ids.erase(_ply_pnt_ids.begin() + pos_dt);
107}
108
110{
111 return _ply_pnt_ids.size();
112}
113
115{
116 return _ply_pnt_ids.empty() ? 0 : _ply_pnt_ids.size() - 1;
117}
118
120{
121 if (_ply_pnt_ids.size() < 3)
122 {
123 return false;
124 }
125
126 return _ply_pnt_ids.front() == _ply_pnt_ids.back();
127}
128
130{
131 std::size_t const n_points(_ply_pnt_ids.size());
132 if (n_points < 4)
133 {
134 return true;
135 }
136
137 GeoLib::Point const& p0(*this->getPoint(0));
138 GeoLib::Point const& p1(*this->getPoint(1));
139 GeoLib::Point const& p2(*this->getPoint(2));
140 for (std::size_t i = 3; i < n_points; ++i)
141 {
142 if (!MathLib::isCoplanar(p0, p1, p2, *this->getPoint(i)))
143 {
144 DBUG(
145 "Point {:d} is not coplanar to the first three points of the "
146 "line.",
147 i);
148 return false;
149 }
150 }
151 return true;
152}
153
154bool Polyline::isPointIDInPolyline(std::size_t pnt_id) const
155{
156 return std::find(_ply_pnt_ids.begin(), _ply_pnt_ids.end(), pnt_id) !=
157 _ply_pnt_ids.end();
158}
159
160std::size_t Polyline::getPointID(std::size_t i) const
161{
162 assert(i < _ply_pnt_ids.size());
163 return _ply_pnt_ids[i];
164}
165
167{
168 assert(i < getNumberOfSegments());
170 _ply_pnts[_ply_pnt_ids[i + 1]], false);
171}
172
173void Polyline::setPointID(std::size_t idx, std::size_t id)
174{
175 assert(idx < _ply_pnt_ids.size());
176 _ply_pnt_ids[idx] = id;
177}
178
179const Point* Polyline::getPoint(std::size_t i) const
180{
181 assert(i < _ply_pnt_ids.size());
182 return _ply_pnts[_ply_pnt_ids[i]];
183}
184
185std::vector<Point*> const& Polyline::getPointsVec() const
186{
187 return _ply_pnts;
188}
189
191 const std::vector<Polyline*>& ply_vec, double prox)
192{
193 std::size_t nLines = ply_vec.size();
194
195 auto* new_ply = new Polyline(*ply_vec[0]);
196 std::vector<GeoLib::Point*> pnt_vec(new_ply->getPointsVec());
197
198 std::vector<Polyline*> local_ply_vec;
199 for (std::size_t i = 1; i < nLines; i++)
200 {
201 local_ply_vec.push_back(ply_vec[i]);
202 }
203
204 while (!local_ply_vec.empty())
205 {
206 bool ply_found(false);
207 prox *= prox; // square distance once to save time later
208 for (auto it = local_ply_vec.begin(); it != local_ply_vec.end(); ++it)
209 {
210 if (pnt_vec == (*it)->getPointsVec())
211 {
212 std::size_t nPoints((*it)->getNumberOfPoints());
213
214 // if (new_ply->getPointID(0) == (*it)->getPointID(0))
215 if (pointsAreIdentical(pnt_vec, new_ply->getPointID(0),
216 (*it)->getPointID(0), prox))
217 {
218 auto* tmp = new Polyline((*it)->getPointsVec());
219 for (std::size_t k = 0; k < nPoints; k++)
220 {
221 tmp->addPoint((*it)->getPointID(nPoints - k - 1));
222 }
223
224 std::size_t new_ply_size(new_ply->getNumberOfPoints());
225 for (std::size_t k = 1; k < new_ply_size; k++)
226 {
227 tmp->addPoint(new_ply->getPointID(k));
228 }
229 delete new_ply;
230 new_ply = tmp;
231 ply_found = true;
232 }
233 // else if (new_ply->getPointID(0) ==
234 // (*it)->getPointID(nPoints-1))
235 else if (pointsAreIdentical(pnt_vec, new_ply->getPointID(0),
236 (*it)->getPointID(nPoints - 1),
237 prox))
238 {
239 auto* tmp = new Polyline(**it);
240 std::size_t new_ply_size(new_ply->getNumberOfPoints());
241 for (std::size_t k = 1; k < new_ply_size; k++)
242 {
243 tmp->addPoint(new_ply->getPointID(k));
244 }
245 delete new_ply;
246 new_ply = tmp;
247 ply_found = true;
248 }
249 // else if (new_ply->getPointID(new_ply->getNumberOfPoints()-1)
250 // == (*it)->getPointID(0))
251 else if (pointsAreIdentical(
252 pnt_vec,
253 new_ply->getPointID(new_ply->getNumberOfPoints() -
254 1),
255 (*it)->getPointID(0), prox))
256 {
257 for (std::size_t k = 1; k < nPoints; k++)
258 {
259 new_ply->addPoint((*it)->getPointID(k));
260 }
261 ply_found = true;
262 }
263 // else if (new_ply->getPointID(new_ply->getNumberOfPoints()-1)
264 // == (*it)->getPointID(nPoints-1))
265 else if (pointsAreIdentical(
266 pnt_vec,
267 new_ply->getPointID(new_ply->getNumberOfPoints() -
268 1),
269 (*it)->getPointID(nPoints - 1), prox))
270 {
271 for (std::size_t k = 1; k < nPoints; k++)
272 {
273 new_ply->addPoint((*it)->getPointID(nPoints - k - 1));
274 }
275 ply_found = true;
276 }
277 if (ply_found)
278 {
279 local_ply_vec.erase(it);
280 break;
281 }
282 }
283 else
284 {
285 ERR("Error in Polyline::contructPolylineFromSegments() - Line "
286 "segments use different point vectors.");
287 }
288 }
289
290 if (!ply_found)
291 {
292 ERR("Error in Polyline::contructPolylineFromSegments() - Not all "
293 "segments are connected.");
294 delete new_ply;
295 new_ply = nullptr;
296 break;
297 }
298 }
299 return new_ply;
300}
301
303{
304 if (getNumberOfPoints() < 2)
305 {
306 ERR("Polyline::closePolyline(): Input polyline needs to be composed of "
307 "at least three points.");
308 }
309 if (!isClosed())
310 {
312 }
313}
314
316 const double epsilon_radius) const
317{
318 double dist(-1.0);
319 double lambda;
320 bool found = false;
321 double act_length_of_ply = 0.0;
322 // loop over all line segments of the polyline
323 for (std::size_t k = 0; k < getNumberOfSegments(); k++)
324 {
325 auto const& a = getPoint(k)->asEigenVector3d();
326 auto const& b = getPoint(k + 1)->asEigenVector3d();
327 double const seg_length((b - a).norm());
328 act_length_of_ply += seg_length;
329 // is the orthogonal projection of the j-th node to the
330 // line g(lambda) = _ply->getPoint(k) + lambda * (_ply->getPoint(k+1) -
331 // _ply->getPoint(k)) at the k-th line segment of the polyline, i.e. 0
332 // <= lambda <= 1?
334 *getPoint(k + 1), lambda,
335 dist) <= epsilon_radius)
336 {
337 double const lower_lambda(-epsilon_radius / seg_length);
338 double const upper_lambda(1 + epsilon_radius / seg_length);
339
340 if (lower_lambda <= lambda && lambda <= upper_lambda)
341 {
342 found = true;
343 dist = act_length_of_ply + dist;
344 break;
345 } // end if lambda
346 }
347 } // end line segment loop
348
349 if (!found)
350 {
351 dist = -1.0;
352 }
353 return dist;
354}
355
357{
358 std::reverse(_ply_pnt_ids.begin(), _ply_pnt_ids.end());
359}
360
362 std::size_t segment_number)
363 : _polyline(&polyline),
364 _segment_number(
365 static_cast<std::vector<GeoLib::Point*>::size_type>(segment_number))
366{
367}
368
370 : _polyline(src._polyline), _segment_number(src._segment_number)
371{
372}
373
375 SegmentIterator const& rhs)
376{
377 if (&rhs == this)
378 {
379 return *this;
380 }
381
382 _polyline = rhs._polyline;
383 _segment_number = rhs._segment_number;
384 return *this;
385}
386
388{
389 return static_cast<std::size_t>(_segment_number);
390}
391
393{
394 ++_segment_number;
395 return *this;
396}
397
399{
400 return _polyline->getSegment(_segment_number);
401}
402
404{
405 return _polyline->getSegment(_segment_number);
406}
407
409{
410 return !(*this != other);
411}
412
414{
415 return other._segment_number != _segment_number ||
416 other._polyline != _polyline;
417}
418
420 std::vector<GeoLib::Point>::difference_type n)
421{
422 if (n < 0)
423 {
424 _segment_number -=
425 static_cast<std::vector<GeoLib::Point>::size_type>(-n);
426 }
427 else
428 {
429 _segment_number +=
430 static_cast<std::vector<GeoLib::Point>::size_type>(n);
431 }
432 if (_segment_number > _polyline->getNumberOfSegments())
433 {
434 OGS_FATAL("");
435 }
436 return *this;
437}
438
440 std::vector<GeoLib::Point>::difference_type n)
441{
442 SegmentIterator t(*this);
443 t += n;
444 return t;
445}
446
448 std::vector<GeoLib::Point>::difference_type n)
449{
450 if (n >= 0)
451 {
452 _segment_number -=
453 static_cast<std::vector<GeoLib::Point>::size_type>(n);
454 }
455 else
456 {
457 _segment_number +=
458 static_cast<std::vector<GeoLib::Point>::size_type>(-n);
459 }
460 if (_segment_number > _polyline->getNumberOfSegments())
461 {
462 OGS_FATAL("");
463 }
464 return *this;
465}
466
468 std::vector<GeoLib::Point>::difference_type n)
469{
471 t -= n;
472 return t;
473}
474
475void resetPointIDs(Polyline& polyline, std::vector<std::size_t> const& mapping)
476{
477 if (polyline.getPointsVec().size() != mapping.size())
478 {
479 OGS_FATAL(
480 "internal error in resetPointIDs(): polyline based on point vector "
481 "of size {}, given mapping has size {}",
482 polyline.getPointsVec().size(), mapping.size());
483 }
484 for (std::size_t i = 0; i < polyline.getNumberOfPoints(); ++i)
485 {
486 polyline.setPointID(i, mapping[polyline.getPointID(i)]);
487 }
488}
489
490void markUsedPoints(Polyline const& polyline, std::vector<bool>& used_points)
491{
492 if (polyline.getPointsVec().size() != used_points.size())
493 {
494 OGS_FATAL(
495 "internal error in markUsedPoints(): polyline based on point "
496 "vector of size {}, given used_points has size {}",
497 polyline.getPointsVec().size(), used_points.size());
498 }
499 for (std::size_t i = 0; i < polyline.getNumberOfPoints(); ++i)
500 {
501 used_points[polyline.getPointID(i)] = true;
502 }
503}
504
505bool containsEdge(const Polyline& ply, std::size_t id0, std::size_t id1)
506{
507 if (id0 == id1)
508 {
509 ERR("no valid edge id0 == id1 == {:d}.", id0);
510 return false;
511 }
512 if (id0 > id1)
513 {
514 std::swap(id0, id1);
515 }
516 const std::size_t n(ply.getNumberOfPoints() - 1);
517 for (std::size_t k(0); k < n; k++)
518 {
519 std::size_t ply_pnt0(ply.getPointID(k));
520 std::size_t ply_pnt1(ply.getPointID(k + 1));
521 if (ply_pnt0 > ply_pnt1)
522 {
523 std::swap(ply_pnt0, ply_pnt1);
524 }
525 if (ply_pnt0 == id0 && ply_pnt1 == id1)
526 {
527 return true;
528 }
529 }
530 return false;
531}
532
533bool operator==(Polyline const& lhs, Polyline const& rhs)
534{
535 if (lhs.getNumberOfPoints() != rhs.getNumberOfPoints())
536 {
537 return false;
538 }
539
540 const std::size_t n(lhs.getNumberOfPoints());
541 for (std::size_t k(0); k < n; k++)
542 {
543 if (lhs.getPointID(k) != rhs.getPointID(k))
544 {
545 return false;
546 }
547 }
548
549 return true;
550}
551
552bool pointsAreIdentical(const std::vector<Point*>& pnt_vec,
553 std::size_t i,
554 std::size_t j,
555 double prox)
556{
557 if (i == j)
558 {
559 return true;
560 }
561 return MathLib::sqrDist(*pnt_vec[i], *pnt_vec[j]) < prox;
562}
563
564std::unique_ptr<Polyline> createPolyline(GeoLib::PointVec const& points_vec,
565 std::vector<std::size_t>&& point_ids)
566{
567 auto const& point_id_map = points_vec.getIDMap();
568 auto polyline = std::make_unique<Polyline>(points_vec.getVector());
569 for (auto point_id : point_ids)
570 {
571 if (point_id >= point_id_map.size())
572 {
573 WARN("The point id {} doesn't exist in the underlying PointVec.",
574 point_id);
575 continue;
576 }
577 polyline->addPoint(point_id_map[point_id]);
578 }
579 return polyline;
580}
581} // end namespace GeoLib
Definition of analytical geometry functions.
#define OGS_FATAL(...)
Definition Error.h:26
void DBUG(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:30
void ERR(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:45
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of the PointVec class.
Definition of the PolyLine class.
This class manages pointers to Points in a std::vector along with a name. It also handles the deletio...
Definition PointVec.h:36
const std::vector< std::size_t > & getIDMap() const
Definition PointVec.h:94
GeoLib::Polyline const * _polyline
Definition Polyline.h:86
SegmentIterator & operator++()
Definition Polyline.cpp:392
SegmentIterator operator-(std::vector< GeoLib::Point >::difference_type n)
Definition Polyline.cpp:467
SegmentIterator & operator+=(std::vector< GeoLib::Point >::difference_type n)
Definition Polyline.cpp:419
LineSegment operator*() const
Definition Polyline.cpp:398
SegmentIterator & operator=(SegmentIterator const &rhs)
Definition Polyline.cpp:374
bool operator==(SegmentIterator const &other) const
Definition Polyline.cpp:408
SegmentIterator operator+(std::vector< GeoLib::Point >::difference_type n)
Definition Polyline.cpp:439
std::vector< GeoLib::Point * >::size_type _segment_number
Definition Polyline.h:87
std::size_t getSegmentNumber() const
Definition Polyline.cpp:387
bool operator!=(SegmentIterator const &other) const
Definition Polyline.cpp:413
SegmentIterator & operator-=(std::vector< GeoLib::Point >::difference_type n)
Definition Polyline.cpp:447
Class Polyline consists mainly of a reference to a point vector and a vector that stores the indices ...
Definition Polyline.h:40
double getDistanceAlongPolyline(const MathLib::Point3d &pnt, const double epsilon_radius) const
Definition Polyline.cpp:315
std::size_t getPointID(std::size_t const i) const
Definition Polyline.cpp:160
std::size_t getNumberOfSegments() const
Definition Polyline.cpp:114
static Polyline * constructPolylineFromSegments(const std::vector< Polyline * > &ply_vec, double prox=0.0)
Definition Polyline.cpp:190
std::size_t getNumberOfPoints() const
Definition Polyline.cpp:109
const Point * getPoint(std::size_t i) const
returns the i-th point contained in the polyline
Definition Polyline.cpp:179
virtual bool insertPoint(std::size_t pos, std::size_t pnt_id)
Definition Polyline.cpp:55
std::vector< std::size_t > _ply_pnt_ids
Definition Polyline.h:222
void setPointID(std::size_t idx, std::size_t id)
Definition Polyline.cpp:173
void reverseOrientation()
Definition Polyline.cpp:356
bool isClosed() const
Definition Polyline.cpp:119
virtual bool addPoint(std::size_t pnt_id)
Definition Polyline.cpp:35
const std::vector< Point * > & _ply_pnts
Definition Polyline.h:211
LineSegment getSegment(std::size_t i) const
Definition Polyline.cpp:166
Polyline(const std::vector< Point * > &pnt_vec)
Definition Polyline.cpp:28
bool isPointIDInPolyline(std::size_t pnt_id) const
Definition Polyline.cpp:154
bool isCoplanar() const
Definition Polyline.cpp:129
void removePoint(std::size_t pos)
Definition Polyline.cpp:97
std::vector< Point * > const & getPointsVec() const
Definition Polyline.cpp:185
std::vector< T * > const & getVector() const
Eigen::Vector3d const & asEigenVector3d() const
Definition Point3d.h:63
bool containsEdge(const Polyline &ply, std::size_t id0, std::size_t id1)
Definition Polyline.cpp:505
bool pointsAreIdentical(const std::vector< Point * > &pnt_vec, std::size_t i, std::size_t j, double prox)
Definition Polyline.cpp:552
void markUsedPoints(Polyline const &polyline, std::vector< bool > &used_points)
Resets the point IDs of the polyline corresponding to the mapping.
Definition Polyline.cpp:490
void resetPointIDs(Polyline &polyline, std::vector< std::size_t > const &mapping)
Resets the point IDs of the polyline corresponding to the mapping.
Definition Polyline.cpp:475
bool operator==(LineSegment const &s0, LineSegment const &s1)
std::unique_ptr< Polyline > createPolyline(GeoLib::PointVec const &points_vec, std::vector< std::size_t > &&point_ids)
Create a polyline from given point ids.
Definition Polyline.cpp:564
bool isCoplanar(const MathLib::Point3d &a, const MathLib::Point3d &b, const MathLib::Point3d &c, const MathLib::Point3d &d)
Checks if the four given points are located on a plane.
double calcProjPntToLineAndDists(Point3d const &pp, Point3d const &pa, Point3d const &pb, double &lambda, double &d0)
Definition MathTools.cpp:19
double sqrDist(MathLib::Point3d const &p0, MathLib::Point3d const &p1)
Definition Point3d.cpp:26