libMesh
Public Member Functions | Protected Member Functions | Protected Attributes | Private Attributes | List of all members
libMesh::TriangulatorInterface::MeshedHole Class Reference

Another concrete instantiation of the hole, as general as ArbitraryHole, but based on an existing 1D or 2D mesh. More...

#include <mesh_triangle_holes.h>

Inheritance diagram for libMesh::TriangulatorInterface::MeshedHole:
[legend]

Public Member Functions

 MeshedHole (const MeshBase &mesh, std::set< std::size_t > ids={})
 The constructor requires a mesh defining the hole, and optionally boundary+subdomain ids restricting the definition. More...
 
virtual unsigned int n_points () const override
 The number of geometric points which define the hole. More...
 
virtual unsigned int n_midpoints () const override
 The number of geometric midpoints along each of the sides defining the hole. More...
 
virtual Point point (const unsigned int n) const override
 Return the nth point defining the hole. More...
 
virtual Point midpoint (const unsigned int m, const unsigned int n) const override
 Return the midpoint m along the side n defining the hole. More...
 
virtual Point inside () const override
 Return an (arbitrary) point which lies inside the hole. More...
 
bool contains (Point p) const
 Return true iff p lies inside the hole. More...
 
Real area () const
 Return the area of the hole. More...
 
RealGradient areavec () const
 Return a vector with right-hand-rule orientation and length of twice area() squared. More...
 
virtual std::vector< unsigned intsegment_indices () const
 Starting indices of points for a hole with multiple disconnected boundaries. More...
 
virtual void set_refine_boundary_allowed (bool refine_bdy_allowed)
 Set whether or not a triangulator is allowed to refine the hole boundary when refining the mesh interior. More...
 
virtual bool refine_boundary_allowed () const
 Get whether or not the triangulation is allowed to refine the mesh boundary when refining the interior. More...
 

Protected Member Functions

std::vector< Realfind_ray_intersections (Point ray_start, Point ray_target) const
 Helper function for contains(), also useful for MeshedHole::inside() More...
 
Point calculate_inside_point () const
 Calculate an inside point based on our boundary. More...
 

Protected Attributes

bool _refine_bdy_allowed = true
 Whether to allow boundary refinement. More...
 

Private Attributes

Point _center
 An (x,y) location inside the hole. More...
 
std::vector< Point_points
 The sorted vector of points which makes up the hole. More...
 
std::vector< Point_midpoints
 The sorted vector of midpoints in between points along the edges of the hole. More...
 

Detailed Description

Another concrete instantiation of the hole, as general as ArbitraryHole, but based on an existing 1D or 2D mesh.

If ids are given, 2D edges on a boundary with a listed id or 1D edges in a subdomain with a listed id will define the hole.

If no ids are given, the hole will be defined by all 1D Edge elements and all outward-facing 2D boundary edges.

In either case, the hole definition should give a single connected boundary, topologically a circle. The hole is defined when the MeshedHole is constructed, and ignores any subsequent changes to the input mesh.

Definition at line 343 of file mesh_triangle_holes.h.

Constructor & Destructor Documentation

◆ MeshedHole()

libMesh::TriangulatorInterface::MeshedHole::MeshedHole ( const MeshBase mesh,
std::set< std::size_t >  ids = {} 
)

The constructor requires a mesh defining the hole, and optionally boundary+subdomain ids restricting the definition.

Definition at line 451 of file mesh_triangle_holes.C.

References _midpoints, _points, libMesh::TriangulatorInterface::Hole::area(), libMesh::as_range(), libMesh::BoundaryInfo::boundary_ids(), TIMPI::Communicator::broadcast(), libMesh::ParallelObject::comm(), libMesh::TypeVector< T >::cross(), distance(), libMesh::EDGE3, libMesh::EDGE4, libMesh::MeshBase::get_boundary_info(), libMesh::libmesh_ignore(), libMesh::make_range(), mesh, n_midpoints(), libMesh::MeshTools::Subdivision::next, libMesh::out, libMesh::ParallelObject::processor_id(), libMesh::Real, and libMesh::MacroFunctions::report_error().

