forked from ufz/ogs
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathPolyline.h
250 lines (197 loc) · 7.67 KB
/
Polyline.h
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
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
/**
* \file
* \author Thomas Fischer
* \date 2010-01-14
* \brief Definition of the PolyLine class.
*
* \copyright
* Copyright (c) 2012-2023, OpenGeoSys Community (http://www.opengeosys.org)
* Distributed under a Modified BSD License.
* See accompanying file LICENSE.txt or
* http://www.opengeosys.org/project/license
*
*/
#pragma once
#include <cmath>
#include <vector>
// GeoLib
#include "GeoObject.h"
#include "LineSegment.h"
#include "Point.h"
// MathLib
#include "MathLib/Point3d.h"
namespace GeoLib
{
class PointVec;
/**
* \ingroup GeoLib
*
* \brief Class Polyline consists mainly of a reference to a point vector and
* a vector that stores the indices in the point vector.
* A polyline consists of at least one line segment. The polyline is specified by the points
* of the line segments. The class Polyline stores ids of pointers to the points in the
* _ply_pnt_ids vector.
* */
class Polyline : public GeoObject
{
public:
class SegmentIterator final
{
public:
using iterator_category = std::forward_iterator_tag;
using value_type = LineSegment;
using difference_type = std::ptrdiff_t;
using pointer = LineSegment*;
using reference = LineSegment&;
explicit SegmentIterator(Polyline const& polyline,
std::size_t segment_number);
SegmentIterator(SegmentIterator const& src);
SegmentIterator() = delete;
~SegmentIterator() = default;
SegmentIterator& operator=(SegmentIterator const& rhs);
std::size_t getSegmentNumber() const;
SegmentIterator& operator++();
LineSegment operator*() const;
LineSegment operator*();
bool operator==(SegmentIterator const& other) const;
bool operator!=(SegmentIterator const& other) const;
SegmentIterator& operator+=(std::vector<GeoLib::Point>::difference_type n);
SegmentIterator operator+(std::vector<GeoLib::Point>::difference_type n);
SegmentIterator& operator-=(std::vector<GeoLib::Point>::difference_type n);
SegmentIterator operator-(std::vector<GeoLib::Point>::difference_type n);
private:
GeoLib::Polyline const* _polyline;
std::vector<GeoLib::Point*>::size_type _segment_number;
};
friend class Polygon;
/** constructor
* \param pnt_vec a reference to the point vector
*/
explicit Polyline(const std::vector<Point*>& pnt_vec);
/**
* Copy constructor
* \param ply Polyline
*/
Polyline(const Polyline& ply);
Polyline& operator=(Polyline const& other) = delete;
~Polyline() override = default;
/// return a geometry type
GEOTYPE getGeoType() const override { return GEOTYPE::POLYLINE; }
/**
* Adds an id of a point at the end of the polyline if and only if the
* resulting segment won't be empty. The id have to be inside the (internal)
* \c _ply_pnts vector the polyline is based on.
* \return If the point could be added the return value is \c true. If the
* addition of the point would result in empty line segment \c false is
* returned.
*/
virtual bool addPoint(std::size_t pnt_id);
/**
* Method inserts a new point (that have to be inside the _ply_pnts vector)
* at the given position in the polyline if and only if the resulting
* segments won't be empty.
* \param pos the position in the polyline, pos have to be a value into the
* interval [0, number of points)
* \param pnt_id the id of the new point in the vector of points the
* polyline is based on
* \return true if the point could be inserted, else false (if empty line
* segments would be created).
*/
virtual bool insertPoint(std::size_t pos, std::size_t pnt_id);
/**
* Method removes a point from the polyline. The connecting line segments
* will be removed and the length of the polyline will be changed.
* \param pos a valid position within the polyline
*/
void removePoint(std::size_t pos);
/**
* Closes a polyline by adding a line segment that connects start- and end-point.
*/
void closePolyline();
/// Constructs one polyline from a vector of connected polylines.
/// All polylines in this vector need to reference the same point vector.
static Polyline* constructPolylineFromSegments(const std::vector<Polyline*> &ply_vec,
double prox = 0.0);
/**
* returns the number of points,
* the number of segments is about one smaller
* */
std::size_t getNumberOfPoints() const;
std::size_t getNumberOfSegments() const;
/** returns true if the polyline is closed */
bool isClosed() const;
/** returns true if the polyline is coplanar */
bool isCoplanar() const;
/**
* Method tests if the given id of a point (within the vector of points the
* polyline is based on) is inside the polyline.
* \param pnt_id the id of the point
* \return true if the point is part of the polyline, else false
*/
bool isPointIDInPolyline(std::size_t pnt_id) const;
/**
* returns the index of the i-th polyline point
* in the point vector
*/
std::size_t getPointID(std::size_t const i) const;
/**
* Changes a point index for one point in a line
* \param idx Index of point in line
* \param id ID of point in PointVec object
*/
void setPointID(std::size_t idx, std::size_t id);
/**
* \brief returns the i-th point contained in the polyline
* */
const Point* getPoint(std::size_t i) const;
SegmentIterator begin() const
{
return SegmentIterator(*this, 0);
}
SegmentIterator end() const
{
return SegmentIterator(*this, getNumberOfSegments());
}
std::vector<Point*> const& getPointsVec () const;
/**
* returns the distance along the polyline from the beginning of the
* polyline
* \param pnt the point on the polyline
* \param epsilon_radius the epsilon
* \return the distance along the polyline between the given point and the
* beginning of the polyline. If the given point is not on the
* polyine, negative value is returned.
*/
double getDistanceAlongPolyline(const MathLib::Point3d& pnt,
const double epsilon_radius) const;
protected:
/** a reference to the vector of pointers to the geometric points */
const std::vector<Point*> &_ply_pnts;
void reverseOrientation();
std::vector<std::size_t> const& getPolylinePointIDs() const
{
return _ply_pnt_ids;
}
private:
/** position of pointers to the geometric points */
std::vector<std::size_t> _ply_pnt_ids;
LineSegment getSegment(std::size_t i) const;
};
bool containsEdge (const Polyline& ply, std::size_t id0, std::size_t id1);
/// Resets the point IDs of the polyline corresponding to the mapping.
void resetPointIDs(Polyline& polyline, std::vector<std::size_t> const& mapping);
/// Resets the point IDs of the polyline corresponding to the mapping.
void markUsedPoints(Polyline const& polyline, std::vector<bool>& used_points);
/**
* comparison operator
* \param lhs first polyline
* \param rhs second polyline
* \return true, if the polylines consists of the same sequence of line segments
*/
bool operator==(Polyline const& lhs, Polyline const& rhs);
bool pointsAreIdentical(const std::vector<Point*> &pnt_vec, std::size_t i, std::size_t j,
double prox);
/// Create a polyline from given point ids.
std::unique_ptr<Polyline> createPolyline(GeoLib::PointVec const& points_vec,
std::vector<std::size_t>&& point_ids);
} // namespace GeoLib