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