453  : _center(std::numeric_limits<Real>::max())
454 {
455  // We'll want to do this on one processor and broadcast to the rest;
456  // otherwise we can get out of sync by doing things like using
457  // pointers as keys.
458  libmesh_parallel_only(mesh.comm());
459 
460  MeshSerializer serial(const_cast<MeshBase &>(mesh),
461  /* serial */ true, /* only proc 0 */ true);
462 
463  // Try to keep in sync even if we throw an error on proc 0, so we
464  // can examine errors in our unit tests in parallel too.
465  std::string error_reported;
466 
467  auto report_error = [&mesh, &error_reported](std::string er) {
468  error_reported = std::move(er);
469  mesh.comm().broadcast(error_reported);
470  libmesh_error_msg(error_reported);
471  };
472 
473  if (mesh.processor_id() != 0)
474  {
475  // Make sure proc 0 didn't just fail
476  mesh.comm().broadcast(error_reported);
477  libmesh_error_msg_if(!error_reported.empty(), error_reported);
478 
479  // Receive the points proc 0 will send later
482  return;
483  }
484 
485  // We'll find all the line segments first, then stitch them together
486  // afterward. If the line segments come from 2D element sides then
487  // we'll label their edge_type as "1" for clockwise orientation
488  // around the element or "2" for CCW, to make it easier to detect
489  // and scream about cases where we have a disconnected outer
490  // boundary.
491  std::multimap<const Node *,
492  std::pair<const Node *, int>> hole_edge_map;
493 
494  // If we're looking at higher-order elements, we have mid-edge edge
495  // nodes to worry about. hole_midpoint_map[{m,n}][i] should give us
496  // the ith mid-edge node traveling from vertex m to vertex n
497  std::map<std::pair<const Node *, const Node *>,
498  std::vector<const Node *>> hole_midpoint_map;
499 
500  std::vector<boundary_id_type> bcids;
501 
502  const BoundaryInfo & boundary_info = mesh.get_boundary_info();
503 
504  for (const auto & elem : mesh.active_element_ptr_range())
505  {
506  if (elem->dim() == 1)
507  {
508  if (ids.empty() || ids.count(elem->subdomain_id()))
509  {
510  hole_edge_map.emplace(elem->node_ptr(0),
511  std::make_pair(elem->node_ptr(1),
512  /*edge*/ 0));
513  hole_edge_map.emplace(elem->node_ptr(1),
514  std::make_pair(elem->node_ptr(0),
515  /*edge*/ 0));
516  if (elem->type() == EDGE3)
517  {
518  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr(0),
519  elem->node_ptr(1)),
520  std::vector<const Node *>{elem->node_ptr(2)});
521  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr(1),
522  elem->node_ptr(0)),
523  std::vector<const Node *>{elem->node_ptr(2)});
524  }
525  else if (elem->type() == EDGE4)
526  {
527  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr(0),
528  elem->node_ptr(1)),
529  std::vector<const Node *>{elem->node_ptr(2),
530  elem->node_ptr(3)});
531  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr(1),
532  elem->node_ptr(0)),
533  std::vector<const Node *>{elem->node_ptr(3),
534  elem->node_ptr(2)});
535  }
536  else
537  libmesh_assert_equal_to(elem->default_side_order(), 1);
538  }
539  continue;
540  }
541 
542  if (elem->dim() == 2)
543  {
544  const auto ns = elem->n_sides();
545  for (auto s : make_range(ns))
546  {
547  boundary_info.boundary_ids(elem, s, bcids);
548 
549  bool add_edge = false;
550  if (!elem->neighbor_ptr(s) && ids.empty())
551  add_edge = true;
552 
553  if (!add_edge)
554  for (auto b : bcids)
555  if (ids.count(b))
556  add_edge = true;
557 
558  if (add_edge)
559  {
560  hole_edge_map.emplace(elem->node_ptr(s),
561  std::make_pair(elem->node_ptr((s+1)%ns),
562  /*counter-CW*/ 2));
563  // Do we really need to support flipped 2D elements?
564  hole_edge_map.emplace(elem->node_ptr((s+1)%ns),
565  std::make_pair(elem->node_ptr(s),
566  /*clockwise*/ 1));
567 
568  if (elem->default_side_order() == 2)
569  {
570  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr(s),
571  elem->node_ptr((s+1)%ns)),
572  std::vector<const Node *>{elem->node_ptr(s+ns)});
573  hole_midpoint_map.emplace(std::make_pair(elem->node_ptr((s+1)%ns),
574  elem->node_ptr(s)),
575  std::vector<const Node *>{elem->node_ptr(s+ns)});
576  }
577  else
578  libmesh_assert_equal_to(elem->default_side_order(), 1);
579 
580  continue;
581  }
582  }
583  }
584  }
585 
586  if (hole_edge_map.empty())
587  report_error("No valid hole edges found in mesh!");
588 
589  // Function to pull a vector of points out of the map; a loop of
590  // edges connecting these points defines a hole boundary. If the
591  // mesh has multiple boundaries (e.g. because it had holes itself),
592  // then a random vector will be extracted; this function will be
593  // called multiple times so that the various options can be
594  // compared. We choose the largest option.
595  auto extract_edge_vector =
596  [&report_error, &hole_edge_map, &hole_midpoint_map]() {
597  std::tuple<std::vector<const Node *>, std::vector<const Node *>, int>
598  hole_points_and_edge_type
599  {{hole_edge_map.begin()->first, hole_edge_map.begin()->second.first},
600  {}, hole_edge_map.begin()->second.second};
601 
602  auto & hole_points = std::get<0>(hole_points_and_edge_type);
603  auto & midpoint_points = std::get<1>(hole_points_and_edge_type);
604  int & edge_type = std::get<2>(hole_points_and_edge_type);
605 
606  // We won't be needing to search for this edge
607  hole_edge_map.erase(hole_points.front());
608 
609  // Sort the remaining edges into a connected order
610  for (const Node * last = hole_points.front(),
611  * n = hole_points.back();
612  n != hole_points.front();
613  last = n,
614  n = hole_points.back())
615  {
616  auto [next_it_begin, next_it_end] = hole_edge_map.equal_range(n);
617 
618  if (std::distance(next_it_begin, next_it_end) != 2)
619  report_error("Bad edge topology found by MeshedHole");
620 
621  const Node * next = nullptr;
622  for (const auto & [key, val] : as_range(next_it_begin, next_it_end))
623  {
624  libmesh_assert_equal_to(key, n);
625  libmesh_ignore(key);
626  libmesh_assert_not_equal_to(val.first, n);
627 
628  // Don't go backwards on the edge we just traversed
629  if (val.first == last)
630  continue;
631 
632  // We can support mixes of Edge and Tri-side edges, but we
633  // can't do proper error detection on flipped triangles.
634  if (val.second != edge_type &&
635  val.second != 0)
636  {
637  if (!edge_type)
638  edge_type = val.second;
639  else
640  report_error("MeshedHole sees inconsistent triangle orientations on boundary");
641  }
642  next = val.first;
643  }
644 
645  // We should never hit the same n twice!
646  hole_edge_map.erase(next_it_begin, next_it_end);
647 
648  hole_points.push_back(next);
649  }
650 
651  for (auto i : make_range(hole_points.size()-1))
652  {
653  const auto & midpoints = hole_midpoint_map[{hole_points[i],hole_points[i+1]}];
654  midpoint_points.insert(midpoint_points.end(),
655  midpoints.begin(), midpoints.end());
656  }
657 
658  hole_points.pop_back();
659 
660  return hole_points_and_edge_type;
661  };
662 
663  /*
664  * If it's not obvious which loop we find is really the loop we
665  * want, then we should die with a nice error message.
666  */
667  int n_negative_areas = 0,
668  n_positive_areas = 0,
669  n_edgeelem_loops = 0;
670 
671  std::vector<const Node *> outer_hole_points, outer_mid_points;
672  int outer_edge_type = -1;
673  Real twice_outer_area = 0,
674  abs_twice_outer_area = 0;
675 
676 #ifdef DEBUG
677  // Area and edge type, for error reporting
678  std::vector<std::pair<Real, int>> areas;
679 #endif
680 
681  while (!hole_edge_map.empty()) {
682  auto [hole_points, mid_points, edge_type] = extract_edge_vector();
683 
684  if (edge_type == 0)
685  {
686  ++n_edgeelem_loops;
687  if (n_edgeelem_loops > 1)
688  report_error("MeshedHole is confused by multiple loops of Edge elements");
689  if (n_positive_areas || n_negative_areas)
690  report_error("MeshedHole is confused by meshes with both Edge and 2D-side boundaries");
691  }
692 
693  const std::size_t n_hole_points = hole_points.size();
694  if (n_hole_points < 3)
695  report_error("Loop with only " + std::to_string(n_hole_points) +
696  " hole edges found in mesh!");
697 
698  Real twice_this_area = 0;
699  const Point p0 = *hole_points[0];
700  for (unsigned int i=2; i != n_hole_points; ++i)
701  {
702  const Point e_0im = *hole_points[i-1] - p0,
703  e_0i = *hole_points[i] - p0;
704 
705  twice_this_area += e_0i.cross(e_0im)(2);
706  }
707 
708  auto abs_twice_this_area = std::abs(twice_this_area);
709 
710  if (((twice_this_area > 0) && edge_type == 2) ||
711  ((twice_this_area < 0) && edge_type == 1))
712  ++n_positive_areas;
713  else if (edge_type != 0)
714  ++n_negative_areas;
715 
716 #ifdef DEBUG
717  areas.push_back({twice_this_area/2,edge_type});
718 #endif
719 
720  if (abs_twice_this_area > abs_twice_outer_area)
721  {
722  twice_outer_area = twice_this_area;
723  abs_twice_outer_area = abs_twice_this_area;
724  outer_hole_points = std::move(hole_points);
725  outer_mid_points = std::move(mid_points);
726  outer_edge_type = edge_type;
727  }
728  }
729 
730  _points.resize(outer_hole_points.size());
731  std::transform(outer_hole_points.begin(),
732  outer_hole_points.end(),
733  _points.begin(),
734  [](const Node * n){ return Point(*n); });
735  _midpoints.resize(outer_mid_points.size());
736  std::transform(outer_mid_points.begin(),
737  outer_mid_points.end(),
738  _midpoints.begin(),
739  [](const Node * n){ return Point(*n); });
740 
741  if (!twice_outer_area)
742  report_error("Zero-area MeshedHoles are not currently supported");
743 
744  // We ordered ourselves counter-clockwise? But a hole is expected
745  // to be clockwise, so use the reverse order.
746  if (twice_outer_area > 0)
747  {
748  std::reverse(_points.begin(), _points.end());
749 
750  // Our midpoints are numbered e.g.
751  // (01a)(01b)(12a)(12b)(23a)(23b)(30a)(30b) for points 0123, but
752  // if we reverse to get 3210 then we want our midpoints to be
753  // (23b)(23a)(12b)(12a)(01b)(01a)(30b)(30a)
754  const unsigned int n_midpoints = _midpoints.size() / _points.size();
755  auto split_it = _midpoints.end() - n_midpoints;
756  std::reverse(_midpoints.begin(), split_it);
757  std::reverse(split_it, _midpoints.end());
758  }
759 
760 #ifdef DEBUG
761  auto print_areas = [areas](){
762  libMesh::out << "Found boundary areas:\n";
763  static const std::vector<std::string> edgenames {"E","CW","CCW"};
764  for (auto area : areas)
765  libMesh::out << '(' << edgenames[area.second] << ' ' <<
766  area.first << ')';
767  libMesh::out << std::endl;
768  };
769 #else
770  auto print_areas = [](){};
771 #endif
772 
773  if (((twice_outer_area > 0) && outer_edge_type == 2) ||
774  ((twice_outer_area < 0) && outer_edge_type == 1))
775  {
776  if (n_positive_areas > 1)
777  {
778  print_areas();
779  report_error("MeshedHole found " +
780  std::to_string(n_positive_areas) +
781  " counter-clockwise boundaries and cannot choose one!");
782  }
783 
784  }
785  else if (outer_edge_type != 0)
786  {
787  if (n_negative_areas > 1)
788  {
789  print_areas();
790  report_error("MeshedHole found " +
791  std::to_string(n_negative_areas) +
792  " clockwise boundaries and cannot choose one!");
793  }
794 
795  }
796 
797  // Hey, no errors! Broadcast that empty string.
798  mesh.comm().broadcast(error_reported);
801 }
std::vector< Point > _points
The sorted vector of points which makes up the hole.
A Node is like a Point, but with more information.
Definition: node.h:52
Real area() const
Return the area of the hole.
MeshBase & mesh
const Parallel::Communicator & comm() const
void boundary_ids(const Node *node, std::vector< boundary_id_type > &vec_to_fill) const
Fills a user-provided std::vector with the boundary ids associated with Node node.
const BoundaryInfo & get_boundary_info() const
The information about boundary ids on the mesh.
Definition: mesh_base.h:165
Real distance(const Point &p)
void libmesh_ignore(const Args &...)
void report_error(const char *file, int line, const char *date, const char *time, std::ostream &os=libMesh::err)
SimpleRange< IndexType > as_range(const std::pair< IndexType, IndexType > &p)
Helper function that allows us to treat a homogenous pair as a range.
Definition: simple_range.h:57
The BoundaryInfo class contains information relevant to boundary conditions including storing faces...
Definition: boundary_info.h:57
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
Definition: type_vector.h:884
virtual unsigned int n_midpoints() const override
The number of geometric midpoints along each of the sides defining the hole.
void broadcast(T &data, const unsigned int root_id=0, const bool identical_sizes=false) const
static const unsigned int next[3]
A lookup table for the increment modulo 3 operation, for iterating through the three nodes per elemen...
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
Temporarily serialize a DistributedMesh for non-distributed-mesh capable code paths.
OStreamProxy out
std::vector< Point > _midpoints
The sorted vector of midpoints in between points along the edges of the hole.
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
processor_id_type processor_id() const
Point _center
An (x,y) location inside the hole.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

