FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
hit_test_factory.hpp
1// FEAT3: Finite Element Analysis Toolbox, Version 3
2// Copyright (C) 2010 by Stefan Turek & the FEAT group
3// FEAT3 is released under the GNU General Public License version 3,
4// see the file 'copyright.txt' in the top level directory for details.
5
6#pragma once
7
8// includes, FEAT
9#include <kernel/geometry/target_set.hpp>
10#include <kernel/geometry/index_set.hpp>
11#include <kernel/geometry/mesh_part.hpp>
12#include <kernel/geometry/atlas/chart.hpp>
13#include <kernel/util/tiny_algebra.hpp>
14
15namespace FEAT
16{
17 namespace Geometry
18 {
20 namespace Intern
21 {
22 template<typename VertexSet_, typename IndexTuple_>
23 inline Tiny::Vector<typename VertexSet_::CoordType, VertexSet_::num_coords>
24 get_midpoint(const VertexSet_& vertex_set, const IndexTuple_& index_tuple)
25 {
26 using DataType = typename VertexSet_::CoordType;
27 constexpr int num_vertex = IndexTuple_::num_indices;
28
29 Tiny::Vector<DataType, VertexSet_::num_coords> mid_point(DataType(0));
30 for(int i(0); i < num_vertex; ++i)
31 {
32 for(int j(0); j < VertexSet_::num_coords; ++j)
33 {
34 mid_point[j] += vertex_set[index_tuple[i]][j];
35 }
36 }
37 return mid_point * (DataType(1) / DataType(num_vertex));
38 }
39
40 template<typename VertexSet_>
41 static Tiny::Vector<typename VertexSet_::CoordType, VertexSet_::num_coords>
42 get_midpoint(const VertexSet_& vertex_set, const Index vertex)
43 {
44 using DataType = typename VertexSet_::CoordType;
45
46 Tiny::Vector<DataType, VertexSet_::num_coords> mid_point;
47 for(int j(0); j < VertexSet_::num_coords; ++j)
48 {
49 mid_point[j] = vertex_set[vertex][j];
50 }
51 return mid_point;
52 }
53
54 template<typename HitFunc_, typename Mesh_, int dim_ = Mesh_::shape_dim>
55 inline void hittest_compute_target_data(
56 std::vector<std::vector<Index>>& target_data,
57 const Mesh_& mesh,
58 const HitFunc_& hit_test)
59 {
60 if constexpr (dim_ == 0)
61 {
62 const Index num_cells(mesh.get_num_entities(0));
63
64 target_data[0].reserve(num_cells);
65 for(Index i(0); i < num_cells; ++i)
66 {
67 if (hit_test(get_midpoint(mesh.get_vertex_set(), i)))
68 {
69 target_data[0].push_back(i);
70 }
71 }
72 }
73 else
74 {
75 // Recurse
76 hittest_compute_target_data<HitFunc_, Mesh_, dim_ - 1>(target_data, mesh, hit_test);
77
78 const Index num_cells(mesh.get_num_entities(dim_));
79 const auto& index_set(mesh.template get_index_set<dim_,0>());
80
81 target_data[dim_].reserve(num_cells);
82 for(Index i(0); i < num_cells; ++i)
83 {
84 if (hit_test(get_midpoint(mesh.get_vertex_set(), index_set[i])))
85 {
86 target_data[dim_].push_back(i);
87 }
88 }
89 }
90 }
91
92 template<typename HitFunc_, typename Mesh_, int dim_ = Mesh_::shape_dim>
93 inline void hittest_compute_filtered_target_data(
94 std::vector<std::vector<Index>>& target_data,
95 const Mesh_& mesh,
96 const MeshPart<Mesh_>& part,
97 const HitFunc_& hit_test)
98 {
99 if constexpr (dim_ == 0)
100 {
101 const Index num_cells(part.get_num_entities(0));
102 const TargetSet& vertex_target_set = part.template get_target_set<0>();
103
104 target_data[0].reserve(num_cells);
105 for(Index i(0); i < num_cells; ++i)
106 {
107 const Index vertex = vertex_target_set[i];
108 if (hit_test(get_midpoint(mesh.get_vertex_set(), vertex)))
109 {
110 target_data[0].push_back(vertex);
111 }
112 }
113 }
114 else
115 {
116 // Recurse
117 hittest_compute_filtered_target_data<HitFunc_, Mesh_, dim_ - 1>(target_data, mesh, part, hit_test);
118
119 const Index num_cells(part.get_num_entities(dim_));
120 const TargetSet& filter_target_set = part.template get_target_set<dim_>();
121 const auto& index_set(mesh.template get_index_set<dim_,0>());
122
123 target_data[dim_].reserve(num_cells);
124 for(Index i(0); i < num_cells; ++i)
125 {
126 const Index entity = filter_target_set[i];
127 if (hit_test(get_midpoint(mesh.get_vertex_set(), index_set[entity])))
128 {
129 target_data[dim_].push_back(entity);
130 }
131 }
132 }
133 }
134
135 template<typename Shape_, int dim_ = Shape_::dimension>
136 inline void write_to_target_set(TargetSetHolder<Shape_>& tsh, std::vector<std::vector<Index>>& source)
137 {
138 if constexpr (dim_ < 0)
139 {
140 return;
141 }
142 else
143 {
144 // Recurse
145 write_to_target_set<Shape_, dim_ - 1>(tsh, source);
146
147 const auto num_cells(Index(source[dim_].size()));
148 TargetSet& trg = tsh.template get_target_set<dim_>();
149 for(Index i(0); i < num_cells; ++i)
150 {
151 trg[i] = source[dim_][i];
152 }
153
154 }
155 }
156 } // namespace Intern
158
175 template<
176 typename HitFunc_,
177 typename Mesh_>
179 public Factory< MeshPart<Mesh_> >
180 {
181 public:
183 typedef typename Mesh_::ShapeType ShapeType;
188
189 protected:
191 const HitFunc_& _hit_func;
193 const Mesh_& _mesh;
195 std::vector<std::vector<Index>> _target_data;
196
197 public:
207 explicit HitTestFactory(const HitFunc_& hit_func, const Mesh_& mesh) :
208 _hit_func(hit_func),
209 _mesh(mesh),
210 _target_data(std::size_t(_mesh.shape_dim+1))
211 {
212 Intern::hittest_compute_target_data<HitFunc_, Mesh_>(_target_data, _mesh, _hit_func);
213 }
214
228 explicit HitTestFactory(const HitFunc_& hit_func, const Mesh_& mesh, const MeshType& filter) :
229 _hit_func(hit_func),
230 _mesh(mesh),
231 _target_data(std::size_t(_mesh.shape_dim+1))
232 {
233 Intern::hittest_compute_filtered_target_data<HitFunc_, Mesh_>(_target_data, _mesh, filter, _hit_func);
234 }
235
237 virtual Index get_num_entities(int dim) override
238 {
239 return Index(_target_data.at(std::size_t(dim)).size());
240 }
241
242 virtual void fill_target_sets(TargetSetHolderType& target_set_holder) override
243 {
244 Intern::write_to_target_set(target_set_holder, _target_data);
245 }
246
247 virtual void fill_attribute_sets(typename MeshType::AttributeSetContainer&) override
248 {
249 // do nothing as the object has no attribute sets
250 }
251
252 virtual void fill_index_sets(std::unique_ptr<typename MeshType::IndexSetHolderType>&) override
253 {
254 // do nothing as the object has no index sets
255 }
256
257 }; // class HitTestFactory
258
271 template<typename Mesh_, typename HitFunc_>
272 MeshPart<Mesh_> make_meshpart_by_hit_test(const Mesh_& mesh, const HitFunc_& hit_func)
273 {
274 HitTestFactory<HitFunc_, Mesh_> factory(mesh, hit_func);
275 return factory.make();
276 }
277
294 template<typename Mesh_, typename HitFunc_>
295 MeshPart<Mesh_> make_meshpart_by_filtered_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, const HitFunc_& hit_func)
296 {
297 HitTestFactory<HitFunc_, Mesh_> factory(mesh, filter, hit_func);
298 return factory.make();
299 }
300
313 template<typename Mesh_, typename HitFunc_>
314 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_hit_test(const Mesh_& mesh, const HitFunc_& hit_func)
315 {
316 HitTestFactory<HitFunc_, Mesh_> factory(mesh, hit_func);
317 return factory.make_unique();
318 }
319
336 template<typename Mesh_, typename HitFunc_>
337 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_filtered_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, const HitFunc_& hit_func)
338 {
339 HitTestFactory<HitFunc_, Mesh_> factory(mesh, filter, hit_func);
340 return factory.make_unique();
341 }
342
357 template<typename DataType_, int dim_>
359 {
360 public:
363
364 private:
368 DataType_ _radius;
369
370 public:
377 explicit SphereHitTestFunction(DataType_ radius) :
378 _midpoint(DataType_(0)),
379 _radius(radius)
380 {
381 XASSERTM(radius > DataType_(0), "sphere radius must be > 0");
382 }
383
393 SphereHitTestFunction(PointType midpoint, DataType_ radius) :
394 _midpoint(midpoint),
395 _radius(radius)
396 {
397 XASSERTM(radius > DataType_(0), "sphere radius must be > 0");
398 }
399
409 bool operator()(PointType point) const
410 {
411 return (point - _midpoint).norm_euclid() <= _radius;
412 }
413 }; // class SphereHitTestFunction<...>
414
415
430 template<typename Mesh_, typename Chart_ = Atlas::ChartBase<Mesh_>>
432 public Factory< MeshPart<Mesh_> >
433 {
434 public:
436 typedef typename Mesh_::ShapeType ShapeType;
441
443 {
444 typedef typename Mesh_::CoordType CoordType;
445 typedef typename Mesh_::VertexType WorldPointType;
446
447 protected:
449 const CoordType _inv;
450 const CoordType _tol;
451
452 public:
453 explicit ChartHitFunction(const Geometry::Atlas::ChartBase<Mesh_>& chart, bool invert, CoordType tol = CoordType(0)) :
454 _chart(chart),
455 _inv(CoordType(invert ? -1 : 1)),
456 _tol(tol)
457 {
458 }
459
460 bool operator()(const WorldPointType& point) const
461 {
462 return _inv * _chart.signed_dist(point) <= _tol;
463 }
464 };
465
466 protected:
468 const Mesh_& _mesh;
472 std::vector<std::vector<Index>> _target_data;
473
474 public:
493 explicit ChartHitTestFactory(const Mesh_& mesh, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0)) :
494 _mesh(mesh),
495 _hit_func(chart, invert, tol),
496 _target_data(std::size_t(_mesh.shape_dim+1))
497 {
498 Intern::hittest_compute_target_data<ChartHitFunction, Mesh_>(_target_data, _mesh, _hit_func);
499 }
500
523 explicit ChartHitTestFactory(const Mesh_& mesh, const MeshType& filter, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0)) :
524 _mesh(mesh),
525 _hit_func(chart, invert, tol),
526 _target_data(std::size_t(_mesh.shape_dim+1))
527 {
528 Intern::hittest_compute_filtered_target_data<ChartHitFunction, Mesh_>(_target_data, _mesh, filter, _hit_func);
529 }
530
532 virtual Index get_num_entities(int dim) override
533 {
534 return Index(_target_data.at(std::size_t(dim)).size());
535 }
536
537 virtual void fill_target_sets(TargetSetHolderType& target_set_holder) override
538 {
539 Intern::write_to_target_set<ShapeType>(target_set_holder, _target_data);
540 }
541
542 virtual void fill_attribute_sets(typename MeshType::AttributeSetContainer&) override
543 {
544 // do nothing as the object has no attribute sets
545 }
546
547 virtual void fill_index_sets(std::unique_ptr<typename MeshType::IndexSetHolderType>&) override
548 {
549 // do nothing as the object has no index sets
550 }
551 }; // class ChartHitTestFactory
552
574 template<typename Mesh_, typename Chart_>
575 MeshPart<Mesh_> make_meshpart_by_chart_hit_test(const Mesh_& mesh, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0))
576 {
577 ChartHitTestFactory<Mesh_, Chart_> factory(mesh, chart, invert, tol);
578 return factory.make();
579 }
580
606 template<typename Mesh_, typename Chart_>
607 MeshPart<Mesh_> make_meshpart_by_filtered_chart_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0))
608 {
609 ChartHitTestFactory<Mesh_, Chart_> factory(mesh, filter, chart, invert, tol);
610 return factory.make();
611 }
612
634 template<typename Mesh_, typename Chart_>
635 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_chart_hit_test(const Mesh_& mesh, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0))
636 {
637 ChartHitTestFactory<Mesh_, Chart_> factory(mesh, chart, invert, tol);
638 return factory.make_unique();
639 }
640
666 template<typename Mesh_, typename Chart_>
667 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_filtered_chart_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, const Chart_& chart, bool invert = false, typename Mesh_::CoordType tol = typename Mesh_::CoordType(0))
668 {
669 ChartHitTestFactory<Mesh_, Chart_> factory(mesh, filter, chart, invert, tol);
670 return factory.make_unique();
671 }
672
688 template<typename Mesh_, typename Lambda_>
690 public Factory< MeshPart<Mesh_> >
691 {
692 public:
694 typedef typename Mesh_::ShapeType ShapeType;
699
700 protected:
703 {
704 public:
705 Lambda_ lambda;
706
707 explicit HitTestLambda(Lambda_&& lb) :
708 lambda(std::forward<Lambda_>(lb))
709 {
710 }
711
713 template<typename T_, int s_>
715 {
716 return lambda(p[0]);
717 }
718
720 template<typename T_, int s_>
722 {
723 return lambda(p[0], p[1]);
724 }
725
727 template<typename T_, int s_>
729 {
730 return lambda(p[0], p[1], p[3]);
731 }
732 } _hit_func;
734 const Mesh_& _mesh;
736 std::vector<std::vector<Index>> _target_data;
737
738 public:
748 explicit LambdaHitTestFactory(const Mesh_& mesh, Lambda_&& lambda) :
749 _hit_func(std::forward<Lambda_>(lambda)),
750 _mesh(mesh),
751 _target_data(std::size_t(_mesh.shape_dim+1))
752 {
753 Intern::hittest_compute_target_data<HitTestLambda, Mesh_>(_target_data, _mesh, _hit_func);
754 }
755
769 explicit LambdaHitTestFactory(const Mesh_& mesh, const MeshType& filter, Lambda_&& lambda) :
770 _hit_func(std::forward<Lambda_>(lambda)),
771 _mesh(mesh),
772 _target_data(std::size_t(_mesh.shape_dim+1))
773 {
774 Intern::hittest_compute_filtered_target_data<HitTestLambda, Mesh_>(_target_data, _mesh, filter, _hit_func);
775 }
776
778 virtual Index get_num_entities(int dim) override
779 {
780 return Index(_target_data.at(std::size_t(dim)).size());
781 }
782
783 virtual void fill_target_sets(TargetSetHolderType& target_set_holder) override
784 {
785 Intern::write_to_target_set<ShapeType>(target_set_holder, _target_data);
786 }
787
788 virtual void fill_attribute_sets(typename MeshType::AttributeSetContainer&) override
789 {
790 // do nothing as the object has no attribute sets
791 }
792
793 virtual void fill_index_sets(std::unique_ptr<typename MeshType::IndexSetHolderType>&) override
794 {
795 // do nothing as the object has no index sets
796 }
797 }; // class LambdaHitTestFactory
798
811 template<typename Mesh_, typename Lambda_>
812 MeshPart<Mesh_> make_meshpart_by_lambda_hit_test(const Mesh_& mesh, Lambda_&& lambda)
813 {
814 LambdaHitTestFactory<Mesh_, Lambda_> factory(mesh, std::forward<Lambda_>(lambda));
815 return factory.make();
816 }
817
834 template<typename Mesh_, typename Lambda_>
835 MeshPart<Mesh_> make_meshpart_by_filtered_lambda_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, Lambda_&& lambda)
836 {
837 LambdaHitTestFactory<Mesh_, Lambda_> factory(mesh, filter, std::forward<Lambda_>(lambda));
838 return factory.make();
839 }
840
853 template<typename Mesh_, typename Lambda_>
854 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_lambda_hit_test(const Mesh_& mesh, Lambda_&& lambda)
855 {
856 LambdaHitTestFactory<Mesh_, Lambda_> factory(mesh, std::forward<Lambda_>(lambda));
857 return factory.make_unique();
858 }
859
876 template<typename Mesh_, typename Lambda_>
877 std::unique_ptr<MeshPart<Mesh_>> make_unique_meshpart_by_filtered_lambda_hit_test(const Mesh_& mesh, const MeshPart<Mesh_>& filter, Lambda_&& lambda)
878 {
879 LambdaHitTestFactory<Mesh_, Lambda_> factory(mesh, filter, std::forward<Lambda_>(lambda));
880 return factory.make_unique();
881 }
882 } // namespace Geometry
883} // namespace FEAT
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
virtual CoordType signed_dist(const WorldPoint &point) const =0
Computes the signed distance of a point to this chart.
Chart-based Hit-Test Factory class template.
ChartHitTestFactory(const Mesh_ &mesh, const MeshType &filter, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates the factory.
MeshType::TargetSetHolderType TargetSetHolderType
target set holder type
std::vector< std::vector< Index > > _target_data
internal data storing the indices
virtual Index get_num_entities(int dim) override
Mesh_::ShapeType ShapeType
The shape type of the mesh.
ChartHitTestFactory(const Mesh_ &mesh, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates the factory.
ChartHitFunction _hit_func
our hit function
MeshPart< Mesh_ > MeshType
mesh part type
const Mesh_ & _mesh
reference to the input mesh
Mesh Factory class template.
Definition: factory.hpp:33
Hit-Test Factory class template.
Mesh_::ShapeType ShapeType
The shape type of the mesh.
HitTestFactory(const HitFunc_ &hit_func, const Mesh_ &mesh, const MeshType &filter)
Creates the factory.
std::vector< std::vector< Index > > _target_data
internal data storing the indices
virtual Index get_num_entities(int dim) override
HitTestFactory(const HitFunc_ &hit_func, const Mesh_ &mesh)
Creates the factory.
const HitFunc_ & _hit_func
reference to the hit-test function
MeshPart< Mesh_ > MeshType
mesh part type
MeshType::TargetSetHolderType TargetSetHolderType
target set holder type
const Mesh_ & _mesh
reference to the input mesh
bool operator()(const Tiny::Vector< T_, 3, s_ > &p) const
3D point overload
bool operator()(const Tiny::Vector< T_, 2, s_ > &p) const
2D point overload
bool operator()(const Tiny::Vector< T_, 1, s_ > &p) const
1D point overload
Lambda Hit-Test Factory class template.
Mesh_::ShapeType ShapeType
The shape type of the mesh.
MeshType::TargetSetHolderType TargetSetHolderType
target set holder type
MeshPart< Mesh_ > MeshType
mesh part type
LambdaHitTestFactory(const Mesh_ &mesh, const MeshType &filter, Lambda_ &&lambda)
Creates the factory.
LambdaHitTestFactory(const Mesh_ &mesh, Lambda_ &&lambda)
Creates the factory.
std::vector< std::vector< Index > > _target_data
internal data storing the indices
const Mesh_ & _mesh
reference to the input mesh
virtual Index get_num_entities(int dim) override
Class template for partial meshes.
Definition: mesh_part.hpp:90
TargetSetHolder< ShapeType > TargetSetHolderType
Target set holder type.
Definition: mesh_part.hpp:101
std::map< String, std::unique_ptr< AttributeSetType > > AttributeSetContainer
submesh node bin container type
Definition: mesh_part.hpp:138
SphereHitTestFunction(DataType_ radius)
Creates a sphere around the origin.
PointType _midpoint
the sphere's midpoint
Tiny::Vector< DataType_, dim_ > PointType
The point type.
SphereHitTestFunction(PointType midpoint, DataType_ radius)
Creates a sphere.
DataType_ _radius
the sphere's radius
bool operator()(PointType point) const
Performs the hit-test.
Tiny Vector class template.
MeshPart< Mesh_ > make_meshpart_by_filtered_lambda_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, Lambda_ &&lambda)
Creates a new mesh-part from a lambda hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_chart_hit_test(const Mesh_ &mesh, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates a new mesh-part from a chart hit-test function.
MeshPart< Mesh_ > make_meshpart_by_filtered_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, const HitFunc_ &hit_func)
Creates a new mesh-part from a hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_filtered_chart_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates a new mesh-part from a chart hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_lambda_hit_test(const Mesh_ &mesh, Lambda_ &&lambda)
Creates a new mesh-part from a lambda hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_filtered_lambda_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, Lambda_ &&lambda)
Creates a new mesh-part from a lambda hit-test function.
MeshPart< Mesh_ > make_meshpart_by_hit_test(const Mesh_ &mesh, const HitFunc_ &hit_func)
Creates a new mesh-part from a hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_filtered_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, const HitFunc_ &hit_func)
Creates a new mesh-part from a hit-test function.
MeshPart< Mesh_ > make_meshpart_by_chart_hit_test(const Mesh_ &mesh, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates a new mesh-part from a chart hit-test function.
std::unique_ptr< MeshPart< Mesh_ > > make_unique_meshpart_by_hit_test(const Mesh_ &mesh, const HitFunc_ &hit_func)
Creates a new mesh-part from a hit-test function.
MeshPart< Mesh_ > make_meshpart_by_lambda_hit_test(const Mesh_ &mesh, Lambda_ &&lambda)
Creates a new mesh-part from a lambda hit-test function.
MeshPart< Mesh_ > make_meshpart_by_filtered_chart_hit_test(const Mesh_ &mesh, const MeshPart< Mesh_ > &filter, const Chart_ &chart, bool invert=false, typename Mesh_::CoordType tol=typename Mesh_::CoordType(0))
Creates a new mesh-part from a chart hit-test function.
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.