FEAT 3
Finite Element Analysis Toolbox
Loading...
Searching...
No Matches
extrude.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#include <kernel/geometry/atlas/chart.hpp>
9// supported sub-charts:
10#include <kernel/geometry/atlas/bezier.hpp>
11#include <kernel/geometry/atlas/circle.hpp>
12
13namespace FEAT
14{
15 namespace Geometry
16 {
17 namespace Atlas
18 {
19 template<typename SubChart_>
21 {
23 static constexpr bool is_explicit = SubChart_::is_explicit;
25 static constexpr bool is_implicit = SubChart_::is_implicit;
27 static constexpr int world_dim = 3;
29 static constexpr int param_dim = 2;
30 };
31
32 template<typename Mesh_, typename SubChart_>
33 class Extrude :
34 public ChartCRTP<Extrude<Mesh_, SubChart_>, Mesh_, ExtrudeTraits<SubChart_>>
35 {
36 public:
45
46 typedef typename SubChart_::WorldPoint SubWorldPoint;
47 typedef typename SubChart_::ParamPoint SubParamPoint;
48
49 //protected:
51 std::unique_ptr<SubChart_> _sub_chart;
52
53 protected:
60
61 public:
62 explicit Extrude() :
64 {
68 }
69
70 explicit Extrude(std::unique_ptr<SubChart_> sub_chart) :
71 _sub_chart(std::move(sub_chart))
72 {
76 }
77
78 virtual ~Extrude()
79 {
80 }
81
82 void set_origin(CoordType x, CoordType y)
83 {
84 _origin[0] = x;
85 _origin[1] = y;
86 }
87
88 void set_offset(CoordType x, CoordType y, CoordType z)
89 {
90 _offset[0] = x;
91 _offset[1] = y;
92 _offset[2] = z;
93 }
94
95 void set_angles(CoordType yaw, CoordType pitch, CoordType roll)
96 {
97 _rotation.set_rotation_3d(yaw, pitch, roll);
98 }
99
100 void set_sub_chart(std::unique_ptr<SubChart_> sub_chart)
101 {
102 XASSERTM(bool(_sub_chart), "Extrude chart already has a sub-chart");
103 _sub_chart = std::move(sub_chart);
104 }
105
106 virtual bool can_implicit() const override
107 {
108 return _sub_chart->can_implicit();
109 }
110
111 virtual bool can_explicit() const override
112 {
113 return _sub_chart->can_explicit();
114 }
115
116 void transform_2d_to_3d(WorldPoint& p, const SubWorldPoint& q, const CoordType z = CoordType(0)) const
117 {
118 // apply our extrude transformation:
119 // p = w + R * (q - v)
120 WorldPoint x;
121 x[0] = q[0] - _origin[0];
122 x[1] = q[1] - _origin[1];
123 x[2] = z;
124 p.set_mat_vec_mult(_rotation, x);
125 p += _offset;
126 }
127
128 void transform_3d_to_2d(const WorldPoint& p, SubWorldPoint& q, CoordType& z) const
129 {
130 // apply our inverse extrude transformation:
131 // q = v + R^{-1} * (p - w)
132 WorldPoint x = p - _offset;
133 WorldPoint y;
134 // rotation matrices are orthogonal, i.e. R^{-1} = R^T
135 y.set_vec_mat_mult(x, _rotation);
136 q[0] = y[0] - _origin[0];
137 q[1] = y[1] - _origin[1];
138 z = y[2];
139 }
140
141 void transform_3d_to_2d(const WorldPoint& p, SubWorldPoint& q) const
142 {
143 CoordType z = CoordType(0);
144 transform_3d_to_2d(p, q, z);
145 }
146
147 virtual void transform(const WorldPoint& origin, const WorldPoint& angles, const WorldPoint& offset) override
148 {
149 // the rotation matrix
150 Tiny::Matrix<CoordType, 3, 3> rotation;
151 rotation.set_rotation_3d(angles[0], angles[1], angles[2]);
152
153 // we now have 2 transformations:
154 // 1. from the extrude chart itself and
155 // 2. from the parameters given to this function
156 //
157 // The new extrusion chart transformation is given by the concatenation of the
158 // two above transformations:
159 //
160 // v2 + R2 * ( (v1 + R1*(x - w1)) - w2)
161 // = v2 + R2*(v1 - w2) + R2*R1*(x - w1)
162 // \---------------/ \---/ \/
163 // v3 R3 w3
164 //
165 // where
166 // vi = offset
167 // Ri = rotation
168 // wi = origin
169
170 WorldPoint tmp1, tmp2;
171
172 // let us first update the offset vector v3:
173 // compute offset vector v3 := v2 + R1*(v1 - w2)
174 tmp1 = _offset - origin;
175 tmp2.set_mat_vec_mult(rotation, tmp1);
176 _offset = offset + tmp2;
177
178 // compute rotation matrix R3 := R2*R1
179 Tiny::Matrix<CoordType, 3, 3> old_rot(_rotation);
180 _rotation.set_mat_mat_mult(rotation, old_rot);
181
182 // our origin vector w3 remains the same (= w1)
183 }
184
185 void project_point(WorldPoint& point) const
186 {
187 // transform to 2d
188 SubWorldPoint sub_point;
189 CoordType z = CoordType(0);
190 transform_3d_to_2d(point, sub_point, z);
191 // project in 2d
192 _sub_chart->project_point(sub_point);
193 // transform to 3d
194 transform_2d_to_3d(point, sub_point, z);
195 }
196
197 void project_meshpart(Mesh_& mesh, const MeshPart<Mesh_>& meshpart) const
198 {
199 auto& vtx = mesh.get_vertex_set();
200 const auto& target_vtx = meshpart.template get_target_set<0>();
201 for(Index i(0); i < meshpart.get_num_entities(0); ++i)
202 {
203 project_point(reinterpret_cast<WorldPoint&>(vtx[target_vtx[i]]));
204 }
205 }
206
207 void map_param(WorldPoint& point, const ParamPoint& param) const
208 {
209 // map the parameter in 2D
210 SubParamPoint sub_param;
211 sub_param[0] = param[0];
212 SubWorldPoint sub_point;
213 _sub_chart->map_param(sub_point, sub_param);
214 // transform to 3d
215 transform_2d_to_3d(point, sub_point, param[1]);
216 }
217
220 {
221 // transform to 2d
222 SubWorldPoint sub_point;
223 transform_3d_to_2d(point, sub_point);
224 return _sub_chart->compute_dist(sub_point);
225 }
226
228 CoordType compute_dist(const WorldPoint& point, WorldPoint& grad_dist) const
229 {
230 // transform to 2d
231 SubWorldPoint sub_point;
232 CoordType z = CoordType(0);
233 transform_3d_to_2d(point, sub_point, z);
234
235 SubWorldPoint sub_grad_dist;
236
237 CoordType my_dist(_sub_chart->compute_dist(sub_point, sub_grad_dist));
238
239 ASSERT(my_dist >= CoordType(0));
240
241 // transform to 3d
242 transform_2d_to_3d(grad_dist, sub_grad_dist, z);
243
244 return my_dist;
245 }
246
249 {
250 // transform to 2d
251 SubWorldPoint sub_point;
252 transform_3d_to_2d(point, sub_point);
253 return _sub_chart->compute_signed_dist(sub_point);
254 }
255
257 CoordType compute_signed_dist(const WorldPoint& point, WorldPoint& grad_dist) const
258 {
259 // transform to 2d
260 SubWorldPoint sub_point;
261 CoordType z = CoordType(0);
262 transform_3d_to_2d(point, sub_point, z);
263
264 SubWorldPoint sub_grad_dist;
265
266 CoordType my_dist(_sub_chart->compute_dist(sub_point, sub_grad_dist));
267
268 // transform to 3d
269 transform_2d_to_3d(grad_dist, sub_grad_dist, z);
270
271 return my_dist;
272 }
273
274 virtual String get_type() const override
275 {
276 return "extrude";
277 }
278
279 virtual void write(std::ostream& os, const String& sindent) const override
280 {
281 String sind(sindent);
282 if(!sind.empty())
283 sind.append(" ");
284
285 const CoordType tol = Math::pow(Math::eps<CoordType>(), CoordType(0.7));
286
287 os << sindent << "<Extrude";
288 if(_origin.norm_euclid_sqr() > tol)
289 os << " origin=\"" << _origin[0] << " " << _origin[1] << "\"";
290 if(_offset.norm_euclid_sqr() > tol)
291 os << " offset=\"" << _offset[0] << " " << _offset[1] << " " << _offset[2] << "\"";
292
293 // check whether our rotation matrix is the identity matrix
295 {
296 // Now that's tricky: we have to reconstruct the yaw-pitch-roll angles
297 // from the rotation matrix: see \cite Craig04, page 43, eq. (2.66) -- (2.68)
298 const CoordType pi = Math::pi<CoordType>();
299 const CoordType pi_2 = CoordType(0.5) * pi;
300 const CoordType r11 = _rotation(0,0);
301 const CoordType r12 = _rotation(0,1);
302 const CoordType r21 = _rotation(1,0);
303 const CoordType r22 = _rotation(1,1);
304 const CoordType r31 = _rotation(2,0);
305 const CoordType r32 = _rotation(2,1);
306 const CoordType r33 = _rotation(2,2);
307 CoordType ay = CoordType(0); // yaw (in book: alpha)
308 CoordType ap = CoordType(0); // pitch (in book: beta)
309 CoordType ar = CoordType(0); // roll (in book: gamma)
310
311 // determine the pitch first
312 ap = Math::atan2(-r31, Math::sqrt(r11*r11 + r21*r21));
313
314 // check pitch for "gimbal lock" angles +pi/2 and -pi/2
315 if(ap >= pi_2 - tol)
316 {
317 ap = pi_2;
318 ar = Math::atan2(r12, r22);
319 }
320 else if(ap <= -pi_2 + tol)
321 {
322 ap = -pi_2;
323 ar = -Math::atan2(r12, r22);
324 }
325 else // no gimbal lock
326 {
327 // Note: we can safely drop the "c\beta" denominators from the book,
328 // as these always cancel out by definition of atan2
329 ay = Math::atan2(r21, r11);
330 ar = Math::atan2(r32, r33);
331 }
332
333 // convert angles from radians to revolutions and write out
334 const CoordType mult = CoordType(0.5) / pi;
335 os << " angles=\"" << (mult*ay) << " " << (mult*ap) << " " << (mult*ar) << "\"";
336 }
337 os << ">\n";
338
339 _sub_chart->write(os, sind);
340 os << sindent << "</Extrude>\n";
341 }
342 };
343
344 template<typename Mesh_, bool enable_ = (Mesh_::shape_dim > 2)>
346 public Xml::DummyParser
347 {
348 public:
349 explicit ExtrudeChartParser(std::unique_ptr<ChartBase<Mesh_>>&)
350 {
351 XABORTM("Thou shall not arrive here");
352 }
353 };
354
355 template<typename Mesh_>
356 class ExtrudeChartParser<Mesh_, true> :
357 public Xml::MarkupParser
358 {
359 private:
360 typedef typename ChartBase<Mesh_>::CoordType CoordType;
361 std::unique_ptr<ChartBase<Mesh_>>& _chart;
362 CoordType _ori_x, _ori_y;
363 CoordType _off_x, _off_y, _off_z;
364 CoordType _yaw, _pitch, _roll;
365
366 public:
367 explicit ExtrudeChartParser(std::unique_ptr<ChartBase<Mesh_>>& chart) :
368 _chart(chart),
369 _ori_x(CoordType(0)),
370 _ori_y(CoordType(0)),
371 _off_x(CoordType(0)),
372 _off_y(CoordType(0)),
373 _off_z(CoordType(0)),
374 _yaw(CoordType(0)),
375 _pitch(CoordType(0)),
376 _roll(CoordType(0))
377 {
378 }
379
380 virtual bool attribs(std::map<String,bool>& attrs) const override
381 {
382 // allowed for upwards compatibility
383 attrs.emplace("origin", false);
384 attrs.emplace("offset", false);
385 attrs.emplace("angles", false);
386 return true;
387 }
388
389 virtual void create(
390 int iline,
391 const String& sline,
392 const String&,
393 const std::map<String, String>& attrs,
394 bool) override
395 {
396 // parse 2D origin (if given)
397 {
398 auto it = attrs.find("origin");
399 if(it != attrs.end())
400 {
401 std::deque<String> sori = it->second.split_by_whitespaces();
402 if(sori.size() != std::size_t(2))
403 throw Xml::GrammarError(iline, sline, "Invalid Extrude chart origin attribute");
404 if(!sori.front().parse(_ori_x) || !sori.back().parse(_ori_y))
405 throw Xml::GrammarError(iline, sline, "Failed to parse extrude origin attribute");
406
407 }
408 }
409
410 // parse 3D offset (if given)
411 {
412 auto it = attrs.find("offset");
413 if(it != attrs.end())
414 {
415 std::deque<String> soff = it->second.split_by_whitespaces();
416 if(soff.size() != std::size_t(3))
417 throw Xml::GrammarError(iline, sline, "Invalid Extrude chart offset attribute");
418 if(!soff.at(0).parse(_off_x) || !soff.at(1).parse(_off_y) || !soff.at(2).parse(_off_z))
419 throw Xml::GrammarError(iline, sline, "Failed to parse extrude offset attribute");
420
421 }
422 }
423
424 // parse angles (if given)
425 {
426 auto it = attrs.find("angles");
427 if(it != attrs.end())
428 {
429 std::deque<String> sang = it->second.split_by_whitespaces();
430 if(sang.size() != std::size_t(3))
431 throw Xml::GrammarError(iline, sline, "Invalid Extrude chart angles attribute");
432 if(!sang.at(0).parse(_yaw) || !sang.at(1).parse(_pitch) || !sang.at(2).parse(_roll))
433 throw Xml::GrammarError(iline, sline, "Failed to parse extrude angles attribute");
434
435 // Note: the angles are specifies in revolutions, but we need radians, so multiply by 2*pi
436 const CoordType mult = CoordType(2) * Math::pi<CoordType>();
437 _yaw *= mult;
438 _pitch *= mult;
439 _roll *= mult;
440 }
441 }
442 }
443
444 virtual void close(int iline, const String& sline) override
445 {
446 if(!_chart)
447 throw Xml::GrammarError(iline, sline, "invalid empty <Extrude> markup");
448 }
449
450 virtual bool content(int, const String&) override
451 {
452 return false;
453 }
454
455 virtual std::shared_ptr<Xml::MarkupParser> markup(int, const String&, const String& name) override
456 {
457 typedef typename Mesh_::ShapeType ShapeType;
458 typedef typename Shape::FaceTraits<ShapeType, 2>::ShapeType SubShapeType;
460
461 // What have we here?
462 if(name == "Circle")
463 {
464 std::unique_ptr<Extrude<Mesh_, Circle<SubMeshType>>> ext(new Extrude<Mesh_, Circle<SubMeshType>>());
465 ext->set_origin(_ori_x, _ori_y);
466 ext->set_offset(_off_x, _off_y, _off_z);
467 ext->set_angles(_yaw, _pitch, _roll);
468 std::unique_ptr<Circle<SubMeshType>>& sub_chart = ext->_sub_chart;
469 _chart = std::move(ext);
470 return std::make_shared<Atlas::CircleChartParser<SubMeshType, Circle<SubMeshType>>>(sub_chart);
471 }
472 if(name == "Bezier")
473 {
474 std::unique_ptr<Extrude<Mesh_, Bezier<SubMeshType>>> ext(new Extrude<Mesh_, Bezier<SubMeshType>>());
475 ext->set_origin(_ori_x, _ori_y);
476 ext->set_offset(_off_x, _off_y, _off_z);
477 ext->set_angles(_yaw, _pitch, _roll);
478 std::unique_ptr<Bezier<SubMeshType>>& sub_chart = ext->_sub_chart;
479 _chart = std::move(ext);
480 return std::make_shared<Atlas::BezierChartParser<SubMeshType, Bezier<SubMeshType>>>(sub_chart);
481 }
482
483 return nullptr;
484 }
485 }; // class ExtrudeChartParser<...>
486 } // namespace Atlas
487 } // namespace Geometry
488} // namespace FEAT
#define ASSERT(expr)
Debug-Assertion macro definition.
Definition: assertion.hpp:229
#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
Bezier chart class template.
Definition: bezier.hpp:45
VertexSetType::CoordType CoordType
out coordinate type
Definition: chart.hpp:43
Chart CRTP base-class template.
Definition: chart.hpp:354
Circle chart class template.
Definition: circle.hpp:52
virtual bool attribs(std::map< String, bool > &attrs) const override
Specifies the mandatory and optional attributes.
Definition: extrude.hpp:380
virtual bool content(int, const String &) override
Called to process a content line.
Definition: extrude.hpp:450
virtual void create(int iline, const String &sline, const String &, const std::map< String, String > &attrs, bool) override
Creates this markup parser node.
Definition: extrude.hpp:389
virtual std::shared_ptr< Xml::MarkupParser > markup(int, const String &, const String &name) override
Called to process a child markup node.
Definition: extrude.hpp:455
virtual void close(int iline, const String &sline) override
Closes this markup parser node.
Definition: extrude.hpp:444
BaseClass::ParamPoint ParamPoint
Vector type for parametrization points, aka domain points.
Definition: extrude.hpp:44
CoordType compute_dist(const WorldPoint &point) const
Computes the distance of a point to this chart.
Definition: extrude.hpp:219
Tiny::Vector< CoordType, 3 > _offset
the offset point
Definition: extrude.hpp:57
Tiny::Matrix< CoordType, 3, 3 > _rotation
the rotation matrix
Definition: extrude.hpp:59
Tiny::Vector< CoordType, 2 > _origin
the origin point
Definition: extrude.hpp:55
CoordType compute_dist(const WorldPoint &point, WorldPoint &grad_dist) const
Computes the distance of a point to this chart.
Definition: extrude.hpp:228
CoordType compute_signed_dist(const WorldPoint &point, WorldPoint &grad_dist) const
Computes the signed distance of a point to this chart.
Definition: extrude.hpp:257
CoordType compute_signed_dist(const WorldPoint &point) const
Computes the signed distance of a point to this chart.
Definition: extrude.hpp:248
std::unique_ptr< SubChart_ > _sub_chart
our sub-chart object
Definition: extrude.hpp:51
ChartCRTP< Extrude< Mesh_, SubChart_ >, Mesh_, ExtrudeTraits< SubChart_ > > BaseClass
The CRTP base class.
Definition: extrude.hpp:38
BaseClass::WorldPoint WorldPoint
Vector type for world points, aka image points.
Definition: extrude.hpp:42
virtual String get_type() const override
Writes the type as String.
Definition: extrude.hpp:274
virtual void write(std::ostream &os, const String &sindent) const override
Writes the Chart into a stream in XML format.
Definition: extrude.hpp:279
virtual bool can_implicit() const override
Definition: extrude.hpp:106
BaseClass::CoordType CoordType
Floating point type.
Definition: extrude.hpp:40
virtual bool can_explicit() const override
Definition: extrude.hpp:111
Conformal mesh class template.
String class implementation.
Definition: string.hpp:47
Tiny Matrix class template.
CUDA_HOST_DEVICE Matrix & set_mat_mat_mult(const Matrix< T_, m_, la_, sma_, sna_ > &a, const Matrix< T_, lb_, n_, smb_, snb_ > &b)
Sets this matrix to the algebraic matrix-product of two other matrices.
CUDA_HOST_DEVICE DataType norm_sub_id_frobenius() const
Returns the Frobenius norm of the difference of this matrix and the identity matrix.
CUDA_HOST_DEVICE Matrix & set_rotation_3d(T_ yaw, T_ pitch, T_ roll)
Sets this matrix to a 3D yaw-pitch-roll rotation matrix.
CUDA_HOST_DEVICE Matrix & set_identity()
Sets this matrix to the identity matrix.
Tiny Vector class template.
CUDA_HOST_DEVICE void format(DataType alpha=DataType(0))
Formats the vector.
CUDA_HOST_DEVICE DataType norm_euclid_sqr() const
Computes the squared euclid norm of this vector.
CUDA_HOST_DEVICE Vector & set_mat_vec_mult(const Matrix< T_, n_, m_, sma_, sna_ > &a, const Vector< T_, m_, sx_ > &x)
Sets this vector to the result of a matrix-vector product.
Dummy XML markup parser class.
Xml grammar error class.
XML Markup Parser interface.
T_ sqrt(T_ x)
Returns the square-root of a value.
Definition: math.hpp:300
T_ atan2(T_ y, T_ x)
Returns the arctangent of y/x.
Definition: math.hpp:708
T_ pow(T_ x, T_ y)
Returns x raised to the power of y.
Definition: math.hpp:643
T_ sqr(T_ x)
Returns the square of a value.
Definition: math.hpp:95
FEAT namespace.
Definition: adjactor.hpp:12
std::uint64_t Index
Index data type.
static constexpr int world_dim
this is a 3D object
Definition: extrude.hpp:27
static constexpr bool is_implicit
we support implicit projection
Definition: extrude.hpp:25
static constexpr int param_dim
we have 2D parameters
Definition: extrude.hpp:29
static constexpr bool is_explicit
we support explicit map
Definition: extrude.hpp:23
Face traits tag struct template.
Definition: shape.hpp:106