Member Function Documentation

◆ area()

Real libMesh::TriangulatorInterface::Hole::area ( ) const
inherited

Return the area of the hole.

This method currently does not take any higher-order hole geometry into account, but treats the hole as a polygon.

Definition at line 184 of file mesh_triangle_holes.C.

References libMesh::TriangulatorInterface::Hole::areavec(), and libMesh::TypeVector< T >::norm().

Referenced by MeshedHole(), and MeshTriangulationTest::testTriangleHoleArea().

185 {
186  return this->areavec().norm() / 2;
187 }
auto norm() const -> decltype(std::norm(T()))
Definition: type_vector.h:907
RealGradient areavec() const
Return a vector with right-hand-rule orientation and length of twice area() squared.

◆ areavec()

RealGradient libMesh::TriangulatorInterface::Hole::areavec ( ) const
inherited

Return a vector with right-hand-rule orientation and length of twice area() squared.

This is useful for determining orientation of non-planar or non-counter-clockwise holes.

This method currently does not take any higher-order hole geometry into account, but treats the hole as a polygon.

Definition at line 190 of file mesh_triangle_holes.C.

References libMesh::TypeVector< T >::cross().

Referenced by libMesh::TriangulatorInterface::Hole::area().

191 {
192  const unsigned int np = this->n_points();
193 
194  if (np < 3)
195  return 0;
196 
197  const Point p0 = this->point(0);
198 
199  // Every segment (p_{i-1},p_i) from i=2 on defines a triangle w.r.t.
200  // p_0. Add up the cross products of those triangles. We'll save
201  // the division by 2 and the norm for the end.
202  //
203  // Your hole points had best be coplanar, but this should work
204  // regardless of which plane they're in. If you're in the XY plane,
205  // then the standard counter-clockwise hole point ordering gives you
206  // a positive areavec(2);
207 
208  RealGradient areavec = 0;
209 
210  for (unsigned int i=2; i != np; ++i)
211  {
212  const Point e_0im = this->point(i-1) - p0,
213  e_0i = this->point(i) - p0;
214 
215  areavec += e_0i.cross(e_0im);
216  }
217 
218  return areavec;
219 }
TypeVector< typename CompareTypes< T, T2 >::supertype > cross(const TypeVector< T2 > &v) const
Definition: type_vector.h:884
RealGradient areavec() const
Return a vector with right-hand-rule orientation and length of twice area() squared.
virtual Point point(const unsigned int n) const =0
Return the nth point defining the hole.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
virtual unsigned int n_points() const =0
The number of geometric points which define the hole.

