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