File: function_signed_distance.h

package info (click to toggle)
deal.ii 9.7.1-4
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 326,024 kB
  • sloc: cpp: 440,899; ansic: 77,337; python: 3,307; perl: 1,041; sh: 1,022; xml: 252; makefile: 97; javascript: 14
file content (324 lines) | stat: -rw-r--r-- 10,468 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
// ------------------------------------------------------------------------
//
// SPDX-License-Identifier: LGPL-2.1-or-later
// Copyright (C) 2021 - 2023 by the deal.II authors
//
// This file is part of the deal.II library.
//
// Part of the source code is dual licensed under Apache-2.0 WITH
// LLVM-exception OR LGPL-2.1-or-later. Detailed license information
// governing the source code and code contributions can be found in
// LICENSE.md and CONTRIBUTING.md at the top level directory of deal.II.
//
// ------------------------------------------------------------------------

#ifndef dealii_function_signed_distance_h
#define dealii_function_signed_distance_h

#include <deal.II/base/config.h>

#include <deal.II/base/bounding_box.h>
#include <deal.II/base/function.h>

#include <array>

DEAL_II_NAMESPACE_OPEN

namespace Functions
{
  namespace SignedDistance
  {
    /**
     * Signed-distance level set function of a sphere:
     * $\psi(x) = \| x - x^c \| - R$.
     * Here, $x^c$ is the center of the sphere and $R$ is its radius. This
     * function is thus zero on the sphere, negative "inside" the ball having
     * the sphere as its boundary, and positive in the rest of
     * $\mathbb{R}^{dim}$.
     *
     * This function has gradient and Hessian equal to
     * $\partial_i \psi(x) = (x - x^c)/\| x - x^c \|$,
     * $\partial_i \partial_j \psi =
     * \delta_{ij}/\| x - x^c \| - (x_i - x_i^c)(x_j - x_j^c)/\| x - x^c \|^3$,
     * where $\delta_{ij}$ is the Kronecker delta function.
     *
     * @ingroup functions
     */
    template <int dim>
    class Sphere : public Function<dim>
    {
    public:
      /**
       * Constructor, takes the center and radius of the sphere.
       */
      Sphere(const Point<dim> &center = Point<dim>(), const double radius = 1);

      double
      value(const Point<dim>  &point,
            const unsigned int component = 0) const override;

      /**
       * @copydoc Function::gradient()
       *
       * @note The gradient is singular at the center of the sphere. If the
       * incoming @p point is too close to the center, a floating-point
       * exception may be thrown or entries in the gradient may be +inf/-inf
       * or +nan/-nan, depending on how the point is located relative to the
       * singularity.
       */
      Tensor<1, dim>
      gradient(const Point<dim>  &point,
               const unsigned int component = 0) const override;

      /**
       * @copydoc Function::hessian()
       *
       * @note The Hessian is singular at the center of the sphere. If the
       * incoming @p point is too close to the center, a floating-point
       * exception may be thrown or entries in the Hessian may be +inf/-inf
       * or +nan/-nan, depending on how the point is located relative to the
       * singularity.
       */
      SymmetricTensor<2, dim>
      hessian(const Point<dim>  &point,
              const unsigned int component = 0) const override;

    private:
      const Point<dim> center;
      const double     radius;
    };


    /**
     * Signed level set function of a plane in $\mathbb{R}^{dim}$:
     * $\psi(x) = n \cdot (x - x_p)$.
     * Here, $n$ is the plane normal and $x_p$ is a point in the plane.
     * Thus, with respect to the direction of the normal, this function is
     * positive above the plane, zero in the plane, and negative below the
     * plane. If the normal is normalized, $\psi$ will be the signed distance to
     * the closest point in the plane.
     *
     * @ingroup functions
     */
    template <int dim>
    class Plane : public Function<dim>
    {
    public:
      /**
       * Constructor, takes a point in the plane and the plane normal.
       */
      Plane(const Point<dim> &point, const Tensor<1, dim> &normal);

      double
      value(const Point<dim>  &point,
            const unsigned int component = 0) const override;

      Tensor<1, dim>
      gradient(const Point<dim> &,
               const unsigned int component = 0) const override;

      SymmetricTensor<2, dim>
      hessian(const Point<dim> &,
              const unsigned int component = 0) const override;

    private:
      const Point<dim>     point_in_plane;
      const Tensor<1, dim> normal;
    };


    /**
     * Signed-distance level set function to an ellipsoid defined by:
     *
     * @f[
     * \sum_{i=1}^{dim} \frac{(x_i - c_i)^2}{R_i^2} = 1
     * @f]
     *
     * Here, $c_i$ are the coordinates of the center of the ellipsoid and $R_i$
     * are the elliptic radii. This function is zero on the ellipsoid, negative
     * inside the ellipsoid and positive outside the ellipsoid.
     *
     * @ingroup functions
     */
    template <int dim>
    class Ellipsoid : public Function<dim>
    {
    public:
      /**
       * Constructor, takes the center and radii of the ellipsoid.
       *
       * @param center Center of the ellipsoid.
       * @param radii Array of radii of the ellipsoid.
       * @param tolerance Tolerance of the distance computation.
       * @param max_iter Max. number of iteration of the distance computation algorithm.
       */
      Ellipsoid(const Point<dim>              &center,
                const std::array<double, dim> &radii,
                const double                   tolerance = 1e-14,
                const unsigned int             max_iter  = 10);