◆ calculate_inside_point()

Point libMesh::TriangulatorInterface::Hole::calculate_inside_point ( ) const
protectedinherited

Calculate an inside point based on our boundary.

Definition at line 248 of file mesh_triangle_holes.C.

References libMesh::make_range(), and libMesh::Real.

Referenced by libMesh::TriangulatorInterface::ArbitraryHole::ArbitraryHole(), and libMesh::TriangulatorInterface::ArbitraryHole::set_points().

249 {
250  // Start with the vertex average
251 
252  // Turns out "I'm a fully compliant C++17 compiler!" doesn't
253  // mean "I have a full C++17 standard library!"
254  // inside = std::reduce(points.begin(), points.end());
255  Point inside = 0;
256  for (auto i : make_range(this->n_points()))
257  inside += this->point(i);
258 
259  inside /= this->n_points();
260 
261  // Count the number of intersections with a ray to the right,
262  // keep track of how far they are
263  Point ray_target = inside + Point(1);
264  std::vector<Real> intersection_distances =
265  this->find_ray_intersections(inside, ray_target);
266 
267  // The vertex average isn't on the interior, and we found no
268  // intersections to the right? Try looking to the left.
269  if (!intersection_distances.size())
270  {
271  ray_target = inside - Point(1);
272  intersection_distances =
273  this->find_ray_intersections(inside, ray_target);
274  }
275 
276  // I'd make this an assert, but I'm not 100% confident we can't
277  // get here via some kind of FP error on a weird hole shape.
278  libmesh_error_msg_if
279  (!intersection_distances.size(),
280  "Can't find a center for a MeshedHole!");
281 
282  if (intersection_distances.size() % 2)
283  return inside;
284 
285  // The vertex average is outside. So go from the vertex average to
286  // the closest edge intersection, then halfway to the next-closest.
287 
288  // Find the nearest first.
289  Real min_distance = std::numeric_limits<Real>::max(),
290  second_distance = std::numeric_limits<Real>::max();
291  for (Real d : intersection_distances)
292  if (d < min_distance)
293  {
294  second_distance = min_distance;
295  min_distance = d;
296  }
297 
298  const Point ray = ray_target - inside;
299  inside += ray * (min_distance + second_distance)/2;
300 
301  return inside;
302 }
std::vector< Real > find_ray_intersections(Point ray_start, Point ray_target) const
Helper function for contains(), also useful for MeshedHole::inside()
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
virtual Point point(const unsigned int n) const =0
Return the nth point defining the hole.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
virtual Point inside() const =0
Return an (arbitrary) point which lies inside the hole.
virtual unsigned int n_points() const =0
The number of geometric points which define the hole.

