OpenLB 1.7
Loading...
Searching...
No Matches
sdf.h
Go to the documentation of this file.
1/* This file is part of the OpenLB library
2 *
3 * Copyright (C) 2019 Adrian Kummerlaender
4 * E-mail contact: info@openlb.net
5 * The most recent release of OpenLB can be downloaded at
6 * <http://www.openlb.net/>
7 *
8 * This program is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU General Public License
10 * as published by the Free Software Foundation; either version 2
11 * of the License, or (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public
19 * License along with this program; if not, write to the Free
20 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21 * Boston, MA 02110-1301, USA.
22*/
23
24#ifndef SDF_H
25#define SDF_H
26
27#include "core/vector.h"
28
29#include <algorithm>
30#include <functional>
31
32#ifndef M_PI
33#define M_PI 3.14159265358979323846
34#endif
35#ifndef M_PI2
36#define M_PI2 1.57079632679489661923
37#endif
38
39namespace olb {
40
41namespace sdf {
42
43template <typename T>
44T mix(T a, T b, T h) any_platform
45{
46 return b * (1.0 - h) + a * h;
47}
48
49template <typename T0, typename T1, typename T2>
50decltype(T0 {} * T1 {} * T2 {}) clamp(T0 x, T1 a, T2 b) any_platform
51{
52 if (x < a) {
53 return a;
54 }
55 else if (x > b) {
56 return b;
57 }
58 else {
59 return x;
60 }
61}
62
64template <typename T>
65Vector<bool, 3> isSymmetric(std::function<T(const Vector<T, 3>&)> sdf,
67{
69
70 isSymmetric[0] = sdf(Vector<T, 3> {1., 1., 1.} + center) ==
71 sdf(Vector<T, 3> {-1., 1., 1.} + center) &&
72 sdf(Vector<T, 3> {1., -1., 1.} + center) ==
73 sdf(Vector<T, 3> {-1., -1., 1.} + center) &&
74 sdf(Vector<T, 3> {1., 1., -1.} + center) ==
75 sdf(Vector<T, 3> {-1., 1., -1.} + center) &&
76 sdf(Vector<T, 3> {1., -1., -1.} + center) ==
77 sdf(Vector<T, 3> {-1., -1., -1.} + center);
78 isSymmetric[1] = sdf(Vector<T, 3> {1., 1., 1.} + center) ==
79 sdf(Vector<T, 3> {1., -1., 1.} + center) &&
80 sdf(Vector<T, 3> {-1., 1., 1.} + center) ==
81 sdf(Vector<T, 3> {-1., -1., 1.} + center) &&
82 sdf(Vector<T, 3> {1., 1., -1.} + center) ==
83 sdf(Vector<T, 3> {1., -1., -1.} + center) &&
84 sdf(Vector<T, 3> {-1., 1., -1.} + center) ==
85 sdf(Vector<T, 3> {-1., -1., -1.} + center);
86 isSymmetric[2] = sdf(Vector<T, 3> {1., 1., 1.} + center) ==
87 sdf(Vector<T, 3> {1., 1., -1.} + center) &&
88 sdf(Vector<T, 3> {-1., 1., 1.} + center) ==
89 sdf(Vector<T, 3> {-1., 1., -1.} + center) &&
90 sdf(Vector<T, 3> {1., -1., 1.} + center) ==
91 sdf(Vector<T, 3> {1., -1., -1.} + center) &&
92 sdf(Vector<T, 3> {-1., -1., 1.} + center) ==
93 sdf(Vector<T, 3> {-1., -1., -1.} + center);
94
95 return isSymmetric;
96}
97
103template <typename T, unsigned D>
105{
106 return norm(p) - r;
107}
108
114template <typename T>
116{
117 Vector<T, 2> q = abs(p) - b;
118 return norm(maxv(q, Vector<T, 2>(0.0))) +
119 util::min(util::max({q[0], q[1]}), T());
120}
121
127template <typename T>
129{
130 Vector<T, 3> q = abs(p) - b;
131 return norm(maxv(q, Vector<T, 3>(0.0))) +
132 util::min(util::max({q[0], q[1], q[2]}), T());
133}
134
142template <typename T>
145{
146 Vector<T, 2> e0 = b - a;
147 Vector<T, 2> v0 = p - a;
148 Vector<T, 2> e1 = c - b;
149 Vector<T, 2> v1 = p - b;
150 Vector<T, 2> e2 = a - c;
151 Vector<T, 2> v2 = p - c;
152 Vector<T, 2> pq0 = v0 - e0 * clamp((v0 * e0) / (e0 * e0), 0., 1.);
153 Vector<T, 2> pq1 = v1 - e1 * clamp((v1 * e1) / (e1 * e1), 0., 1.);
154 Vector<T, 2> pq2 = v2 - e2 * clamp((v2 * e2) / (e2 * e2), 0., 1.);
155 T s = util::sign(e0[0] * e2[1] - e0[1] * e2[0]);
156
157 T dx = util::min(util::min((pq0 * pq0), (pq1 * pq1)), (pq2 * pq2));
158 T dy = util::min(util::min(s * (v0[0] * e0[1] - v0[1] * e0[0]),
159 s * (v1[0] * e1[1] - v1[1] * e1[0])),
160 s * (v2[0] * e2[1] - v2[1] * e2[0]));
161 return -util::sqrt(dx) * util::sign(dy);
162}
163
171template <typename T>
173 T r) any_platform
174{
175 const Vector<T, 3> pa = p - a;
176 const T paba = pa * ba;
177 const T x = norm(pa * baba - ba * paba) - r * baba;
178 const T y = util::abs(paba - baba * T {0.5}) - baba * T {0.5};
179 const T x2 = x * x;
180 const T y2 = y * y * baba;
181 const T d = (util::max(x, y) < T {0})
182 ? -util::min(x2, y2)
183 : (((x > T {0}) ? x2 : T {0}) + ((y > T {0}) ? y2 : T {0}));
184 return util::sign(d) * util::sqrt(util::abs(d)) / baba;
185}
186
194template <typename T>
196{
197 Vector<T, 3> ba = b - a;
198 T baba = ba * ba;
199 return sdf::cylinder(p, a, ba, baba, r);
200}
201
209template <typename T>
211 T rb) any_platform
212{
213 T rba = rb - ra;
214 T papa = (p - a) * (p - a);
215 T paba = (p - a) * (ba) / baba;
216 // x distance to the axis of the cone
217 // note: abs() prevents from negative values, e.g. caused by rounding errors
218 T x = util::sqrt(util::abs(papa - paba * paba * baba));
219 // cax and cay for the distances to the caps
220 T cax = util::max(0.0, x - ((paba < 0.5) ? ra : rb));
221 T cay = util::abs(paba - 0.5) - 0.5;
222 // cbx and cby for the distance to the side wall
223 T k = rba * rba + baba;
224 T f = clamp((rba * (x - ra) + paba * baba) / k, 0.0, 1.0);
225 T cbx = x - ra - f * rba;
226 T cby = paba - f;
227 T s = (cbx < 0.0 && cay < 0.0) ? -1.0 : 1.0;
228 return s * util::sqrt(util::min(cax * cax + cay * cay * baba,
229 cbx * cbx + cby * cby * baba));
230}
231
240template <typename T>
242{
243 Vector<T, 3> ba = b - a;
244 T baba = ba * ba;
245 return sdf::cone(p, a, ba, baba, ra, rb);
246}
247
252template <typename T>
254{
255 const Vector<T, 3> a(p[0] / r[0], p[1] / r[1], p[2] / r[2]);
256 T k0 = norm(a);
257 const Vector<T, 3> r2(r[0] * r[0], r[1] * r[1], r[2] * r[2]);
258 const Vector<T, 3> b(p[0] / r2[0], p[1] / r2[1], p[2] / r2[2]);
259 T k1 = norm(b);
260 return (k0 < 1.0) ? (k0 - 1.0) * util::min(util::min(r[0], r[1]), r[2])
261 : k0 * (k0 - 1.0) / k1;
262}
263
270template <typename T>
272{
273 Vector<T, 2> b {p[0], p[2]};
274 Vector<T, 2> q {norm(b) - t[0], p[1]};
275 return norm(q) - t[1];
276}
277
285template <typename T>
287{
288 Vector<T, 2> q {norm(Vector<T, 2> {p[0], p[2]}), p[1]};
289 T l = norm(q) - r;
290 T m = norm(q - c * clamp(q * c, 0.0, r));
291 return util::max(l, m * util::sign(c[1] * q[0] - c[0] * q[1]));
292}
293
298template <typename T, unsigned D>
300{
301 return p - origin;
302}
303
304template <typename T>
306{
307 return {p[1], p[0], p[2]};
308}
309
316template <typename T>
318{
319 return util::max(-a, b);
320}
321
328template <typename T>
330{
331 return util::min(a, b);
332}
333
340template <typename T>
342{
343 return util::max(a, b);
344}
345
346template <typename T>
348{
349 T h = clamp(0.5 + 0.5 * (b - a) / k, 0.0, 1.0);
350 return mix(a, b, h) - k * h * (1.0 - h);
351}
352
353template <typename T>
355{
356 T h = clamp(0.5 - 0.5 * (b + a) / k, 0.0, 1.0);
357 return mix(b, -a, h) + k * h * (1.0 - h);
358}
359
360template <typename T>
362{
363 T h = clamp(0.5 - 0.5 * (b - a) / k, 0.0, 1.0);
364 return mix(b, a, h) + k * h * (1.0 - h);
365}
366
371template <typename T>
373{
374 return a - r;
375}
376
385template <typename T, bool symmetryCheck = true>
386T elongation(std::function<T(const Vector<T, 3>&)> sdf, const Vector<T, 3>& p,
387 const Vector<T, 3>& h,
388 const Vector<T, 3>& center = (T(0))) any_platform
389{
390 Vector<T, 3> q = abs(p - center) - h;
391 Vector<T, 3> p_elong = p - center;
392 // elongation requires symmetry e.g. for elongation in x --> plane of symmetry = YZ-plane
393 Vector<bool, 3> sdfIsSymmetric;
394 if constexpr (symmetryCheck) {
395 sdfIsSymmetric = isSymmetric(sdf, center);
396 }
397
398 if (h[0] != 0) {
399 p_elong[0] = util::max(q[0], 0.);
400 if constexpr (symmetryCheck) {
401 if (!sdfIsSymmetric[0]) {
402 std::cout << "Warning: symmetry in x is not met" << std::endl;
403 }
404 }
405 }
406
407 if (h[1] != 0) {
408 p_elong[1] = util::max(q[1], 0.);
409 if constexpr (symmetryCheck) {
410 if (!sdfIsSymmetric[1]) {
411 std::cout << "Warning: symmetry in y is not met" << std::endl;
412 }
413 }
414 }
415
416 if (h[2] != 0) {
417 p_elong[2] = util::max(q[2], 0.);
418 if constexpr (symmetryCheck) {
419 if (!sdfIsSymmetric[2]) {
420 std::cout << "Warning: symmetry in z is not met" << std::endl;
421 }
422 }
423 }
424
425 // Second term needed in case of 3D-Elongation if all parts of Vector q are negative
426 return sdf(p_elong + center) + util::min(util::max({q[0], q[1], q[2]}), 0.);
427}
428
436template <typename T, unsigned D>
437T scale(std::function<T(const Vector<T, D>&)> sdf, const Vector<T, D>& p, T s,
438 const Vector<T, D>& center = (T(0))) any_platform
439{
440 return sdf((p - center) / s) * s;
441}
442
444// TODO: Rename function
445template <typename T>
447{
448 const T d = signedDist + .5 * eps;
449 return util::pow(util::cos(M_PI2 * d / eps), 2);
450}
451
452template <typename T>
453bool evalSolidVolumeFraction(T output[], T signedDist, T eps) any_platform
454{
455 T const halfEps = .5 * eps;
456 if (signedDist <= -halfEps) {
457 output[0] = 1.;
458 return true;
459 }
460 else if (signedDist < halfEps) {
461 output[0] = signedDistanceToPorosity(signedDist, eps);
462 return true;
463 }
464 output[0] = 0.;
465 return false;
466}
467
468} // namespace sdf
469
470} // namespace olb
471
472#endif
Plain old scalar vector.
Definition vector.h:47
#define M_PI2
T rounding(T a, T r) any_platform
Computes a layer of a constant thickness around the surface.
Definition sdf.h:372
T torus(Vector< T, 3 > p, Vector< T, 2 > t) any_platform
Exact signed distance to the surface of a torus placed in the XZ-plane of the coordinate system.
Definition sdf.h:271
Vector< T, 3 > flip(Vector< T, 3 > p) any_platform
Definition sdf.h:305
T signedDistanceToPorosity(T signedDist, T eps) any_platform
Converts signed distance to values for the smooth epsilon boundary.
Definition sdf.h:446
T intersection(T a, T b) any_platform
Volume which is shared by a and b creates a new object.
Definition sdf.h:341
T triangle(Vector< T, 2 > p, Vector< T, 2 > a, Vector< T, 2 > b, Vector< T, 2 > c) any_platform
Exact signed distance to the surface of two-dimensional triangle.
Definition sdf.h:143
T sphere(Vector< T, D > p, T r) any_platform
Exact signed distance to the surface of circle (in 2D) or sphere (in 3D).
Definition sdf.h:104
T elongation(std::function< T(const Vector< T, 3 > &)> sdf, const Vector< T, 3 > &p, const Vector< T, 3 > &h, const Vector< T, 3 > &center=(T(0))) any_platform
Elongation splits the object in 2 (4 or 8) parts, moves them apart and connects them again The object...
Definition sdf.h:386
T scale(std::function< T(const Vector< T, D > &)> sdf, const Vector< T, D > &p, T s, const Vector< T, D > &center=(T(0))) any_platform
Function to scale a geometry The object has to be placed in the origin of the coodinate system.
Definition sdf.h:437
T unify(T a, T b) any_platform
Volume of a and volume of b are combined as a new object.
Definition sdf.h:329
Vector< T, D > translate(Vector< T, D > p, Vector< T, D > origin) any_platform
Translation: The output of this function is used for the calculation of the signed distance to transl...
Definition sdf.h:299
T mix(T a, T b, T h) any_platform
Definition sdf.h:44
bool evalSolidVolumeFraction(T output[], T signedDist, T eps) any_platform
Definition sdf.h:453
T smooth_subtraction(T a, T b, T k) any_platform
Definition sdf.h:354
T cone(Vector< T, 3 > p, Vector< T, 3 > a, Vector< T, 3 > ba, T baba, T ra, T rb) any_platform
Exact signed distance to the surface of three-dimensional (capped) cone.
Definition sdf.h:210
T smooth_intersection(T a, T b, T k) any_platform
Definition sdf.h:361
T box(Vector< T, 2 > p, Vector< T, 2 > b) any_platform
Exact signed distance to the surface of two-dimensional cuboid.
Definition sdf.h:115
T ellipsoid(Vector< T, 3 > p, Vector< T, 3 > r) any_platform
Calculate the NOT EXACT (!) signed distance to the surface of three-dimensional ellipsoid.
Definition sdf.h:253
T cylinder(Vector< T, 3 > p, Vector< T, 3 > a, Vector< T, 3 > ba, T baba, T r) any_platform
Exact signed distance to the surface of three-dimensional cylinder.
Definition sdf.h:172
Vector< bool, 3 > isSymmetric(std::function< T(const Vector< T, 3 > &)> sdf, Vector< T, 3 > center) any_platform
A rough test for symmetry.
Definition sdf.h:65
T solidAngle(Vector< T, 3 > p, Vector< T, 2 > c, T r) any_platform
Exact signed distance to the surface of a solid angle which represents a combination of a cone (axis ...
Definition sdf.h:286
T subtraction(T a, T b) any_platform
Volume of a is subtracted from b.
Definition sdf.h:317
decltype(T0 {} *T1 {} *T2 {}) clamp(T0 x, T1 a, T2 b) any_platform
Definition sdf.h:50
T smooth_union(T a, T b, T k) any_platform
Definition sdf.h:347
cpu::simd::Pack< T > sqrt(cpu::simd::Pack< T > value)
Definition pack.h:100
ADf< T, DIM > abs(const ADf< T, DIM > &a)
Definition aDiff.h:1019
cpu::simd::Pack< T > min(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:124
cpu::simd::Pack< T > max(cpu::simd::Pack< T > rhs, cpu::simd::Pack< T > lhs)
Definition pack.h:130
cpu::simd::Pack< T > pow(cpu::simd::Pack< T > base, cpu::simd::Pack< T > exp)
Definition pack.h:112
int sign(T val)
Definition util.h:54
ADf< T, DIM > cos(const ADf< T, DIM > &a)
Definition aDiff.h:578
Top level namespace for all of OpenLB.
std::enable_if_t< std::is_arithmetic< T >::type::value, T > abs(T x)
Definition util.h:396
constexpr Vector< T, D > maxv(const ScalarVector< T, D, IMPL > &v, const ScalarVector< T, D, IMPL_ > &w)
Definition vector.h:400
constexpr T norm(const ScalarVector< T, D, IMPL > &a)
Euclidean vector norm.
#define any_platform
Define preprocessor macros for device-side functions, constant storage.
Definition platform.h:78
efficient implementation of a vector class