OGS
GMSHPolygonTree.cpp
Go to the documentation of this file.
1 
11 #include "GMSHPolygonTree.h"
12 
14 #include "GMSHFixedMeshDensity.h"
16 #include "GeoLib/GEOObjects.h"
17 #include "GeoLib/Point.h"
18 #include "GeoLib/Polygon.h"
21 #include "GeoLib/Station.h"
22 
23 namespace FileIO
24 {
25 namespace GMSH
26 {
28  GMSHPolygonTree* parent,
29  GeoLib::GEOObjects& geo_objs,
30  std::string const& geo_name,
31  GMSHMeshDensityStrategy& mesh_density_strategy)
32  : GeoLib::SimplePolygonTree(polygon, parent),
33  _geo_objs(geo_objs),
34  _geo_name(geo_name),
35  _mesh_density_strategy(mesh_density_strategy)
36 {
37 }
38 
40 {
41  // the polylines are processed also by the children, but the root is
42  // responsible to cleanup up
43  if (isRoot())
44  { // root
45  for (auto* polyline : _plys)
46  {
47  delete polyline;
48  }
49  }
50 }
51 
53 {
54  if (isRoot())
55  {
56  return;
57  }
58 
59  for (auto& child : *this)
60  {
61  std::size_t const n_pnts(child->polygon().getNumberOfPoints());
62  for (std::size_t k(1); k < n_pnts; k++)
63  {
65  polygon().getPointID(k - 1),
66  polygon().getPointID(k)))
67  {
69  .markSegment(k, true);
70  }
71  }
72  }
73 }
74 
76 {
77  if (polygon().isPntInPolygon(*station))
78  {
79  // try to insert station into the child nodes
80  for (auto* child : *this)
81  {
82  if (child->polygon().isPntInPolygon(*station))
83  {
84  bool rval(dynamic_cast<GMSHPolygonTree*>(child)->insertStation(
85  station));
86  // stop recursion if sub SimplePolygonTree is a leaf
87  if (rval && child->getNumberOfChildren() == 0)
88  {
89  _stations.push_back(station);
90  }
91  return rval;
92  }
93  }
94  // station did not fit into child nodes -> insert the station into this
95  // node
96  _stations.push_back(station);
97  return true;
98  }
99  return false;
100 }
101 
103 {
104  if (!polygon().isPartOfPolylineInPolygon(*ply))
105  {
106  return;
107  }
108 
109  // check if polyline segments are inside of the polygon, intersect the
110  // polygon or are part of the boundary of the polygon
111  for (auto* child : *this)
112  {
113  dynamic_cast<GMSHPolygonTree*>(child)->insertPolyline(ply);
114  }
115 
116  // calculate possible intersection points between the node polygon and the
117  // given polyline ply
118  // pay attention: loop bound is not fix!
119  GeoLib::Point tmp_pnt;
121  for (auto segment_it(ply->begin()); segment_it != ply->end(); ++segment_it)
122  {
123  if (ply->isSegmentMarked(segment_it.getSegmentNumber()))
124  {
125  continue;
126  }
127 
128  if (polygon().containsSegment(*segment_it))
129  {
130  ply->markSegment(segment_it.getSegmentNumber(), true);
131  continue;
132  }
133 
134  std::size_t seg_num(0);
135  GeoLib::Point intersection_pnt;
136  while (polygon().getNextIntersectionPointPolygonLine(
137  *segment_it, intersection_pnt, seg_num))
138  {
139  // insert the intersection point to point vector of GEOObjects
140  // instance
141  const std::size_t pnt_vec_size(pnt_vec.size());
142  std::size_t pnt_id(
143  pnt_vec.push_back(new GeoLib::Point(intersection_pnt)));
144  if (pnt_vec_size < pnt_vec.size())
145  { // case: new point
146  // modify the polygon
147  polygon().insertPoint(seg_num + 1, pnt_id);
148  // modify the polyline
149  ply->insertPoint(segment_it.getSegmentNumber(), pnt_id);
150  }
151  else
152  { // case: existing point
153  // check if point id is within the polygon
154  if (!polygon().isPointIDInPolyline(pnt_id))
155  {
156  polygon().insertPoint(seg_num + 1, pnt_id);
157  }
158 
159  // check if point id is in polyline
160  if (!ply->isPointIDInPolyline(pnt_id))
161  {
162  ply->insertPoint(segment_it.getSegmentNumber() + 1, pnt_id);
163  }
164  }
165 
166  std::size_t tmp_seg_num(seg_num + 1);
167  if (!polygon().getNextIntersectionPointPolygonLine(
168  *segment_it, tmp_pnt, tmp_seg_num))
169  {
170  // check a point of the segment except the end points
171  for (std::size_t i(0); i < 3; i++)
172  {
173  tmp_pnt[i] = ((*segment_it).getBeginPoint()[i] +
174  (*segment_it).getEndPoint()[i]) /
175  2;
176  }
177  if (polygon().isPntInPolygon(tmp_pnt))
178  {
179  ply->markSegment(segment_it.getSegmentNumber(), true);
180  // insert line segment as constraint
181  _gmsh_lines_for_constraints.push_back(
182  new GMSHLine((*segment_it).getBeginPoint().getID(),
183  (*segment_it).getEndPoint().getID()));
184  }
185  }
186  seg_num++;
187 
188  // check a point of the segment except the end points
189  for (std::size_t i(0); i < 3; i++)
190  {
191  tmp_pnt[i] = ((*segment_it).getBeginPoint()[i] +
192  (*segment_it).getEndPoint()[i]) /
193  2;
194  }
195 
197 
198  if (polygon().isPntInPolygon(tmp_pnt))
199  {
200  ply->markSegment(segment_it.getSegmentNumber(), true);
201  // insert line segment as constraint
202  _gmsh_lines_for_constraints.push_back(
203  new GMSHLine((*segment_it).getBeginPoint().getID(),
204  (*segment_it).getEndPoint().getID()));
205  }
206  }
207  }
208 
209  _plys.push_back(ply);
210 }
211 
214  GeoLib::Polyline::SegmentIterator const& seg_it)
215 {
216  std::size_t const ply_segment_number(seg_it.getSegmentNumber());
218  {
220  for (auto seg_it_p(p->begin()); seg_it_p != p->end(); ++seg_it_p)
221  {
222  GeoLib::Point s; // intersection point
223  if (GeoLib::lineSegmentIntersect(*seg_it, *seg_it_p, s))
224  {
225  const std::size_t pnt_vec_size(pnt_vec.size());
226  // point id of new point in GEOObjects instance
227  const std::size_t pnt_id(
228  pnt_vec.push_back(new GeoLib::Point(s)));
229  if (pnt_vec_size < pnt_vec.size())
230  { // case: new point
231  // modify polyline already in this node
232  p->insertPoint(seg_it_p.getSegmentNumber() + 1, pnt_id);
233  // modify polyline
234  ply->insertPoint(ply_segment_number + 1, pnt_id);
235  }
236  else
237  { // case: point exists already in geometry
238  // check if point is not already in polyline p
239  std::size_t const k(seg_it_p.getSegmentNumber());
240  if (p->getPointID(k) != pnt_id &&
241  p->getPointID(k + 1) != pnt_id)
242  {
243  p->insertPoint(k + 1, pnt_id);
244  }
245  // check if point is not already in polyline ply
246  if (ply->getPointID(ply_segment_number) != pnt_id &&
247  ply->getPointID(ply_segment_number + 1) != pnt_id)
248  {
249  ply->insertPoint(ply_segment_number + 1, pnt_id);
250  }
251  }
252  }
253  }
254  }
255 }
256 
258 {
259  if (auto* adaptive_mesh_density =
261  {
262  // collect points
263  std::vector<GeoLib::Point const*> pnts;
264  const std::size_t n_pnts_polygon(polygon().getNumberOfPoints());
265  for (std::size_t k(0); k < n_pnts_polygon; k++)
266  {
267  pnts.push_back(polygon().getPoint(k));
268  }
270 
271  const std::size_t n_plys(_plys.size());
272  for (std::size_t k(0); k < n_plys; k++)
273  {
274  const std::size_t n_pnts_in_kth_ply(_plys[k]->getNumberOfPoints());
275  for (std::size_t j(0); j < n_pnts_in_kth_ply; j++)
276  {
277  pnts.push_back(_plys[k]->getPoint(j));
278  }
279  }
280 
281  // give collected points to the mesh density strategy
282  adaptive_mesh_density->initialize(pnts);
283  // insert constraints
284  adaptive_mesh_density->addPoints(_stations);
285  std::vector<GeoLib::Point const*> stations;
287  adaptive_mesh_density->addPoints(stations);
288  }
289 }
290 
291 void GMSHPolygonTree::createGMSHPoints(std::vector<GMSHPoint*>& gmsh_pnts) const
292 {
293  const std::size_t n_pnts_polygon(polygon().getNumberOfPoints());
294  for (std::size_t k(0); k < n_pnts_polygon - 1; k++)
295  {
296  const std::size_t id(polygon().getPointID(k));
297  GeoLib::Point const* const pnt(polygon().getPoint(k));
298  // if this point was already part of another polyline
299  if (gmsh_pnts[id] != nullptr)
300  {
301  continue;
302  }
303  gmsh_pnts[id] = new GMSHPoint(
305  }
306 
307  const std::size_t n_plys(_plys.size());
308  for (std::size_t k(0); k < n_plys; k++)
309  {
310  const std::size_t n_pnts_in_ply(_plys[k]->getNumberOfPoints());
311  for (std::size_t j(0); j < n_pnts_in_ply; j++)
312  {
313  if (polygon().isPntInPolygon(*(_plys[k]->getPoint(j))))
314  {
315  const std::size_t id(_plys[k]->getPointID(j));
316  // if this point was already part of another polyline
317  if (gmsh_pnts[id] != nullptr)
318  {
319  continue;
320  }
321  GeoLib::Point const* const pnt(_plys[k]->getPoint(j));
322  gmsh_pnts[id] = new GMSHPoint(
323  *pnt, id,
325  }
326  }
327  }
328 
329  // walk through children
330  for (auto* child : *this)
331  {
332  dynamic_cast<GMSHPolygonTree*>(child)->createGMSHPoints(gmsh_pnts);
333  }
334 }
335 
336 void GMSHPolygonTree::writeLineLoop(std::size_t& line_offset,
337  std::size_t& sfc_offset, std::ostream& out,
338  bool const write_physical) const
339 {
340  const std::size_t n_pnts(polygon().getNumberOfPoints());
341  for (std::size_t k(1), first_pnt_id(polygon().getPointID(0)); k < n_pnts;
342  k++)
343  {
344  std::size_t const second_pnt_id = polygon().getPointID(k);
345  out << "Line(" << line_offset + k - 1 << ") = {" << first_pnt_id << ","
346  << second_pnt_id << "};\n";
347  first_pnt_id = second_pnt_id;
348  }
349  out << "Line Loop(" << line_offset + n_pnts - 1 << ") = {";
350  for (std::size_t k(0); k < n_pnts - 2; k++)
351  {
352  out << line_offset + k << ",";
353  }
354  out << line_offset + n_pnts - 2 << "};\n";
355  out << "Plane Surface(" << sfc_offset << ") = {" << line_offset + n_pnts - 1
356  << "};\n";
357  if (write_physical)
358  {
359  out << "Physical Curve(" << sfc_offset << ") = {";
360  for (std::size_t k(0); k < n_pnts - 2; k++)
361  {
362  out << line_offset + k << ",";
363  }
364  out << line_offset + n_pnts - 2 << "};\n";
365  out << "Physical Surface(" << sfc_offset << ") = {" << sfc_offset
366  << "};\n";
367  }
368  line_offset += n_pnts;
369  sfc_offset++;
370 }
371 
372 void GMSHPolygonTree::writeLineConstraints(std::size_t& line_offset,
373  std::size_t sfc_number,
374  std::ostream& out) const
375 {
376  for (auto polyline : _plys)
377  {
378  const std::size_t n_pnts(polyline->getNumberOfPoints());
379  std::size_t first_pnt_id(polyline->getPointID(0));
380  for (std::size_t k(1); k < n_pnts; k++)
381  {
382  auto const second_pnt_id = polyline->getPointID(k);
383  if (polyline->isSegmentMarked(k - 1) &&
384  polygon().isPntInPolygon(*(polyline->getPoint(k))) &&
385  !GeoLib::containsEdge(polygon(), first_pnt_id, second_pnt_id))
386  {
387  out << "Line(" << line_offset + k - 1 << ") = {" << first_pnt_id
388  << "," << second_pnt_id << "};\n";
389  out << "Line { " << line_offset + k - 1 << " } In Surface { "
390  << sfc_number << " };\n";
391  }
392  first_pnt_id = second_pnt_id;
393  }
394  line_offset += n_pnts;
395  }
396 }
397 
399  std::size_t& line_offset, std::size_t sfc_number, std::ostream& out) const
400 {
401  for (auto* child : *this)
402  {
403  dynamic_cast<GMSHPolygonTree*>(child)
404  ->writeSubPolygonsAsLineConstraints(line_offset, sfc_number, out);
405  }
406 
407  if (!isRoot())
408  {
409  const std::size_t n_pnts(polygon().getNumberOfPoints());
410  std::size_t first_pnt_id(polygon().getPointID(0));
411  for (std::size_t k(1); k < n_pnts; k++)
412  {
413  auto const second_pnt_id = polygon().getPointID(k);
414  out << "Line(" << line_offset + k - 1 << ") = {" << first_pnt_id
415  << "," << second_pnt_id << "};\n";
416  first_pnt_id = second_pnt_id;
417  out << "Line { " << line_offset + k - 1 << " } In Surface { "
418  << sfc_number << " };\n";
419  }
420  line_offset += n_pnts;
421  }
422 }
423 
424 void GMSHPolygonTree::writeStations(std::size_t& pnt_id_offset,
425  std::size_t sfc_number,
426  std::ostream& out) const
427 {
428  for (auto const* station : _stations)
429  {
430  out << "Point(" << pnt_id_offset << ") = {" << (*station)[0] << ", "
431  << (*station)[1] << ", 0.0, "
433  << "}; // Station "
434  << static_cast<GeoLib::Station const*>(station)->getName() << " \n";
435  out << "Point { " << pnt_id_offset << " } In Surface { " << sfc_number
436  << " };\n";
437  ++pnt_id_offset;
438  }
439 }
440 
441 void GMSHPolygonTree::writeAdditionalPointData(std::size_t& pnt_id_offset,
442  std::size_t sfc_number,
443  std::ostream& out) const
444 {
445  if (auto* adaptive_mesh_density =
447  {
448  std::vector<GeoLib::Point*> steiner_pnts;
449  adaptive_mesh_density->getSteinerPoints(steiner_pnts, 0);
450  const std::size_t n(steiner_pnts.size());
451  for (std::size_t k(0); k < n; k++)
452  {
453  if (polygon().isPntInPolygon(*(steiner_pnts[k])))
454  {
455  out << "Point(" << pnt_id_offset + k << ") = {"
456  << (*(steiner_pnts[k]))[0] << "," << (*(steiner_pnts[k]))[1]
457  << ", 0.0, ";
459  steiner_pnts[k])
460  << "};\n";
461  out << "Point { " << pnt_id_offset + k << " } In Surface { "
462  << sfc_number << " };\n";
463  }
464  delete steiner_pnts[k];
465  }
466  pnt_id_offset += n;
467  }
468 
469 #ifndef NDEBUG
470  if (auto* adaptive_mesh_density =
472  {
473  auto pnts = std::make_unique<std::vector<GeoLib::Point*>>();
474  auto plys = std::make_unique<std::vector<GeoLib::Polyline*>>();
475  adaptive_mesh_density->getQuadTreeGeometry(*pnts, *plys);
476  std::string quad_tree_geo("QuadTree");
477  _geo_objs.addPointVec(std::move(pnts), quad_tree_geo);
478  std::vector<std::size_t> const& id_map(
479  (_geo_objs.getPointVecObj(quad_tree_geo))->getIDMap());
480  for (std::size_t k(0); k < plys->size(); k++)
481  {
482  for (std::size_t j(0); j < (*plys)[k]->getNumberOfPoints(); j++)
483  {
484  ((*plys)[k])
485  ->setPointID(j, id_map[((*plys)[k])->getPointID(j)]);
486  }
487  }
488  _geo_objs.addPolylineVec(std::move(plys), quad_tree_geo);
489  }
490 #endif
491 }
492 
494  std::vector<GeoLib::Point const*>& pnts) const
495 {
496  for (auto const* child : *this)
497  {
498  dynamic_cast<GMSHPolygonTree const*>(child)->getPointsFromSubPolygons(
499  pnts);
500  }
501 }
502 
504  std::vector<GeoLib::Point const*>& stations) const
505 {
506  const std::size_t n_stations(_stations.size());
507  for (std::size_t k(0); k < n_stations; k++)
508  {
509  stations.push_back(_stations[k]);
510  }
511 
512  for (auto const* child : *this)
513  {
514  dynamic_cast<GMSHPolygonTree const*>(child)
515  ->getStationsInsideSubPolygons(stations);
516  }
517 }
518 
519 } // end namespace GMSH
520 } // end namespace FileIO
Definition of analytical geometry functions.
Definition of the GEOObjects class.
Definition of the Point class.
Definition of the Polygon class.
Definition of the PolylineWithSegmentMarker class.
Definition of the Station class.
std::string getName(std::string const &line)
Returns the name/title from the "Zone"-description.
virtual double getMeshDensityAtStation(GeoLib::Point const *const) const =0
virtual double getMeshDensityAtPoint(GeoLib::Point const *const) const =0
void writeSubPolygonsAsLineConstraints(std::size_t &line_offset, std::size_t sfc_number, std::ostream &out) const
std::vector< GeoLib::PolylineWithSegmentMarker * > _plys
GMSHMeshDensityStrategy & _mesh_density_strategy
void insertPolyline(GeoLib::PolylineWithSegmentMarker *ply)
virtual void writeLineConstraints(std::size_t &line_offset, std::size_t sfc_number, std::ostream &out) const
std::string const & _geo_name
void writeAdditionalPointData(std::size_t &pnt_id_offset, std::size_t sfc_number, std::ostream &out) const
std::vector< GeoLib::Point const * > _stations
GMSHPolygonTree(GeoLib::PolygonWithSegmentMarker *polygon, GMSHPolygonTree *parent, GeoLib::GEOObjects &geo_objs, std::string const &geo_name, GMSHMeshDensityStrategy &mesh_density_strategy)
void getStationsInsideSubPolygons(std::vector< GeoLib::Point const * > &stations) const
void writeStations(std::size_t &pnt_id_offset, std::size_t sfc_number, std::ostream &out) const
void createGMSHPoints(std::vector< GMSHPoint * > &gmsh_pnts) const
void getPointsFromSubPolygons(std::vector< GeoLib::Point const * > &pnts) const
void checkIntersectionsSegmentExistingPolylines(GeoLib::PolylineWithSegmentMarker *ply, GeoLib::Polyline::SegmentIterator const &seg_it)
GeoLib::GEOObjects & _geo_objs
bool insertStation(GeoLib::Point const *station)
std::vector< GMSHLine * > _gmsh_lines_for_constraints
virtual void writeLineLoop(std::size_t &line_offset, std::size_t &sfc_offset, std::ostream &out, bool const write_physical) const
Container class for geometric objects.
Definition: GEOObjects.h:61
const PointVec * getPointVecObj(const std::string &name) const
Definition: GEOObjects.cpp:84
void addPointVec(std::unique_ptr< std::vector< Point * >> points, std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> pnt_id_name_map=nullptr, double eps=std::sqrt(std::numeric_limits< double >::epsilon()))
Definition: GEOObjects.cpp:51
void addPolylineVec(std::unique_ptr< std::vector< Polyline * >> lines, const std::string &name, std::unique_ptr< std::map< std::string, std::size_t >> ply_names=nullptr)
Definition: GEOObjects.cpp:150
This class manages pointers to Points in a std::vector along with a name. It also handles the deletin...
Definition: PointVec.h:39
std::size_t push_back(Point *pnt)
Definition: PointVec.cpp:129
bool isPntInPolygon(const MathLib::Point3d &pnt) const
Definition: Polygon.cpp:71
bool isSegmentMarked(std::size_t seg_num) const
void markSegment(std::size_t seg_num, bool mark_val=true)
bool insertPoint(std::size_t pos, std::size_t pnt_id) override
std::size_t getSegmentNumber() const
Definition: Polyline.cpp:422
std::size_t getPointID(std::size_t i) const
Definition: Polyline.cpp:150
virtual bool insertPoint(std::size_t pos, std::size_t pnt_id)
Definition: Polyline.cpp:51
SegmentIterator begin() const
Definition: Polyline.h:189
bool isPointIDInPolyline(std::size_t pnt_id) const
Definition: Polyline.cpp:144
SegmentIterator end() const
Definition: Polyline.h:194
const SimplePolygonTree * parent() const
Polygon const & polygon() const
A Station (observation site) is basically a Point with some additional information.
Definition: Station.h:37
std::size_t size() const
Definition: TemplateVec.h:106
bool containsEdge(const Polyline &ply, std::size_t id0, std::size_t id1)
Definition: Polyline.cpp:510
bool lineSegmentIntersect(GeoLib::LineSegment const &s0, GeoLib::LineSegment const &s1, GeoLib::Point &s)