◆ contains()

bool libMesh::TriangulatorInterface::Hole::contains ( Point  p) const
inherited

Return true iff p lies inside the hole.

This method currently does not take any higher-order hole geometry into account, but treats the hole as a polygon.

Definition at line 305 of file mesh_triangle_holes.C.

Referenced by libMesh::TriangulatorInterface::verify_holes().

306 {
307  // Count the number of intersections with a ray to the right,
308  // keep track of how far they are
309  Point ray_target = p + Point(1);
310  std::vector<Real> intersection_distances =
311  this->find_ray_intersections(p, ray_target);
312 
313  // Odd number of intersections == we're inside
314  // Even number == we're outside
315  return intersection_distances.size() % 2;
316 }
std::vector< Real > find_ray_intersections(Point ray_start, Point ray_target) const
Helper function for contains(), also useful for MeshedHole::inside()
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39

◆ find_ray_intersections()

std::vector< Real > libMesh::TriangulatorInterface::Hole::find_ray_intersections ( Point  ray_start,
Point  ray_target 
) const
protectedinherited

Helper function for contains(), also useful for MeshedHole::inside()

Definition at line 224 of file mesh_triangle_holes.C.

References libMesh::make_range(), and libMesh::Real.

226 {
227  const auto np = this->n_points();
228 
229  std::vector<Real> intersection_distances;
230 
231  for (auto i : make_range(np))
232  {
233  const Point & p0 = this->point(i),
234  & p1 = this->point((i+1)%np),
235  & p2 = this->point((i+2)%np);
236  const Real intersection_distance =
237  find_intersection(ray_start, ray_target, p0, p1, p2);
238  if (intersection_distance >= 0)
239  intersection_distances.push_back
240  (intersection_distance);
241  }
242 
243  return intersection_distances;
244 }
DIE A HORRIBLE DEATH HERE typedef LIBMESH_DEFAULT_SCALAR_TYPE Real
IntRange< T > make_range(T beg, T end)
The 2-parameter make_range() helper function returns an IntRange<T> when both input parameters are of...
Definition: int_range.h:140
virtual Point point(const unsigned int n) const =0
Return the nth point defining the hole.
A Point defines a location in LIBMESH_DIM dimensional Real space.
Definition: point.h:39
virtual unsigned int n_points() const =0
The number of geometric points which define the hole.

