ViewDesignEngine  3.1.0
高性能 CAD 计算几何引擎
sdf_gradient.h
浏览该文件的文档.
1 #pragma once
26 #include "vde/sdf/sdf_primitives.h"
27 #include "vde/sdf/sdf_operations.h"
28 #include "vde/core/point.h"
29 #include <cmath>
30 #include <functional>
31 
32 namespace vde::sdf {
33 
34 using core::Point3D;
35 using core::Vector3D;
36 
37 // ═══════════════════════════════════════════════
38 // Finite-Difference Gradient
39 // ═══════════════════════════════════════════════
40 
65 [[nodiscard]] inline Vector3D gradient(
66  const std::function<double(const Point3D&)>& f,
67  const Point3D& p, double h = 1e-6)
68 {
69  Vector3D g;
70  double inv_2h = 0.5 / h;
71  g.x() = (f(Point3D(p.x() + h, p.y(), p.z())) - f(Point3D(p.x() - h, p.y(), p.z()))) * inv_2h;
72  g.y() = (f(Point3D(p.x(), p.y() + h, p.z())) - f(Point3D(p.x(), p.y() - h, p.z()))) * inv_2h;
73  g.z() = (f(Point3D(p.x(), p.y(), p.z() + h)) - f(Point3D(p.x(), p.y(), p.z() - h))) * inv_2h;
74  return g;
75 }
76 
77 // ═══════════════════════════════════════════════
78 // Gradient Result Struct
79 // ═══════════════════════════════════════════════
80 
87 struct GradResult {
88  double value;
90 };
91 
102 [[nodiscard]] inline GradResult evaluate_with_gradient(
103  const std::function<double(const Point3D&)>& f,
104  const Point3D& p, double h = 1e-6)
105 {
106  return GradResult{f(p), gradient(f, p, h)};
107 }
108 
109 // ═══════════════════════════════════════════════
110 // Parameter Gradients (Finite Difference)
111 // ═══════════════════════════════════════════════
112 
127 [[nodiscard]] inline double sphere_radius_gradient(const Point3D& p, double radius, double h = 1e-6)
128 {
129  return (sphere(p, radius + h) - sphere(p, radius - h)) / (2.0 * h);
130 }
131 
143 [[nodiscard]] inline double box_extent_gradient(const Point3D& p, const Point3D& extents,
144  int axis, double h = 1e-6)
145 {
146  Point3D ext_plus = extents;
147  Point3D ext_minus = extents;
148  ext_plus[axis] += h;
149  ext_minus[axis] -= h;
150  return (box(p, ext_plus) - box(p, ext_minus)) / (2.0 * h);
151 }
152 
162 [[nodiscard]] inline double torus_major_gradient(const Point3D& p, double major_r, double minor_r,
163  double h = 1e-6)
164 {
165  return (torus(p, major_r + h, minor_r) - torus(p, major_r - h, minor_r)) / (2.0 * h);
166 }
167 
173 [[nodiscard]] inline double torus_minor_gradient(const Point3D& p, double major_r, double minor_r,
174  double h = 1e-6)
175 {
176  return (torus(p, major_r, minor_r + h) - torus(p, major_r, minor_r - h)) / (2.0 * h);
177 }
178 
188 [[nodiscard]] inline double cylinder_height_gradient(const Point3D& p, double radius, double height,
189  double h = 1e-6)
190 {
191  return (cylinder(p, radius, height + h) - cylinder(p, radius, height - h)) / (2.0 * h);
192 }
193 
199 [[nodiscard]] inline double cylinder_radius_gradient(const Point3D& p, double radius, double height,
200  double h = 1e-6)
201 {
202  return (cylinder(p, radius + h, height) - cylinder(p, radius - h, height)) / (2.0 * h);
203 }
204 
205 // ═══════════════════════════════════════════════
206 // Analytical Gradients (Exact)
207 // ═══════════════════════════════════════════════
208 
223 [[nodiscard]] inline Vector3D sphere_gradient_analytic(const Point3D& p, double /*radius*/)
224 {
225  double n = p.norm();
226  if (n < 1e-30) return Vector3D::Zero();
227  return p / n;
228 }
229 
243 [[nodiscard]] inline Vector3D box_gradient_analytic(const Point3D& p, const Point3D& half_extents)
244 {
245  Vector3D g = Vector3D::Zero();
246  if (std::abs(p.x()) > half_extents.x()) g.x() = (p.x() > 0.0 ? 1.0 : -1.0);
247  if (std::abs(p.y()) > half_extents.y()) g.y() = (p.y() > 0.0 ? 1.0 : -1.0);
248  if (std::abs(p.z()) > half_extents.z()) g.z() = (p.z() > 0.0 ? 1.0 : -1.0);
249 
250  // For interior: gradient points toward nearest face
251  if (g.norm() < 1e-30 && half_extents.norm() > 1e-30) {
252  // Find the dimension where the point is closest to a face
253  Point3D q = Point3D(
254  half_extents.x() - std::abs(p.x()),
255  half_extents.y() - std::abs(p.y()),
256  half_extents.z() - std::abs(p.z())
257  );
258  // Smallest q component = closest face
259  if (q.x() <= q.y() && q.x() <= q.z()) g.x() = (p.x() >= 0.0 ? 1.0 : -1.0);
260  else if (q.y() <= q.x() && q.y() <= q.z()) g.y() = (p.y() >= 0.0 ? 1.0 : -1.0);
261  else g.z() = (p.z() >= 0.0 ? 1.0 : -1.0);
262  }
263  return g;
264 }
265 
280 [[nodiscard]] inline Vector3D torus_gradient_analytic(const Point3D& p, double major_r, double minor_r)
281 {
282  double rho = std::sqrt(p.x() * p.x() + p.z() * p.z());
283  if (rho < 1e-30) {
284  // On the Y axis: x and z gradients are 0 by symmetry;
285  // y gradient = py / sqrt(major² + py²)
286  double inner = std::sqrt(major_r * major_r + p.y() * p.y());
287  if (inner < 1e-30) return Vector3D::Zero();
288  return Vector3D(0.0, p.y() / inner, 0.0);
289  }
290  double inner = std::sqrt((rho - major_r) * (rho - major_r) + p.y() * p.y());
291  if (inner < 1e-30) return Vector3D::Zero();
292  double d_rho = (rho - major_r) / inner;
293  return Vector3D(
294  d_rho * p.x() / rho,
295  p.y() / inner,
296  d_rho * p.z() / rho
297  );
298 }
299 
312 [[nodiscard]] inline Vector3D cylinder_gradient_analytic(const Point3D& p, double /*radius*/)
313 {
314  double rho = std::sqrt(p.x() * p.x() + p.z() * p.z());
315  if (rho < 1e-30) return Vector3D::UnitY(); // degenerate case: along the axis
316  return Vector3D(p.x() / rho, 0.0, p.z() / rho);
317 }
318 
331 [[nodiscard]] inline Vector3D plane_gradient_analytic(const Vector3D& normal)
332 {
333  return normal;
334 }
335 
354 [[nodiscard]] inline Vector3D capsule_gradient_analytic(const Point3D& p,
355  const Point3D& a, const Point3D& b,
356  double radius)
357 {
358  Point3D pa = p - a;
359  Point3D ba = b - a;
360  double ba_sq = ba.squaredNorm();
361  if (ba_sq < 1e-30) {
362  // Degenerate to sphere
363  double n = pa.norm();
364  if (n < 1e-30) return Vector3D::Zero();
365  return pa / n;
366  }
367  double h = std::clamp(pa.dot(ba) / ba_sq, 0.0, 1.0);
368  Point3D closest = a + ba * h;
369  Point3D delta = p - closest;
370  double d = delta.norm();
371  if (d < 1e-30) return Vector3D::Zero();
372  return delta / d;
373 }
374 
375 // ═══════════════════════════════════════════════
376 // Chain Rule for CSG Operations
377 // ═══════════════════════════════════════════════
378 
394 [[nodiscard]] inline Vector3D chain_union(const Vector3D& grad_a, const Vector3D& grad_b,
395  double d1, double d2)
396 {
397  return (d1 < d2) ? grad_a : grad_b;
398 }
399 
407 [[nodiscard]] inline Vector3D chain_intersection(const Vector3D& grad_a, const Vector3D& grad_b,
408  double d1, double d2)
409 {
410  return (d1 > d2) ? grad_a : grad_b;
411 }
412 
424 [[nodiscard]] inline Vector3D chain_difference(const Vector3D& grad_a, const Vector3D& grad_b,
425  double d1, double d2)
426 {
427  return (d1 > -d2) ? grad_a : Vector3D(-grad_b.x(), -grad_b.y(), -grad_b.z());
428 }
429 
452 [[nodiscard]] inline Vector3D chain_smooth_union(const Vector3D& grad_a, const Vector3D& grad_b,
453  double d1, double d2, double k)
454 {
455  if (k <= 0.0) return chain_union(grad_a, grad_b, d1, d2);
456  double h = std::clamp(0.5 + 0.5 * (d1 - d2) / k, 0.0, 1.0);
457  if (h <= 0.0) return grad_a;
458  if (h >= 1.0) return grad_b;
459 
460  // Full derivatives w.r.t. d1, d2:
461  // ∂f/∂d1 = 2 - 3h, ∂f/∂d2 = 3h - 1
462  double w1 = 2.0 - 3.0 * h;
463  double w2 = 3.0 * h - 1.0;
464  return grad_a * w1 + grad_b * w2;
465 }
466 
467 // ═══════════════════════════════════════════════
468 // Chain Rule for Domain Transforms
469 // ═══════════════════════════════════════════════
470 
481 [[nodiscard]] inline GradResult chain_translate(const GradResult& child_result, const Point3D& /*offset*/)
482 {
483  return child_result;
484 }
485 
498 [[nodiscard]] inline GradResult chain_rotate(const GradResult& child_result, double angle_rad)
499 {
500  GradResult result = child_result;
501  double c = std::cos(angle_rad);
502  double s = std::sin(angle_rad);
503  // R(θ) = [[c, 0, -s], [0, 1, 0], [s, 0, c]]
504  result.grad = Vector3D(
505  c * child_result.grad.x() - s * child_result.grad.z(),
506  child_result.grad.y(),
507  s * child_result.grad.x() + c * child_result.grad.z()
508  );
509  return result;
510 }
511 
525 [[nodiscard]] inline GradResult chain_scale(const GradResult& child_result, const Point3D& factors)
526 {
527  GradResult result = child_result;
528  result.grad = Vector3D(
529  child_result.grad.x() / factors.x(),
530  child_result.grad.y() / factors.y(),
531  child_result.grad.z() / factors.z()
532  );
533  return result;
534 }
535 
558 [[nodiscard]] inline GradResult chain_twist(const GradResult& child_result,
559  double amount, const Point3D& p)
560 {
561  double angle = amount * p.y();
562  double c = std::cos(angle);
563  double s = std::sin(angle);
564 
565  // Forward-twisted position
566  double tp_x = p.x() * c - p.z() * s;
567  double tp_z = p.x() * s + p.z() * c;
568 
569  GradResult result = child_result;
570 
571  // Spatial part: inverse rotation R(-angle) applied to child gradient
572  double gx = c * child_result.grad.x() + s * child_result.grad.z();
573  double gz = -s * child_result.grad.x() + c * child_result.grad.z();
574 
575  // Y-component: extra term from angle's dependence on p.y
576  // ∂/∂y correction: amount * (tp_x * gz_child - tp_z * gx_child)
577  double gy = child_result.grad.y() + amount * (tp_x * child_result.grad.z()
578  - tp_z * child_result.grad.x());
579 
580  result.grad = Vector3D(gx, gy, gz);
581  return result;
582 }
583 
597 [[nodiscard]] inline GradResult chain_repeat(const GradResult& child_result,
598  const Point3D& /*cell*/, const Point3D& /*p*/)
599 {
600  return child_result;
601 }
602 
603 // ═══════════════════════════════════════════════
604 // Parameter Gradient Vector (All Shape Params)
605 // ═══════════════════════════════════════════════
606 
618 struct ParamGrad {
619  double d_radius = 0.0;
620  double d_height = 0.0;
621  Point3D d_extents = Point3D::Zero();
622  double d_major = 0.0;
623  double d_minor = 0.0;
624  double d_angle = 0.0;
625  Vector3D d_normal = Vector3D::Zero();
626  double d_offset = 0.0;
627  Point3D d_translate = Point3D::Zero();
628  double d_rotate = 0.0;
629  Point3D d_scale = Point3D::Zero();
630 };
631 
642 [[nodiscard]] inline ParamGrad sphere_param_grad(const Point3D& p, double radius, double h = 1e-6)
643 {
644  ParamGrad pg;
645  pg.d_radius = sphere_radius_gradient(p, radius, h);
646  return pg;
647 }
648 
661 [[nodiscard]] inline ParamGrad box_param_grad(const Point3D& p, const Point3D& half_extents,
662  double h = 1e-6)
663 {
664  ParamGrad pg;
665  pg.d_extents.x() = box_extent_gradient(p, half_extents, 0, h);
666  pg.d_extents.y() = box_extent_gradient(p, half_extents, 1, h);
667  pg.d_extents.z() = box_extent_gradient(p, half_extents, 2, h);
668  return pg;
669 }
670 
682 [[nodiscard]] inline ParamGrad cylinder_param_grad(const Point3D& p, double radius, double height,
683  double h = 1e-6)
684 {
685  ParamGrad pg;
686  pg.d_radius = cylinder_radius_gradient(p, radius, height, h);
687  pg.d_height = cylinder_height_gradient(p, radius, height, h);
688  return pg;
689 }
690 
691 } // namespace vde::sdf
foundation::Vector3D Vector3D
双精度三维向量(重新导出)
Definition: point.h:49
foundation::Point3D Point3D
双精度三维点(重新导出)
Definition: point.h:31
Vector3D sphere_gradient_analytic(const Point3D &p, double)
球体 SDF 的解析梯度
Definition: sdf_gradient.h:223
Vector3D chain_smooth_union(const Vector3D &grad_a, const Vector3D &grad_b, double d1, double d2, double k)
平滑并集操作的梯度传递(含完整链式法则)
Definition: sdf_gradient.h:452
Vector3D cylinder_gradient_analytic(const Point3D &p, double)
无限圆柱(沿 Y 轴)的解析梯度
Definition: sdf_gradient.h:312
GradResult chain_twist(const GradResult &child_result, double amount, const Point3D &p)
扭曲变换后的梯度传递(含完整雅可比)
Definition: sdf_gradient.h:558
Vector3D capsule_gradient_analytic(const Point3D &p, const Point3D &a, const Point3D &b, double radius)
胶囊体 SDF 的解析梯度
Definition: sdf_gradient.h:354
ParamGrad sphere_param_grad(const Point3D &p, double radius, double h=1e-6)
球体所有参数的梯度(当前仅 radius 有意义)
Definition: sdf_gradient.h:642
ParamGrad box_param_grad(const Point3D &p, const Point3D &half_extents, double h=1e-6)
长方体所有参数的梯度
Definition: sdf_gradient.h:661
double cylinder_radius_gradient(const Point3D &p, double radius, double height, double h=1e-6)
圆柱 SDF 对半径的参数梯度 ∂f/∂radius
Definition: sdf_gradient.h:199
Vector3D chain_difference(const Vector3D &grad_a, const Vector3D &grad_b, double d1, double d2)
差集操作后的梯度传递
Definition: sdf_gradient.h:424
double box(const Point3D &p, const Point3D &half_extents)
轴对齐立方体的 SDF
double cylinder(const Point3D &p, double radius, double height)
带平端盖的圆柱体 SDF
Vector3D chain_union(const Vector3D &grad_a, const Vector3D &grad_b, double d1, double d2)
并集操作后的梯度传递
Definition: sdf_gradient.h:394
GradResult chain_rotate(const GradResult &child_result, double angle_rad)
绕 Y 轴旋转后的梯度传递
Definition: sdf_gradient.h:498
double box_extent_gradient(const Point3D &p, const Point3D &extents, int axis, double h=1e-6)
长方体 SDF 对各轴半尺寸的参数梯度 ∂f/∂extent[i]
Definition: sdf_gradient.h:143
double cylinder_height_gradient(const Point3D &p, double radius, double height, double h=1e-6)
圆柱 SDF 对高度的参数梯度 ∂f/∂height
Definition: sdf_gradient.h:188
double torus(const Point3D &p, double major_radius, double minor_radius)
圆环面的 SDF
GradResult chain_repeat(const GradResult &child_result, const Point3D &, const Point3D &)
周期重复后的梯度传递(梯度不变)
Definition: sdf_gradient.h:597
double sphere_radius_gradient(const Point3D &p, double radius, double h=1e-6)
球体 SDF 对半径的参数梯度 ∂f/∂r
Definition: sdf_gradient.h:127
double torus_minor_gradient(const Point3D &p, double major_r, double minor_r, double h=1e-6)
圆环 SDF 对副半径的参数梯度 ∂f/∂minor_r
Definition: sdf_gradient.h:173
Vector3D plane_gradient_analytic(const Vector3D &normal)
平面的解析梯度
Definition: sdf_gradient.h:331
Vector3D box_gradient_analytic(const Point3D &p, const Point3D &half_extents)
长方体 SDF 的解析梯度
Definition: sdf_gradient.h:243
Vector3D torus_gradient_analytic(const Point3D &p, double major_r, double minor_r)
圆环 SDF 的解析梯度
Definition: sdf_gradient.h:280
Vector3D chain_intersection(const Vector3D &grad_a, const Vector3D &grad_b, double d1, double d2)
交集操作后的梯度传递
Definition: sdf_gradient.h:407
GradResult chain_scale(const GradResult &child_result, const Point3D &factors)
非均匀缩放后的梯度传递
Definition: sdf_gradient.h:525
double sphere(const Point3D &p, double radius)
球体的 SDF
double torus_major_gradient(const Point3D &p, double major_r, double minor_r, double h=1e-6)
圆环 SDF 对主半径的参数梯度 ∂f/∂major_r
Definition: sdf_gradient.h:162
GradResult chain_translate(const GradResult &child_result, const Point3D &)
平移变换后的梯度传递(梯度不变)
Definition: sdf_gradient.h:481
ParamGrad cylinder_param_grad(const Point3D &p, double radius, double height, double h=1e-6)
圆柱所有参数的梯度
Definition: sdf_gradient.h:682
Vector3D gradient(const std::function< double(const Point3D &)> &f, const Point3D &p, double h=1e-6)
SDF 的空间梯度(中心差分近似)
Definition: sdf_gradient.h:65
GradResult evaluate_with_gradient(const std::function< double(const Point3D &)> &f, const Point3D &p, double h=1e-6)
同时计算 SDF 值和梯度的便捷函数
Definition: sdf_gradient.h:102
SDF 布尔运算、修饰算子与域变形
有符号距离函数(SDF)基础图元
前向模梯度结果: SDF 值 + 梯度
Definition: sdf_gradient.h:87
double value
SDF 值 f(p)
Definition: sdf_gradient.h:88
Vector3D grad
空间梯度 ∇f(p) = (df/dx, df/dy, df/dz)
Definition: sdf_gradient.h:89
参数梯度结构体
Definition: sdf_gradient.h:618
Point3D d_translate
∂f/∂translate_offset
Definition: sdf_gradient.h:627
double d_height
∂f/∂height
Definition: sdf_gradient.h:620
double d_minor
∂f/∂minor_radius
Definition: sdf_gradient.h:623
double d_rotate
∂f/∂rotation_angle
Definition: sdf_gradient.h:628
double d_offset
∂f/∂offset
Definition: sdf_gradient.h:626
Vector3D d_normal
∂f/∂normal (无效分量清零)
Definition: sdf_gradient.h:625
double d_major
∂f/∂major_radius
Definition: sdf_gradient.h:622
Point3D d_scale
∂f/∂scale_factors
Definition: sdf_gradient.h:629
double d_radius
∂f/∂radius
Definition: sdf_gradient.h:619
Point3D d_extents
∂f/∂(extent.x, extent.y, extent.z)
Definition: sdf_gradient.h:621
double d_angle
∂f/∂angle_rad
Definition: sdf_gradient.h:624