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 
20 namespace GeoLib
21 {
22 PointVec::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& [name, id] : _name_id_map)
118  {
119  if (id >= _id_to_name_map.size())
120  {
121  continue;
122  }
123  _id_to_name_map[id] = name;
124  }
125 }
126 
127 PointVec::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 
133 std::size_t PointVec::push_back(Point* pnt)
134 {
135  _pnt_id_map.push_back(uniqueInsert(pnt));
136  _id_to_name_map.emplace_back("");
137  return _pnt_id_map[_pnt_id_map.size() - 1];
138 }
139 
140 void 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 
165 std::size_t PointVec::uniqueInsert(Point* pnt)
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& 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 
248 std::string const& PointVec::getItemNameByID(std::size_t id) const
249 {
250  return _id_to_name_map[id];
251 }
252 
253 void 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(_aabb.getMinPoint());
262  auto const& max(_aabb.getMaxPoint());
263  double const rel_eps(_rel_eps / (max - min).norm());
264 
265  _aabb = GeoLib::AABB(_data_vec.begin(), _data_vec.end());
266 
267  _rel_eps = rel_eps * (_aabb.getMaxPoint() - _aabb.getMinPoint()).norm();
268 
271 
272  GeoLib::Point* ret_pnt(nullptr);
273  for (auto const& p : _data_vec)
274  {
275  _oct_tree->addPoint(p, ret_pnt);
276  }
277 }
278 
279 } // namespace GeoLib
void WARN(char const *fmt, Args const &... args)
Definition: Logging.h:37
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:49
Eigen::Vector3d const & getMinPoint() const
Definition: AABB.h:172
Eigen::Vector3d const & getMaxPoint() const
Definition: AABB.h:179
bool update(PNT_TYPE const &p)
Definition: AABB.h:101
This class manages pointers to Points in a std::vector along with a name. It also handles the deletio...
Definition: PointVec.h:38
std::vector< std::string > _id_to_name_map
Definition: PointVec.h:148
double _rel_eps
Definition: PointVec.h:151
std::unique_ptr< GeoLib::OctTree< GeoLib::Point, 16 > > _oct_tree
Definition: PointVec.h:152
std::vector< std::size_t > _pnt_id_map
Definition: PointVec.h:144
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:42
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...
Definition: TemplateVec.h:41
std::vector< Point * > _data_vec
Definition: TemplateVec.h:251
virtual void setNameForElement(std::size_t id, std::string const &name)
Sets the given name for the element of the given ID.
Definition: TemplateVec.h:215
std::size_t getID() const
Definition: Point3dWithID.h:62
void setID(std::size_t id)
Sets the ID of a node to the given value.
Definition: Point3dWithID.h:66
double norm(MatrixOrVector const &x, MathLib::VecNormType type)
Definition: LinAlg.h:88