◆ inside()

Point libMesh::TriangulatorInterface::MeshedHole::inside ( ) const
overridevirtual

Return an (arbitrary) point which lies inside the hole.

Implements libMesh::TriangulatorInterface::Hole.

Definition at line 834 of file mesh_triangle_holes.C.

835 {
836  // This is expensive to compute, so only do it when we first need it
837  if (_center(0) == std::numeric_limits<Real>::max())
839 
840  return _center;
841 }
Point calculate_inside_point() const
Calculate an inside point based on our boundary.
Point _center
An (x,y) location inside the hole.

◆ midpoint()

Point libMesh::TriangulatorInterface::MeshedHole::midpoint ( const unsigned int  ,
const unsigned int   
) const
overridevirtual

Return the midpoint m along the side n defining the hole.

Reimplemented from libMesh::TriangulatorInterface::Hole.

Definition at line 824 of file mesh_triangle_holes.C.

826 {
827  const unsigned int n_mid = this->n_midpoints();
828  libmesh_assert_less (m, n_mid);
829  libmesh_assert_less (n, _points.size());
830  return _midpoints[n*n_mid+m];
831 }
std::vector< Point > _points
The sorted vector of points which makes up the hole.
virtual unsigned int n_midpoints() const override
The number of geometric midpoints along each of the sides defining the hole.
std::vector< Point > _midpoints
The sorted vector of midpoints in between points along the edges of the hole.