      double
      value(const Point<dim>  &point,
            const unsigned int component = 0) const override;

      /**
       * Calculates the gradient of the signed distance function via the normal
       * of the closest point on the ellipsoid.
       */
      Tensor<1, dim>
      gradient(const Point<dim> &,
               const unsigned int component = 0) const override;

    private:
      /**
       * Evaluates the ellipsoid function:
       *
       * @f[
       * f(\vec{x}) = \sum_{i=1}^{dim} \frac{(x_i - c_i)^2}{R_i^2} - 1
       * @f]
       */
      double
      evaluate_ellipsoid(const Point<dim> &point) const;

      /**
       * Computes the closest point on the given ellipse for an arbitrary point.
       */
      Point<dim>
      compute_closest_point_ellipse(const Point<dim> &point) const;

      /**
       * Computes the analytical normal vector of a origin centred ellipse at a
       * given @p point according to:
       *
       *  /          \    / b x     a y  \
       * | n_x , n_y | = | ----- , ----- |
       * \          /    \   a       b  /
       *
       *
       * @param point [x, y]
       * @return [n_x , n_y]
       */
      Tensor<1, dim, double>
      compute_analyical_normal_vector_on_ellipse(const Point<dim> &point) const;

      /**
       * Compute the signed distance to a 2d ellipsoid i.e. ellipse.
       */
      double
      compute_signed_distance_ellipse(const Point<dim> &point) const;

      const Point<dim>              center;
      const std::array<double, dim> radii;
      const double                  tolerance;
      const unsigned int            max_iter;
    };


    /**
     * Signed-distance level set function of a rectangle.
     *
     * This function is zero on the rectangle, negative "inside" and positive
     * in the rest of $\mathbb{R}^{dim}$.
     *
     * Contour surfaces of the signed distance function of a 3D rectangle are
     * illustrated below:
     *
     * @image html signed_distance_hyper_rectangle.png
     *
     * @ingroup functions
     */
    template <int dim>
    class Rectangle : public Function<dim>
    {
    public:
      /**
       * Constructor, takes the bottom left point and the top right
       * point of the rectangle.
       *
       * @param bottom_left Bottom left point of the rectangle.
       * @param top_right Top right point of the rectangle.
       */
      Rectangle(const Point<dim> &bottom_left, const Point<dim> &top_right);
      /**
       * Constructor, takes a bounding box.
       *
       * @param bounding_box Bounding box.
       */
      Rectangle(const BoundingBox<dim> bounding_box);

      /**
       * Calculates the signed distance from a given point @p p to the rectangle.
       * The signed distance is negative for points inside the rectangle, zero
       * for points on the rectangle and positive for points outside the
       * rectangle.
       */
      double
      value(const Point<dim>  &p,
            const unsigned int component = 0) const override;

    private:
      const BoundingBox<dim> bounding_box;
    };


    /**
     * Signed-distance level set function of Zalesak's disk proposed in
     * @cite zalesak1979fully.
     *
     * It is calculated by the set difference $\psi(x) = \max(\psi_{S}(x),
     * -\psi_{N}(x))$ of the level set functions of a sphere $\psi_{S}$ and a
     * rectangle $\psi_{N}$. This function is zero on the surface of the disk,
     * negative "inside" and positive in the rest of $\mathbb{R}^{dim}$.
     *
     * Contour surfaces of the signed distance function of a 3D Zalesak's disk
     * are illustrated below:
     *
     * @image html https://www.dealii.org/images/grids/signed_distance_zalesak_disk.png
     *
     * @ingroup functions
     */
    template <int dim>
    class ZalesakDisk : public Function<dim>
    {
    public:
      /**
       * Constructor, takes the radius and center of the disk together
       * with the width and the height of the notch.
       *
       * @param radius Radius of the disk.
       * @param center Center of the disk.
       * @param notch_width Width of the notch of the disk.
       * @param notch_height Height of the notch of the disk.
       */
      ZalesakDisk(const Point<dim> &center,
                  const double      radius,
                  const double      notch_width,
                  const double      notch_height);

      /**
       * Calculates the signed distance from a given point @p p to the disk.
       * The signed distance is negative for points inside the disk, zero
       * for points on the disk and positive for points outside the
       * disk.
       */
      double
      value(const Point<dim>  &p,
            const unsigned int component = 0) const override;

    private:
      /**
       * Disk described by a sphere.
       */
      const Functions::SignedDistance::Sphere<dim> sphere;

      /**
       * Notch described by a rectangle.
       */
      const Functions::SignedDistance::Rectangle<dim> notch;
    };
  } // namespace SignedDistance
} // namespace Functions

DEAL_II_NAMESPACE_CLOSE

#endif