OGS
PointVec.cpp
Go to the documentation of this file.
1
13#include "PointVec.h"
14
15#include <numeric>
16
17#include "BaseLib/Logging.h"
18#include "MathLib/MathTools.h"
19
20namespace GeoLib
21{
22PointVec::PointVec(std::string const& name, std::vector<Point*>&& points,
23 NameIdMap&& name_id_map, PointType const type,
24 double const rel_eps)
25 : TemplateVec<Point>(name, std::move(points), std::move(name_id_map)),
26 _type(type),
27 _aabb(_data_vec.begin(), _data_vec.end()),
28 _rel_eps(rel_eps * (_aabb.getMaxPoint() - _aabb.getMinPoint()).norm()),
29 _oct_tree(OctTree<GeoLib::Point, 16>::createOctTree(
30 _aabb.getMinPoint(), _aabb.getMaxPoint(), _rel_eps))
31{
32 std::size_t const number_of_all_input_pnts(_data_vec.size());
33
34 // correct the ids if necessary
35 for (std::size_t k(0); k < _data_vec.size(); ++k)
36 {
37 if (_data_vec[k]->getID() == std::numeric_limits<std::size_t>::max())
38 {
39 _data_vec[k]->setID(k);
40 }
41 }
42
43 std::vector<std::size_t> rm_pos;
44 // add all points in the oct tree in order to make them unique
45 _pnt_id_map.resize(number_of_all_input_pnts);
46 std::iota(_pnt_id_map.begin(), _pnt_id_map.end(), 0);
47 GeoLib::Point* ret_pnt(nullptr);
48 for (std::size_t k(0); k < _data_vec.size(); ++k)
49 {
50 GeoLib::Point* const pnt(_data_vec[k]);
51 if (!_oct_tree->addPoint(pnt, ret_pnt))
52 {
53 assert(ret_pnt != nullptr);
54 _pnt_id_map[pnt->getID()] = ret_pnt->getID();
55 rm_pos.push_back(k);
56 delete _data_vec[k];
57 _data_vec[k] = nullptr;
58 }
59 else
60 {
61 _pnt_id_map[k] = pnt->getID();
62 }
63 }
64
65 auto const data_vec_end =
66 std::remove(_data_vec.begin(), _data_vec.end(), nullptr);
67 _data_vec.erase(data_vec_end, _data_vec.end());
68
69 // decrement the ids according to the number of removed points (==k) before
70 // the j-th point (positions of removed points are stored in the vector
71 // rm_pos)
72 for (std::size_t k(1); k < rm_pos.size(); ++k)
73 {
74 // decrement the ids in the interval [rm_pos[k-1]+1, rm_pos[k])
75 for (std::size_t j(rm_pos[k - 1] + 1); j < rm_pos[k]; ++j)
76 {
77 _pnt_id_map[j] -= k;
78 }
79 }
80 // decrement the ids from rm_pos.back()+1 until the end of _pnt_id_map
81 if (!rm_pos.empty())
82 {
83 for (std::size_t j(rm_pos.back() + 1); j < _pnt_id_map.size(); ++j)
84 {
85 _pnt_id_map[j] -= rm_pos.size();
86 }
87 }
88 // decrement the ids within the _pnt_id_map at positions of the removed
89 // points
90 for (std::size_t k(1); k < rm_pos.size(); ++k)
91 {
92 std::size_t cnt(0);
93 for (cnt = 0;
94 cnt < rm_pos.size() && _pnt_id_map[rm_pos[k]] > rm_pos[cnt];)
95 {
96 cnt++;
97 }
98 _pnt_id_map[rm_pos[k]] -= cnt;
99 }
100
101 // set value of the point id to the position of the point within _data_vec
102 for (std::size_t k(0); k < _data_vec.size(); ++k)
103 {
104 _data_vec[k]->setID(k);
105 }
106
107 if (number_of_all_input_pnts > _data_vec.size())
108 {
109 WARN("PointVec::PointVec(): there are {:d} double points.",
110 number_of_all_input_pnts - _data_vec.size());
111 }
112
114 // create the inverse mapping
115 _id_to_name_map.resize(_data_vec.size());
116 // fetch the names from the name id map
117 for (auto& [point_name, id] : _name_id_map)
118 {
119 if (id >= _id_to_name_map.size())
120 {
121 continue;
122 }
123 _id_to_name_map[id] = point_name;
124 }
125}
126
127PointVec::PointVec(std::string const& name, std::vector<Point*>&& points,
128 PointType const type, double const rel_eps)
129 : PointVec(name, std::move(points), NameIdMap{}, type, rel_eps)
130{
131}
132
133std::size_t PointVec::push_back(Point* pnt)
134{
136 _id_to_name_map.emplace_back("");
137 return _pnt_id_map[_pnt_id_map.size() - 1];
138}
139
140void PointVec::push_back(Point* pnt, std::string const* const name)
141{
142 if (name == nullptr)
143 {
144 _pnt_id_map.push_back(uniqueInsert(pnt));
145 _id_to_name_map.emplace_back("");
146 return;
147 }
148
149 std::map<std::string, std::size_t>::const_iterator it(
150 _name_id_map.find(*name));
151 if (it != _name_id_map.end())
152 {
153 _id_to_name_map.emplace_back("");
154 WARN("PointVec::push_back(): two points share the name {:s}.",
155 name->c_str());
156 return;
157 }
158
159 std::size_t id(uniqueInsert(pnt));
160 _pnt_id_map.push_back(id);
161 _name_id_map[*name] = id;
162 _id_to_name_map.push_back(*name);
163}
164
166{
167 GeoLib::Point* ret_pnt(nullptr);
168 if (_oct_tree->addPoint(pnt, ret_pnt))
169 {
170 // set value of the point id to the position of the point within
171 // _data_vec
172 pnt->setID(_data_vec.size());
173 _data_vec.push_back(pnt);
174 return _data_vec.size() - 1;
175 }
176
177 // pnt is outside of OctTree object
178 if (ret_pnt == nullptr)
179 {
180 // update the axis aligned bounding box
181 _aabb.update(*pnt);
182 // recreate the (enlarged) OctTree
185 // add all points that are already in the _data_vec
186 for (std::size_t k(0); k < _data_vec.size(); ++k)
187 {
188 GeoLib::Point* const p(_data_vec[k]);
189 _oct_tree->addPoint(p, ret_pnt);
190 }
191 // add the new point
192 ret_pnt = nullptr;
193 _oct_tree->addPoint(pnt, ret_pnt);
194 // set value of the point id to the position of the point within
195 // _data_vec
196 pnt->setID(_data_vec.size());
197 _data_vec.push_back(pnt);
198 return _data_vec.size() - 1;
199 }
200
201 delete pnt;
202 return ret_pnt->getID();
203}
204
206{
207 // create mapping id -> name using the std::vector id_names
208 std::vector<std::string> id_names(_pnt_id_map.size(), std::string(""));
209 for (auto const& id_name_pair : _name_id_map)
210 {
211 id_names[id_name_pair.second] = id_name_pair.first;
212 }
213
214 for (auto it = _name_id_map.begin(); it != _name_id_map.end();)
215 {
216 // extract the id associated with the name
217 const std::size_t id(it->second);
218
219 if (_pnt_id_map[id] == id)
220 {
221 ++it;
222 continue;
223 }
224
225 if (_pnt_id_map[_pnt_id_map[id]] == _pnt_id_map[id])
226 {
227 if (id_names[_pnt_id_map[id]].length() != 0)
228 {
229 // point has already a name, erase the second occurrence
230 it = _name_id_map.erase(it);
231 }
232 else
233 {
234 // until now the point has not a name assign the second
235 // occurrence the correct id
236 it->second = _pnt_id_map[id];
237 ++it;
238 }
239 }
240 else
241 {
242 it->second = _pnt_id_map[id]; // update id associated to the name
243 ++it;
244 }
245 }
246}
247
248std::string const& PointVec::getItemNameByID(std::size_t id) const
249{
250 return _id_to_name_map[id];
251}
252
253void PointVec::setNameForElement(std::size_t id, std::string const& name)
254{
256 _id_to_name_map[id] = name;
257}
258
260{
261 auto const [min, max] = _aabb.getMinMaxPoints();
262 double const rel_eps(_rel_eps / (max - min).norm());
263
264 _aabb = GeoLib::AABB(_data_vec.begin(), _data_vec.end());
265
266 _rel_eps = rel_eps * (_aabb.getMaxPoint() - _aabb.getMinPoint()).norm();
267
270
271 GeoLib::Point* ret_pnt(nullptr);
272 for (auto const& p : _data_vec)
273 {
274 _oct_tree->addPoint(p, ret_pnt);
275 }
276}
277
278} // namespace GeoLib
void WARN(fmt::format_string< Args... > fmt, Args &&... args)
Definition Logging.h:40
Definition of the PointVec class.
Class AABB is an axis aligned bounding box around a given set of geometric points of (template) type ...
Definition AABB.h:56
Eigen::Vector3d const & getMaxPoint() const
Definition AABB.h:187
Eigen::Vector3d const & getMinPoint() const
Definition AABB.h:180
MinMaxPoints getMinMaxPoints() const
Definition AABB.h:174
bool update(PNT_TYPE const &p)
Definition AABB.h:108
This class manages pointers to Points in a std::vector along with a name. It also handles the deletio...
Definition PointVec.h:36
std::vector< std::string > _id_to_name_map
Definition PointVec.h:149
std::unique_ptr< GeoLib::OctTree< GeoLib::Point, 16 > > _oct_tree
Definition PointVec.h:153
std::vector< std::size_t > _pnt_id_map
Definition PointVec.h:145
std::size_t uniqueInsert(Point *pnt)
Definition PointVec.cpp:165
void setNameForElement(std::size_t id, std::string const &name) override
Sets the given name for the element of the given ID.
Definition PointVec.cpp:253
std::size_t push_back(Point *pnt)
Definition PointVec.cpp:133
std::string const & getItemNameByID(std::size_t id) const
Definition PointVec.cpp:248
PointType
Signals if the vector contains object of type Point or Station.
Definition PointVec.h:40
void correctNameIDMapping()
Definition PointVec.cpp:205
void resetInternalDataStructures()
Definition PointVec.cpp:259
The class TemplateVec takes a unique name and manages a std::vector of pointers to data elements of t...
std::vector< Point * > _data_vec
virtual void setNameForElement(std::size_t id, std::string const &name)
Sets the given name for the element of the given ID.
std::size_t getID() const
void setID(std::size_t id)
Sets the ID of a node to the given value.