◆ n_midpoints()

unsigned int libMesh::TriangulatorInterface::MeshedHole::n_midpoints ( ) const
overridevirtual

The number of geometric midpoints along each of the sides defining the hole.

Reimplemented from libMesh::TriangulatorInterface::Hole.

Definition at line 810 of file mesh_triangle_holes.C.

References libMesh::libmesh_assert().

Referenced by MeshedHole().

811 {
812  libmesh_assert (!(_midpoints.size() % _points.size()));
813  return _midpoints.size() / _points.size();
814 }
std::vector< Point > _points
The sorted vector of points which makes up the hole.
libmesh_assert(ctx)
std::vector< Point > _midpoints
The sorted vector of midpoints in between points along the edges of the hole.

◆ n_points()

unsigned int libMesh::TriangulatorInterface::MeshedHole::n_points ( ) const
overridevirtual

The number of geometric points which define the hole.

Implements libMesh::TriangulatorInterface::Hole.

Definition at line 804 of file mesh_triangle_holes.C.

805 {
806  return _points.size();
807 }
std::vector< Point > _points
The sorted vector of points which makes up the hole.

◆ point()

Point libMesh::TriangulatorInterface::MeshedHole::point ( const unsigned int  n) const
overridevirtual

Return the nth point defining the hole.

