FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
meshpart_converter.hpp
1#pragma once
2#include <kernel/geometry/mesh_part.hpp>
3#include <kernel/geometry/atlas/bezier.hpp>
4#include <kernel/adjacency/graph.hpp>
5
6
7namespace FEAT::Geometry::Intern
8{
9
10 template<typename Shape_>
12 {
13 public:
14 // typedef Mesh_ MeshType;
17 static constexpr int dim = MeshType::shape_dim;
18 typedef typename MeshType::CoordType DataType;
19
20
21 static std::unique_ptr<Atlas::ChartBase<MeshType>> meshpart_to_bezier(const MeshType& mesh, const MeshPartType& meshpart)
22 {
23 // only works in 2d
24 if constexpr(dim == 2)
25 {
26 const auto& vtx_set = mesh.get_vertex_set();
27 const auto& edge_to_vert = mesh.template get_index_set<1, 0>();
28 const auto& face_to_edge = mesh.template get_index_set<2, 1>();
29 const auto& face_to_vert = mesh.template get_index_set<2, 0>();
32
33 const auto& target_set = meshpart.template get_target_set<1>();
34
35 std::vector<Index> is_target(mesh.get_num_entities(1));
36 std::for_each(is_target.begin(), is_target.end(), [](Index& a){a = Index(0);});
37 for(Index k = 0; k < target_set.get_num_entities(); ++k)
38 {
39 is_target[target_set[k]] = Index(1);
40 }
41
42 XASSERTM(target_set.get_num_entities() > 0u, "Trying to create bezier chart from non 1d meshpart");
43
44 std::vector<Tiny::Vector<DataType, dim>> vtx_line;
45 vtx_line.reserve(target_set.get_num_entities()+1);
46
47 bool not_closed = false;
48 Index cur_edge = target_set[0];
49 Index prev_vert = ~Index(0);
50 const auto* dom_ptr = vert_to_edge.get_domain_ptr();
51 const auto* img_ptr = vert_to_edge.get_image_idx();
52 // first of all, see if we start at a beginning or somewhere inside our mehspart
53 for(int k = 0; k < edge_to_vert.get_num_indices(); ++k)
54 {
55 Index cur_vert = edge_to_vert[target_set[0]][k];
56 bool is_boundary = true;
57 for(Index l = dom_ptr[cur_vert]; l < dom_ptr[cur_vert+1]; ++l)
58 {
59 if(img_ptr[l] != cur_edge && is_target[img_ptr[l]] == Index(1))
60 is_boundary = false;
61 }
62 if(is_boundary)
63 {
64 prev_vert = cur_vert;
65 not_closed = true;
66 }
67 }
68
69 if(prev_vert == ~Index(0))
70 {
71 prev_vert = edge_to_vert[target_set[0]][0];
72 }
73
74 const Index start_edge = target_set[0];
75 vtx_line.push_back(vtx_set[prev_vert]);
76
77 // track while running through our edges which orientation we are having
78 Index orientation = Index(2);
79
80 while(true)
81 {
82 Index cur_vert = Index(0);
83 // first of all get the vertex not yet handled
84 for(int k = 0; k < edge_to_vert.get_num_indices(); ++k)
85 {
86 if(edge_to_vert[cur_edge][k] != prev_vert)
87 {
88 cur_vert = edge_to_vert[cur_edge][k];
89 break;
90 }
91 }
92
93 vtx_line.push_back(vtx_set[cur_vert]);
94
95 // TODO: we could do this smarter by comparing orientation of the cell and the referance egde, but this is more striaghtforward
96 if(orientation != ~Index(0))
97 {
98 // compute mid vertex of our line segment
99 auto mid_e = DataType(0.5) * (vtx_set[cur_vert] + vtx_set[prev_vert]);
100 // compute mean value of our cell
101 auto mid_c = Tiny::Vector<DataType, dim>();
102 mid_c.format();
103 if(edge_to_face.degree(cur_edge) != Index(1))
104 {
105 orientation = ~Index(0);
106 }
107 if(orientation != ~Index(0))
108 {
109 // get cell of our edge
110 const auto& index_tuple = face_to_vert[edge_to_face.get_image_idx()[edge_to_face.get_domain_ptr()[cur_edge]]];
111 for(int k = 0; k < index_tuple.num_indices; ++k)
112 {
113 mid_c.axpy(DataType(1)/DataType(index_tuple.num_indices), vtx_set[index_tuple[k]]);
114 }
115
116 const auto outer_normal = mid_e - mid_c;
117 const auto line_segment = vtx_set[cur_vert] - vtx_set[prev_vert];
118
119 // rotate line_segment by -90 degrees (i.e. to the right)
120 const auto right_normal = Tiny::Vector<DataType, dim>{line_segment[1], -line_segment[0]};
121
122 // if vectors are on the same halfplane, we have positive, i.e. counterclockwise orientation
123 const Index new_orient = Tiny::dot(right_normal, outer_normal) > 0 ? Index(1) : Index(0);
124 if(orientation == Index(2)) orientation = new_orient;
125 XASSERTM(orientation == new_orient, "Non orientable");
126 }
127 }
128
129
130 Index next_edge = ~Index(0);
131 // find next edge
132 for(Index l = dom_ptr[cur_vert]; l < dom_ptr[cur_vert+1]; ++l)
133 {
134 if(img_ptr[l] != cur_edge && is_target[img_ptr[l]] == Index(1))
135 {
136 next_edge = img_ptr[l];
137 break;
138 }
139 }
140 if(next_edge == ~Index(0))
141 {
142 not_closed = true;
143 break;
144 }
145
146 if(next_edge == start_edge)
147 {
148 break;
149 }
150
151 cur_edge = next_edge;
152 prev_vert = cur_vert;
153 }
154
155 std::unique_ptr<Atlas::Bezier<MeshType>> bezier = std::make_unique<Atlas::Bezier<MeshType>>(!not_closed, orientation == Index(0) ? 1 : -1);
156 for(Index k = 0; k < vtx_line.size(); ++k)
157 {
158 bezier->push_vertex(vtx_line[k]);
159 bezier->push_param(Tiny::Vector<DataType, 1>{DataType(k)});
160 }
161
162 return bezier;
163
164 }
165 else
166 {
167 XABORTM("Bezier chart only valid in 2d");
168 }
169
170 return std::unique_ptr<Atlas::ChartBase<MeshType>>{nullptr};
171 }
172
173 };
174
175}
#define XABORTM(msg)
Abortion macro definition with custom message.
Definition: assertion.hpp:192
#define XASSERTM(expr, msg)
Assertion macro definition with custom message.
Definition: assertion.hpp:263
Adjacency Graph implementation.
Definition: graph.hpp:34
Index * get_domain_ptr()
Returns the domain pointer array.
Definition: graph.hpp:359
Index * get_image_idx()
Returns the image node index array.
Definition: graph.hpp:374
Index degree(Index domain_node) const
Returns the degree of a domain node.
Definition: graph.hpp:333
Conformal mesh class template.
Index get_num_entities(int dim) const
Returns the number of entities.
static constexpr int shape_dim
shape dimension
Coord_ CoordType
Coordinate type.
VertexSetType & get_vertex_set()
Returns a reference to the vertex set of the mesh.
Class template for partial meshes.
Definition: mesh_part.hpp:90
Tiny Vector class template.
@ injectify_transpose
Render-Injectified-Transpose mode.
CUDA_HOST_DEVICE T_ dot(const T_ &a, const T_ &b)
Computes the dot-product of two scalars.
std::uint64_t Index
Index data type.