Implements libMesh::TriangulatorInterface::Hole.

Definition at line 817 of file mesh_triangle_holes.C.

818 {
819  libmesh_assert_less (n, _points.size());
820  return _points[n];
821 }
std::vector< Point > _points
The sorted vector of points which makes up the hole.

◆ refine_boundary_allowed()

virtual bool libMesh::TriangulatorInterface::Hole::refine_boundary_allowed ( ) const
inlinevirtualinherited

Get whether or not the triangulation is allowed to refine the mesh boundary when refining the interior.

True by default.

Definition at line 140 of file mesh_triangle_holes.h.

References libMesh::TriangulatorInterface::Hole::_refine_bdy_allowed.

Referenced by libMesh::Poly2TriTriangulator::is_refine_boundary_allowed(), and MeshTriangulationTest::testPoly2TriHolesInteriorRefinedBase().

141  { return _refine_bdy_allowed; }
bool _refine_bdy_allowed
Whether to allow boundary refinement.

◆ segment_indices()

virtual std::vector<unsigned int> libMesh::TriangulatorInterface::Hole::segment_indices ( ) const
inlinevirtualinherited

Starting indices of points for a hole with multiple disconnected boundaries.

Reimplemented in libMesh::TriangulatorInterface::ArbitraryHole.

Definition at line 118 of file mesh_triangle_holes.h.

References libMesh::TriangulatorInterface::Hole::n_points().

119  {
120  // default to only one enclosing boundary
121  std::vector<unsigned int> seg;
122  seg.push_back(0);
123  seg.push_back(n_points());
124  return seg;
125  }
virtual unsigned int n_points() const =0
The number of geometric points which define the hole.

◆ set_refine_boundary_allowed()

virtual void libMesh::TriangulatorInterface::Hole::set_refine_boundary_allowed ( bool  refine_bdy_allowed)
inlinevirtualinherited

Set whether or not a triangulator is allowed to refine the hole boundary when refining the mesh interior.

This is true by default, but may be set to false to make the hole boundary more predictable (and so easier to stitch to other meshes) later.

Definition at line 133 of file mesh_triangle_holes.h.

References libMesh::TriangulatorInterface::Hole::_refine_bdy_allowed.

Referenced by MeshTriangulationTest::testPoly2TriHolesInteriorRefinedBase().

134  { _refine_bdy_allowed = refine_bdy_allowed; }
bool _refine_bdy_allowed
Whether to allow boundary refinement.

Member Data Documentation

◆ _center

Point libMesh::TriangulatorInterface::MeshedHole::_center
mutableprivate

An (x,y) location inside the hole.

Cached because this is too expensive to compute for an arbitrary input mesh unless we need it for Triangle.

Definition at line 370 of file mesh_triangle_holes.h.

◆ _midpoints

std::vector<Point> libMesh::TriangulatorInterface::MeshedHole::_midpoints
private

The sorted vector of midpoints in between points along the edges of the hole.

For a hole with m midpoints per edge, between _points[n] and _points[n+1] lies _midpoints[n*m] through _midpoints[n*m+m-1]

Definition at line 383 of file mesh_triangle_holes.h.

Referenced by MeshedHole().

◆ _points

std::vector<Point> libMesh::TriangulatorInterface::MeshedHole::_points
private

The sorted vector of points which makes up the hole.

Definition at line 375 of file mesh_triangle_holes.h.

Referenced by MeshedHole().

◆ _refine_bdy_allowed

bool libMesh::TriangulatorInterface::Hole::_refine_bdy_allowed = true
protectedinherited

Whether to allow boundary refinement.

True by default; specified here so we can use the default constructor.

Definition at line 160 of file mesh_triangle_holes.h.

Referenced by libMesh::TriangulatorInterface::Hole::refine_boundary_allowed(), and libMesh::TriangulatorInterface::Hole::set_refine_boundary_allowed().


The documentation for this class was generated from the following files: