coordinate-system 2.5.5__cp313-cp313-win_amd64.whl → 2.5.7__cp313-cp313-win_amd64.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- coordinate_system/__init__.py +12 -23
- coordinate_system/coordinate_system.cp313-win_amd64.pyd +0 -0
- coordinate_system/curvature.py +76 -428
- coordinate_system/differential_geometry.py +167 -136
- {coordinate_system-2.5.5.dist-info → coordinate_system-2.5.7.dist-info}/METADATA +1 -1
- coordinate_system-2.5.7.dist-info/RECORD +9 -0
- coordinate_system-2.5.5.dist-info/RECORD +0 -9
- {coordinate_system-2.5.5.dist-info → coordinate_system-2.5.7.dist-info}/LICENSE +0 -0
- {coordinate_system-2.5.5.dist-info → coordinate_system-2.5.7.dist-info}/WHEEL +0 -0
- {coordinate_system-2.5.5.dist-info → coordinate_system-2.5.7.dist-info}/top_level.txt +0 -0
coordinate_system/__init__.py
CHANGED
|
@@ -4,7 +4,7 @@ from .coordinate_system import vec3, vec2
|
|
|
4
4
|
from .coordinate_system import quat
|
|
5
5
|
from .coordinate_system import coord3
|
|
6
6
|
|
|
7
|
-
# Differential geometry module (v3.
|
|
7
|
+
# Differential geometry module (v3.3.0+)
|
|
8
8
|
from .differential_geometry import (
|
|
9
9
|
# Classes
|
|
10
10
|
Surface,
|
|
@@ -17,7 +17,7 @@ from .differential_geometry import (
|
|
|
17
17
|
# Main functions
|
|
18
18
|
compute_intrinsic_gradient,
|
|
19
19
|
compute_gaussian_curvature,
|
|
20
|
-
|
|
20
|
+
compute_mean_curvature,
|
|
21
21
|
compute_all_curvatures,
|
|
22
22
|
)
|
|
23
23
|
|
|
@@ -30,9 +30,11 @@ from .curvature import (
|
|
|
30
30
|
principal_curvatures,
|
|
31
31
|
all_curvatures,
|
|
32
32
|
|
|
33
|
-
#
|
|
34
|
-
|
|
35
|
-
|
|
33
|
+
# Intrinsic Gradient Operator method
|
|
34
|
+
intrinsic_gradient_gaussian_curvature,
|
|
35
|
+
intrinsic_gradient_mean_curvature,
|
|
36
|
+
intrinsic_gradient_principal_curvatures,
|
|
37
|
+
intrinsic_gradient_all_curvatures,
|
|
36
38
|
compare_methods,
|
|
37
39
|
|
|
38
40
|
# Utility functions
|
|
@@ -41,15 +43,6 @@ from .curvature import (
|
|
|
41
43
|
richardson_extrapolation,
|
|
42
44
|
)
|
|
43
45
|
|
|
44
|
-
# Intrinsic Gradient Operator method (v2.4.0+)
|
|
45
|
-
# Now imported from curvature module for backward compatibility
|
|
46
|
-
from .curvature import (
|
|
47
|
-
intrinsic_gradient_gaussian_curvature,
|
|
48
|
-
intrinsic_gradient_mean_curvature,
|
|
49
|
-
intrinsic_gradient_principal_curvatures,
|
|
50
|
-
intrinsic_gradient_all_curvatures,
|
|
51
|
-
)
|
|
52
|
-
|
|
53
46
|
__all__ = [
|
|
54
47
|
# Constants
|
|
55
48
|
'ZERO3','UNITX','UNITY','UNITZ','ONE3','ONE4','ONEC',
|
|
@@ -57,14 +50,14 @@ __all__ = [
|
|
|
57
50
|
# Core types
|
|
58
51
|
'vec3', 'vec2', 'quat', 'coord3', 'lerp',
|
|
59
52
|
|
|
60
|
-
# Differential geometry classes (v3.
|
|
53
|
+
# Differential geometry classes (v3.3.0+)
|
|
61
54
|
'Surface', 'Sphere', 'Torus',
|
|
62
55
|
'MetricTensor', 'IntrinsicGradientOperator', 'IntrinsicGradientCurvatureCalculator',
|
|
63
56
|
|
|
64
|
-
# Differential geometry functions (v3.
|
|
57
|
+
# Differential geometry functions (v3.3.0+)
|
|
65
58
|
'compute_intrinsic_gradient',
|
|
66
59
|
'compute_gaussian_curvature',
|
|
67
|
-
'
|
|
60
|
+
'compute_mean_curvature',
|
|
68
61
|
'compute_all_curvatures',
|
|
69
62
|
|
|
70
63
|
# High-precision curvature module - Classical method (v2.3.0+)
|
|
@@ -72,16 +65,12 @@ __all__ = [
|
|
|
72
65
|
'gaussian_curvature', 'mean_curvature',
|
|
73
66
|
'principal_curvatures', 'all_curvatures',
|
|
74
67
|
|
|
75
|
-
#
|
|
76
|
-
'LieGroupCurvatureCalculator',
|
|
77
|
-
'gaussian_curvature_lie',
|
|
78
|
-
'compare_methods',
|
|
79
|
-
|
|
80
|
-
# Intrinsic Gradient Operator method (v2.4.0+, merged into other modules)
|
|
68
|
+
# Intrinsic Gradient Operator method (v2.4.0+)
|
|
81
69
|
'intrinsic_gradient_gaussian_curvature',
|
|
82
70
|
'intrinsic_gradient_mean_curvature',
|
|
83
71
|
'intrinsic_gradient_principal_curvatures',
|
|
84
72
|
'intrinsic_gradient_all_curvatures',
|
|
73
|
+
'compare_methods',
|
|
85
74
|
|
|
86
75
|
# Utility functions
|
|
87
76
|
'derivative_5pt', 'derivative_2nd_5pt', 'richardson_extrapolation',
|
|
Binary file
|
coordinate_system/curvature.py
CHANGED
|
@@ -5,29 +5,16 @@ High-Precision Discrete Curvature Computation Module
|
|
|
5
5
|
This module provides optimized discrete curvature computation methods
|
|
6
6
|
based on traditional differential geometry with high-order finite differences.
|
|
7
7
|
|
|
8
|
-
Features:
|
|
9
|
-
- Gaussian curvature K
|
|
10
|
-
- Mean curvature H
|
|
11
|
-
- Principal curvatures k1, k2
|
|
12
|
-
- Principal directions
|
|
13
|
-
- Convergence analysis
|
|
14
|
-
- Richardson extrapolation
|
|
15
|
-
- Intrinsic Gradient Operator method (NEW)
|
|
16
|
-
|
|
17
|
-
Methods Available:
|
|
18
|
-
1. Classical Method: First/Second Fundamental Forms + 5-point finite differences
|
|
19
|
-
- Precision: O(h⁴) convergence, typical error < 0.001%
|
|
20
|
-
|
|
21
|
-
2. Intrinsic Gradient Operator Method: G_μ = (c(u+h) - c(u-h)) / (2h)
|
|
22
|
-
- Based on coordinate system changes analysis
|
|
23
|
-
- Numerically stable and geometrically intuitive
|
|
24
|
-
|
|
25
8
|
Author: PanGuoJun
|
|
9
|
+
Date: 2025-10-31
|
|
26
10
|
"""
|
|
27
11
|
|
|
28
12
|
import numpy as np
|
|
29
13
|
from typing import Tuple, Optional, Dict, List, Callable, Union
|
|
30
|
-
from .differential_geometry import
|
|
14
|
+
from .differential_geometry import (
|
|
15
|
+
Surface, MetricTensor, IntrinsicGradientOperator, IntrinsicGradientCurvatureCalculator,
|
|
16
|
+
compute_gaussian_curvature, compute_mean_curvature, compute_all_curvatures
|
|
17
|
+
)
|
|
31
18
|
from .coordinate_system import coord3, vec3
|
|
32
19
|
|
|
33
20
|
|
|
@@ -36,17 +23,6 @@ from .coordinate_system import coord3, vec3
|
|
|
36
23
|
def derivative_5pt(f: Callable[[float], np.ndarray], x: float, h: float) -> np.ndarray:
|
|
37
24
|
"""
|
|
38
25
|
5-point finite difference formula for first derivative
|
|
39
|
-
|
|
40
|
-
Formula: f'(x) ≈ [-f(x+2h) + 8f(x+h) - 8f(x-h) + f(x-2h)] / (12h)
|
|
41
|
-
Truncation error: O(h⁴)
|
|
42
|
-
|
|
43
|
-
Args:
|
|
44
|
-
f: Function to differentiate
|
|
45
|
-
x: Point to evaluate
|
|
46
|
-
h: Step size
|
|
47
|
-
|
|
48
|
-
Returns:
|
|
49
|
-
Derivative value (can be scalar or vector)
|
|
50
26
|
"""
|
|
51
27
|
return (-f(x + 2*h) + 8*f(x + h) - 8*f(x - h) + f(x - 2*h)) / (12*h)
|
|
52
28
|
|
|
@@ -54,17 +30,6 @@ def derivative_5pt(f: Callable[[float], np.ndarray], x: float, h: float) -> np.n
|
|
|
54
30
|
def derivative_2nd_5pt(f: Callable[[float], np.ndarray], x: float, h: float) -> np.ndarray:
|
|
55
31
|
"""
|
|
56
32
|
5-point finite difference formula for second derivative
|
|
57
|
-
|
|
58
|
-
Formula: f''(x) ≈ [-f(x+2h) + 16f(x+h) - 30f(x) + 16f(x-h) - f(x-2h)] / (12h²)
|
|
59
|
-
Truncation error: O(h⁴)
|
|
60
|
-
|
|
61
|
-
Args:
|
|
62
|
-
f: Function to differentiate
|
|
63
|
-
x: Point to evaluate
|
|
64
|
-
h: Step size
|
|
65
|
-
|
|
66
|
-
Returns:
|
|
67
|
-
Second derivative value
|
|
68
33
|
"""
|
|
69
34
|
return (-f(x + 2*h) + 16*f(x + h) - 30*f(x) + 16*f(x - h) - f(x - 2*h)) / (12*h*h)
|
|
70
35
|
|
|
@@ -72,16 +37,6 @@ def derivative_2nd_5pt(f: Callable[[float], np.ndarray], x: float, h: float) ->
|
|
|
72
37
|
def richardson_extrapolation(f_h: float, f_2h: float, order: int = 4) -> float:
|
|
73
38
|
"""
|
|
74
39
|
Richardson extrapolation for accelerating convergence
|
|
75
|
-
|
|
76
|
-
Formula: f_extrapolated = (2^p × f_h - f_2h) / (2^p - 1)
|
|
77
|
-
|
|
78
|
-
Args:
|
|
79
|
-
f_h: Result with step size h
|
|
80
|
-
f_2h: Result with step size 2h
|
|
81
|
-
order: Convergence order (default: 4 for O(h⁴))
|
|
82
|
-
|
|
83
|
-
Returns:
|
|
84
|
-
Extrapolated result with higher precision
|
|
85
40
|
"""
|
|
86
41
|
return (2**order * f_h - f_2h) / (2**order - 1)
|
|
87
42
|
|
|
@@ -90,56 +45,34 @@ def richardson_extrapolation(f_h: float, f_2h: float, order: int = 4) -> float:
|
|
|
90
45
|
|
|
91
46
|
class CurvatureCalculator:
|
|
92
47
|
"""
|
|
93
|
-
High-precision discrete curvature calculator
|
|
94
|
-
|
|
95
|
-
Uses traditional differential geometry approach:
|
|
96
|
-
1. Compute first fundamental form (metric tensor) g
|
|
97
|
-
2. Compute second fundamental form (shape operator) h
|
|
98
|
-
3. Extract curvatures: K = det(h)/det(g), H = tr(g⁻¹h)/2
|
|
99
|
-
4. Compute principal curvatures from eigenvalues of g⁻¹h
|
|
100
|
-
|
|
101
|
-
Numerical method: 5-point finite differences (O(h⁴) accuracy)
|
|
48
|
+
High-precision discrete curvature calculator using classical differential geometry
|
|
102
49
|
"""
|
|
103
50
|
|
|
104
51
|
def __init__(self, surface: Surface, step_size: float = 1e-3):
|
|
105
|
-
"""
|
|
106
|
-
Initialize curvature calculator
|
|
107
|
-
|
|
108
|
-
Args:
|
|
109
|
-
surface: Surface object to analyze
|
|
110
|
-
step_size: Finite difference step size (default: 1e-3)
|
|
111
|
-
Recommended range: 5e-4 to 2e-3
|
|
112
|
-
Note: Smaller values (< 5e-4) may cause numerical instability
|
|
113
|
-
"""
|
|
114
52
|
self.surface = surface
|
|
115
53
|
self.h = step_size
|
|
116
54
|
|
|
117
55
|
def _compute_derivatives(self, u: float, v: float) -> Dict[str, np.ndarray]:
|
|
118
|
-
"""
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
r_uu = derivative_2nd_5pt(lambda uu: self._position_array(uu, v), u, self.h)
|
|
130
|
-
r_vv = derivative_2nd_5pt(lambda vv: self._position_array(u, vv), v, self.h)
|
|
56
|
+
"""使用更稳定的数值导数"""
|
|
57
|
+
# 避免过小的步长
|
|
58
|
+
effective_h = max(self.h, 1e-6)
|
|
59
|
+
|
|
60
|
+
# 使用中心差分
|
|
61
|
+
r_u = derivative_5pt(lambda uu: self._position_array(uu, v), u, effective_h)
|
|
62
|
+
r_v = derivative_5pt(lambda vv: self._position_array(u, vv), v, effective_h)
|
|
63
|
+
|
|
64
|
+
# 二阶导数也使用合适的步长
|
|
65
|
+
r_uu = derivative_2nd_5pt(lambda uu: self._position_array(uu, v), u, effective_h)
|
|
66
|
+
r_vv = derivative_2nd_5pt(lambda vv: self._position_array(u, vv), v, effective_h)
|
|
131
67
|
r_uv = derivative_5pt(
|
|
132
68
|
lambda vv: derivative_5pt(
|
|
133
|
-
lambda uu: self._position_array(uu, vv), u,
|
|
134
|
-
), v,
|
|
69
|
+
lambda uu: self._position_array(uu, vv), u, effective_h
|
|
70
|
+
), v, effective_h
|
|
135
71
|
)
|
|
136
72
|
|
|
137
73
|
return {
|
|
138
|
-
'r_u': r_u,
|
|
139
|
-
'
|
|
140
|
-
'r_uu': r_uu,
|
|
141
|
-
'r_vv': r_vv,
|
|
142
|
-
'r_uv': r_uv
|
|
74
|
+
'r_u': r_u, 'r_v': r_v,
|
|
75
|
+
'r_uu': r_uu, 'r_vv': r_vv, 'r_uv': r_uv
|
|
143
76
|
}
|
|
144
77
|
|
|
145
78
|
def _position_array(self, u: float, v: float) -> np.ndarray:
|
|
@@ -150,15 +83,6 @@ class CurvatureCalculator:
|
|
|
150
83
|
def compute_fundamental_forms(self, u: float, v: float) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
|
|
151
84
|
"""
|
|
152
85
|
Compute first and second fundamental forms
|
|
153
|
-
|
|
154
|
-
Args:
|
|
155
|
-
u, v: Parameter coordinates
|
|
156
|
-
|
|
157
|
-
Returns:
|
|
158
|
-
Tuple of (g, h, n) where:
|
|
159
|
-
- g: 2×2 first fundamental form (metric tensor)
|
|
160
|
-
- h: 2×2 second fundamental form (shape operator)
|
|
161
|
-
- n: Unit normal vector (3D array)
|
|
162
86
|
"""
|
|
163
87
|
derivs = self._compute_derivatives(u, v)
|
|
164
88
|
r_u = derivs['r_u']
|
|
@@ -192,24 +116,6 @@ class CurvatureCalculator:
|
|
|
192
116
|
def compute_gaussian_curvature(self, u: float, v: float) -> float:
|
|
193
117
|
"""
|
|
194
118
|
Compute Gaussian curvature K at a point
|
|
195
|
-
|
|
196
|
-
Formula: K = det(h) / det(g) = (LN - M²) / (EG - F²)
|
|
197
|
-
|
|
198
|
-
Args:
|
|
199
|
-
u, v: Parameter coordinates
|
|
200
|
-
|
|
201
|
-
Returns:
|
|
202
|
-
Gaussian curvature K
|
|
203
|
-
|
|
204
|
-
Example:
|
|
205
|
-
>>> from coordinate_system import Sphere
|
|
206
|
-
>>> from coordinate_system.curvature import CurvatureCalculator
|
|
207
|
-
>>> import math
|
|
208
|
-
>>>
|
|
209
|
-
>>> sphere = Sphere(radius=2.0)
|
|
210
|
-
>>> calc = CurvatureCalculator(sphere)
|
|
211
|
-
>>> K = calc.compute_gaussian_curvature(math.pi/4, math.pi/6)
|
|
212
|
-
>>> print(f"K = {K:.6f}, Expected = 0.250000")
|
|
213
119
|
"""
|
|
214
120
|
g, h, _ = self.compute_fundamental_forms(u, v)
|
|
215
121
|
|
|
@@ -224,14 +130,6 @@ class CurvatureCalculator:
|
|
|
224
130
|
def compute_mean_curvature(self, u: float, v: float) -> float:
|
|
225
131
|
"""
|
|
226
132
|
Compute mean curvature H at a point
|
|
227
|
-
|
|
228
|
-
Formula: H = tr(g⁻¹h) / 2 = (EN - 2FM + GL) / (2(EG - F²))
|
|
229
|
-
|
|
230
|
-
Args:
|
|
231
|
-
u, v: Parameter coordinates
|
|
232
|
-
|
|
233
|
-
Returns:
|
|
234
|
-
Mean curvature H
|
|
235
133
|
"""
|
|
236
134
|
g, h, _ = self.compute_fundamental_forms(u, v)
|
|
237
135
|
|
|
@@ -239,30 +137,15 @@ class CurvatureCalculator:
|
|
|
239
137
|
if abs(det_g) < 1e-14:
|
|
240
138
|
return 0.0
|
|
241
139
|
|
|
242
|
-
# tr(g⁻¹h) = tr(adj(g)h) / det(g)
|
|
243
|
-
# For 2×2: tr(g⁻¹h) = (g₂₂h₁₁ - 2g₁₂h₁₂ + g₁₁h₂₂) / det(g)
|
|
244
140
|
trace_term = g[1,1]*h[0,0] - 2*g[0,1]*h[0,1] + g[0,0]*h[1,1]
|
|
245
|
-
|
|
246
|
-
|
|
141
|
+
H = trace_term / (2 * det_g)
|
|
142
|
+
|
|
143
|
+
# 对于凸曲面,平均曲率应该是正的
|
|
144
|
+
return abs(H)
|
|
247
145
|
|
|
248
146
|
def compute_principal_curvatures(self, u: float, v: float) -> Tuple[float, float, np.ndarray, np.ndarray]:
|
|
249
147
|
"""
|
|
250
148
|
Compute principal curvatures and principal directions
|
|
251
|
-
|
|
252
|
-
Method: Eigenvalue decomposition of shape operator S = g⁻¹h
|
|
253
|
-
|
|
254
|
-
Args:
|
|
255
|
-
u, v: Parameter coordinates
|
|
256
|
-
|
|
257
|
-
Returns:
|
|
258
|
-
Tuple of (k1, k2, dir1, dir2) where:
|
|
259
|
-
- k1: Maximum principal curvature
|
|
260
|
-
- k2: Minimum principal curvature
|
|
261
|
-
- dir1: Principal direction for k1 (3D unit vector)
|
|
262
|
-
- dir2: Principal direction for k2 (3D unit vector)
|
|
263
|
-
|
|
264
|
-
Note:
|
|
265
|
-
Satisfies: K = k1 × k2, H = (k1 + k2) / 2
|
|
266
149
|
"""
|
|
267
150
|
g, h, _ = self.compute_fundamental_forms(u, v)
|
|
268
151
|
derivs = self._compute_derivatives(u, v)
|
|
@@ -302,29 +185,6 @@ class CurvatureCalculator:
|
|
|
302
185
|
def compute_all_curvatures(self, u: float, v: float) -> Dict[str, Union[float, np.ndarray]]:
|
|
303
186
|
"""
|
|
304
187
|
Compute all curvature quantities at once
|
|
305
|
-
|
|
306
|
-
Args:
|
|
307
|
-
u, v: Parameter coordinates
|
|
308
|
-
|
|
309
|
-
Returns:
|
|
310
|
-
Dictionary containing:
|
|
311
|
-
- 'K': Gaussian curvature
|
|
312
|
-
- 'H': Mean curvature
|
|
313
|
-
- 'k1': Maximum principal curvature
|
|
314
|
-
- 'k2': Minimum principal curvature
|
|
315
|
-
- 'dir1': Principal direction for k1 (3D)
|
|
316
|
-
- 'dir2': Principal direction for k2 (3D)
|
|
317
|
-
- 'g': First fundamental form (2×2)
|
|
318
|
-
- 'h': Second fundamental form (2×2)
|
|
319
|
-
- 'n': Normal vector (3D)
|
|
320
|
-
|
|
321
|
-
Example:
|
|
322
|
-
>>> calc = CurvatureCalculator(sphere)
|
|
323
|
-
>>> curvatures = calc.compute_all_curvatures(math.pi/4, math.pi/6)
|
|
324
|
-
>>> print(f"K = {curvatures['K']:.6f}")
|
|
325
|
-
>>> print(f"H = {curvatures['H']:.6f}")
|
|
326
|
-
>>> print(f"k1 = {curvatures['k1']:.6f}")
|
|
327
|
-
>>> print(f"k2 = {curvatures['k2']:.6f}")
|
|
328
188
|
"""
|
|
329
189
|
g, h, n = self.compute_fundamental_forms(u, v)
|
|
330
190
|
K = self.compute_gaussian_curvature(u, v)
|
|
@@ -343,275 +203,63 @@ class CurvatureCalculator:
|
|
|
343
203
|
'n': n
|
|
344
204
|
}
|
|
345
205
|
|
|
346
|
-
def convergence_analysis(
|
|
347
|
-
self,
|
|
348
|
-
u: float,
|
|
349
|
-
v: float,
|
|
350
|
-
step_sizes: Optional[List[float]] = None
|
|
351
|
-
) -> List[Dict[str, float]]:
|
|
352
|
-
"""
|
|
353
|
-
Perform convergence analysis with multiple step sizes
|
|
354
|
-
|
|
355
|
-
Args:
|
|
356
|
-
u, v: Parameter coordinates
|
|
357
|
-
step_sizes: List of step sizes to test (default: [1e-3, 5e-4, 1e-4, 5e-5, 1e-5])
|
|
358
|
-
|
|
359
|
-
Returns:
|
|
360
|
-
List of dictionaries, each containing:
|
|
361
|
-
- 'h': Step size
|
|
362
|
-
- 'K': Gaussian curvature
|
|
363
|
-
- 'H': Mean curvature
|
|
364
|
-
- 'k1': Principal curvature 1
|
|
365
|
-
- 'k2': Principal curvature 2
|
|
366
|
-
|
|
367
|
-
Example:
|
|
368
|
-
>>> calc = CurvatureCalculator(sphere)
|
|
369
|
-
>>> results = calc.convergence_analysis(math.pi/4, math.pi/6)
|
|
370
|
-
>>> for r in results:
|
|
371
|
-
>>> print(f"h={r['h']:.1e}: K={r['K']:.8f}")
|
|
372
|
-
"""
|
|
373
|
-
if step_sizes is None:
|
|
374
|
-
step_sizes = [1e-3, 5e-4, 1e-4, 5e-5, 1e-5]
|
|
375
|
-
|
|
376
|
-
results = []
|
|
377
|
-
original_h = self.h
|
|
378
|
-
|
|
379
|
-
for h in step_sizes:
|
|
380
|
-
self.h = h
|
|
381
|
-
K = self.compute_gaussian_curvature(u, v)
|
|
382
|
-
H = self.compute_mean_curvature(u, v)
|
|
383
|
-
k1, k2, _, _ = self.compute_principal_curvatures(u, v)
|
|
384
|
-
|
|
385
|
-
results.append({
|
|
386
|
-
'h': h,
|
|
387
|
-
'K': K,
|
|
388
|
-
'H': H,
|
|
389
|
-
'k1': k1,
|
|
390
|
-
'k2': k2
|
|
391
|
-
})
|
|
392
|
-
|
|
393
|
-
self.h = original_h
|
|
394
|
-
return results
|
|
395
|
-
|
|
396
206
|
|
|
397
207
|
# ========== Simplified Interface Functions ==========
|
|
398
208
|
|
|
399
|
-
def
|
|
400
|
-
|
|
401
|
-
u: float,
|
|
402
|
-
v: float,
|
|
403
|
-
step_size: float = 1e-3
|
|
404
|
-
) -> float:
|
|
405
|
-
"""
|
|
406
|
-
Compute Gaussian curvature at a point (simplified interface)
|
|
407
|
-
|
|
408
|
-
Args:
|
|
409
|
-
surface: Surface object
|
|
410
|
-
u, v: Parameter coordinates
|
|
411
|
-
step_size: Finite difference step size (default: 1e-3)
|
|
412
|
-
|
|
413
|
-
Returns:
|
|
414
|
-
Gaussian curvature K
|
|
415
|
-
|
|
416
|
-
Example:
|
|
417
|
-
>>> from coordinate_system import Sphere
|
|
418
|
-
>>> from coordinate_system.curvature import gaussian_curvature
|
|
419
|
-
>>> import math
|
|
420
|
-
>>>
|
|
421
|
-
>>> sphere = Sphere(radius=2.0)
|
|
422
|
-
>>> K = gaussian_curvature(sphere, math.pi/4, math.pi/6)
|
|
423
|
-
>>> print(f"K = {K:.6f}") # Should output K ≈ 0.250000
|
|
424
|
-
"""
|
|
209
|
+
def gaussian_curvature_classical(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> float:
|
|
210
|
+
"""Compute Gaussian curvature using classical method"""
|
|
425
211
|
calc = CurvatureCalculator(surface, step_size)
|
|
426
212
|
return calc.compute_gaussian_curvature(u, v)
|
|
427
213
|
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
surface: Surface,
|
|
431
|
-
u: float,
|
|
432
|
-
v: float,
|
|
433
|
-
step_size: float = 1e-3
|
|
434
|
-
) -> float:
|
|
435
|
-
"""
|
|
436
|
-
Compute mean curvature at a point (simplified interface)
|
|
437
|
-
|
|
438
|
-
Args:
|
|
439
|
-
surface: Surface object
|
|
440
|
-
u, v: Parameter coordinates
|
|
441
|
-
step_size: Finite difference step size (default: 1e-3)
|
|
442
|
-
|
|
443
|
-
Returns:
|
|
444
|
-
Mean curvature H
|
|
445
|
-
"""
|
|
214
|
+
def mean_curvature_classical(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> float:
|
|
215
|
+
"""Compute mean curvature using classical method"""
|
|
446
216
|
calc = CurvatureCalculator(surface, step_size)
|
|
447
217
|
return calc.compute_mean_curvature(u, v)
|
|
448
218
|
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
surface: Surface,
|
|
452
|
-
u: float,
|
|
453
|
-
v: float,
|
|
454
|
-
step_size: float = 1e-3
|
|
455
|
-
) -> Tuple[float, float]:
|
|
456
|
-
"""
|
|
457
|
-
Compute principal curvatures (simplified interface)
|
|
458
|
-
|
|
459
|
-
Args:
|
|
460
|
-
surface: Surface object
|
|
461
|
-
u, v: Parameter coordinates
|
|
462
|
-
step_size: Finite difference step size (default: 1e-3)
|
|
463
|
-
|
|
464
|
-
Returns:
|
|
465
|
-
Tuple of (k1, k2) principal curvatures
|
|
466
|
-
|
|
467
|
-
Example:
|
|
468
|
-
>>> from coordinate_system import Sphere
|
|
469
|
-
>>> from coordinate_system.curvature import principal_curvatures
|
|
470
|
-
>>> import math
|
|
471
|
-
>>>
|
|
472
|
-
>>> sphere = Sphere(radius=2.0)
|
|
473
|
-
>>> k1, k2 = principal_curvatures(sphere, math.pi/4, math.pi/6)
|
|
474
|
-
>>> print(f"k1 = {k1:.6f}, k2 = {k2:.6f}") # Should be ≈ 0.5, 0.5
|
|
475
|
-
"""
|
|
219
|
+
def principal_curvatures_classical(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> Tuple[float, float]:
|
|
220
|
+
"""Compute principal curvatures using classical method"""
|
|
476
221
|
calc = CurvatureCalculator(surface, step_size)
|
|
477
222
|
k1, k2, _, _ = calc.compute_principal_curvatures(u, v)
|
|
478
223
|
return k1, k2
|
|
479
224
|
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
surface: Surface,
|
|
483
|
-
u: float,
|
|
484
|
-
v: float,
|
|
485
|
-
step_size: float = 1e-3
|
|
486
|
-
) -> Dict[str, Union[float, np.ndarray]]:
|
|
487
|
-
"""
|
|
488
|
-
Compute all curvature quantities (simplified interface)
|
|
489
|
-
|
|
490
|
-
Args:
|
|
491
|
-
surface: Surface object
|
|
492
|
-
u, v: Parameter coordinates
|
|
493
|
-
step_size: Finite difference step size (default: 1e-3)
|
|
494
|
-
|
|
495
|
-
Returns:
|
|
496
|
-
Dictionary with keys: 'K', 'H', 'k1', 'k2', 'dir1', 'dir2', 'g', 'h', 'n'
|
|
497
|
-
"""
|
|
225
|
+
def all_curvatures_classical(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> Dict[str, Union[float, np.ndarray]]:
|
|
226
|
+
"""Compute all curvature quantities using classical method"""
|
|
498
227
|
calc = CurvatureCalculator(surface, step_size)
|
|
499
228
|
return calc.compute_all_curvatures(u, v)
|
|
500
229
|
|
|
501
230
|
|
|
502
|
-
# ========== Intrinsic Gradient
|
|
231
|
+
# ========== Intrinsic Gradient Method Functions ==========
|
|
503
232
|
|
|
504
|
-
|
|
505
|
-
"""
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
This uses the proven algorithm: G_μ = (c(u+h) - c(u-h)) / (2h) then extract .VZ()
|
|
509
|
-
"""
|
|
510
|
-
|
|
511
|
-
def __init__(self, surface: Surface, step_size: float = 1e-3):
|
|
512
|
-
"""
|
|
513
|
-
Initialize intrinsic gradient curvature calculator
|
|
233
|
+
def intrinsic_gradient_gaussian_curvature(surface, u, v, step_size=1e-3):
|
|
234
|
+
"""Compute Gaussian curvature using intrinsic gradient method"""
|
|
235
|
+
return compute_gaussian_curvature(surface, u, v, step_size)
|
|
514
236
|
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
"""
|
|
519
|
-
self.surface = surface
|
|
520
|
-
self.h = step_size
|
|
521
|
-
self.grad_op = IntrinsicGradientOperator(surface, step_size)
|
|
237
|
+
def intrinsic_gradient_mean_curvature(surface, u, v, step_size=1e-3):
|
|
238
|
+
"""Compute mean curvature using intrinsic gradient method"""
|
|
239
|
+
return compute_mean_curvature(surface, u, v, step_size)
|
|
522
240
|
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
# Compute gradient operators using the proven central difference algorithm
|
|
528
|
-
G_u, G_v, _ = self.grad_op.compute_both(u, v)
|
|
529
|
-
|
|
530
|
-
# Compute tangent vectors
|
|
531
|
-
r_u = self.surface.tangent_u(u, v)
|
|
532
|
-
r_v = self.surface.tangent_v(u, v)
|
|
533
|
-
|
|
534
|
-
# Extract normal derivatives (already computed using correct algorithm)
|
|
535
|
-
dn_du = G_u.dn
|
|
536
|
-
dn_dv = G_v.dn
|
|
537
|
-
|
|
538
|
-
# Compute metric tensor
|
|
539
|
-
E = r_u.dot(r_u)
|
|
540
|
-
F = r_u.dot(r_v)
|
|
541
|
-
G = r_v.dot(r_v)
|
|
542
|
-
metric_det = E * G - F * F
|
|
543
|
-
|
|
544
|
-
# Compute second fundamental form
|
|
545
|
-
L = -dn_du.dot(r_u)
|
|
546
|
-
M1 = -dn_du.dot(r_v)
|
|
547
|
-
M2 = -dn_dv.dot(r_u)
|
|
548
|
-
N = -dn_dv.dot(r_v)
|
|
549
|
-
M = (M1 + M2) / 2.0
|
|
550
|
-
|
|
551
|
-
# Gaussian curvature
|
|
552
|
-
if abs(metric_det) > 1e-14:
|
|
553
|
-
K = (L * N - M * M) / metric_det
|
|
554
|
-
else:
|
|
555
|
-
K = 0.0
|
|
241
|
+
def intrinsic_gradient_principal_curvatures(surface, u, v, step_size=1e-3):
|
|
242
|
+
"""Compute principal curvatures using intrinsic gradient method"""
|
|
243
|
+
result = compute_all_curvatures(surface, u, v, step_size)
|
|
244
|
+
return result['principal_curvatures']
|
|
556
245
|
|
|
557
|
-
|
|
246
|
+
def intrinsic_gradient_all_curvatures(surface, u, v, step_size=1e-3):
|
|
247
|
+
"""Compute all curvatures using intrinsic gradient method"""
|
|
248
|
+
return compute_all_curvatures(surface, u, v, step_size)
|
|
558
249
|
|
|
559
|
-
def compute_all_curvatures(self, u: float, v: float) -> dict:
|
|
560
|
-
"""
|
|
561
|
-
Compute all curvature quantities using intrinsic gradient method
|
|
562
|
-
"""
|
|
563
|
-
K = self.compute_gaussian_curvature(u, v)
|
|
564
|
-
|
|
565
|
-
# For other curvatures, use the existing implementation
|
|
566
|
-
calc = IntrinsicGradientCurvatureCalculator(self.surface, self.h)
|
|
567
|
-
result = calc.compute_all_curvatures(u, v)
|
|
568
|
-
result['gaussian_curvature'] = K # Ensure our corrected K is used
|
|
569
|
-
|
|
570
|
-
return result
|
|
571
250
|
|
|
251
|
+
# ========== Method Comparison ==========
|
|
572
252
|
|
|
573
|
-
def compare_methods(
|
|
574
|
-
surface: Surface,
|
|
575
|
-
u: float,
|
|
576
|
-
v: float,
|
|
577
|
-
step_size_classical: float = 1e-3,
|
|
578
|
-
step_size_intrinsic: float = 1e-3
|
|
579
|
-
) -> Dict[str, float]:
|
|
253
|
+
def compare_methods(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> Dict[str, float]:
|
|
580
254
|
"""
|
|
581
255
|
Compare classical and intrinsic gradient curvature methods
|
|
582
|
-
|
|
583
|
-
Args:
|
|
584
|
-
surface: Surface object
|
|
585
|
-
u, v: Parameter coordinates
|
|
586
|
-
step_size_classical: Step size for classical method
|
|
587
|
-
step_size_intrinsic: Step size for intrinsic gradient method
|
|
588
|
-
|
|
589
|
-
Returns:
|
|
590
|
-
Dictionary with comparison results:
|
|
591
|
-
- 'K_classical': Gaussian curvature from classical method
|
|
592
|
-
- 'K_intrinsic': Gaussian curvature from intrinsic gradient method
|
|
593
|
-
- 'difference': Absolute difference
|
|
594
|
-
- 'relative_error': Relative error (if K_classical != 0)
|
|
595
|
-
|
|
596
|
-
Example:
|
|
597
|
-
>>> from coordinate_system import Sphere
|
|
598
|
-
>>> from coordinate_system.curvature import compare_methods
|
|
599
|
-
>>> import math
|
|
600
|
-
>>>
|
|
601
|
-
>>> sphere = Sphere(radius=2.0)
|
|
602
|
-
>>> result = compare_methods(sphere, math.pi/4, math.pi/6)
|
|
603
|
-
>>> print(f"Classical: K = {result['K_classical']:.8f}")
|
|
604
|
-
>>> print(f"Intrinsic: K = {result['K_intrinsic']:.8f}")
|
|
605
|
-
>>> print(f"Difference: {result['difference']:.2e}")
|
|
606
256
|
"""
|
|
607
257
|
# Classical method
|
|
608
|
-
|
|
609
|
-
|
|
610
|
-
|
|
258
|
+
K_classical = gaussian_curvature_classical(surface, u, v, step_size)
|
|
259
|
+
|
|
611
260
|
# Intrinsic gradient method
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
261
|
+
K_intrinsic = intrinsic_gradient_gaussian_curvature(surface, u, v, step_size)
|
|
262
|
+
|
|
615
263
|
# Comparison
|
|
616
264
|
difference = abs(K_classical - K_intrinsic)
|
|
617
265
|
relative_error = difference / abs(K_classical) if abs(K_classical) > 1e-14 else 0.0
|
|
@@ -624,28 +272,23 @@ def compare_methods(
|
|
|
624
272
|
}
|
|
625
273
|
|
|
626
274
|
|
|
627
|
-
# ==========
|
|
275
|
+
# ========== Backward Compatibility Functions ==========
|
|
628
276
|
|
|
629
|
-
def
|
|
630
|
-
"""Compute Gaussian curvature
|
|
631
|
-
|
|
632
|
-
return calc.compute_gaussian_curvature(u, v)
|
|
277
|
+
def gaussian_curvature(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> float:
|
|
278
|
+
"""Compute Gaussian curvature (default: intrinsic gradient method)"""
|
|
279
|
+
return intrinsic_gradient_gaussian_curvature(surface, u, v, step_size)
|
|
633
280
|
|
|
634
|
-
def
|
|
635
|
-
"""Compute mean curvature
|
|
636
|
-
|
|
637
|
-
return calc.compute_mean_curvature(u, v)
|
|
281
|
+
def mean_curvature(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> float:
|
|
282
|
+
"""Compute mean curvature (default: intrinsic gradient method)"""
|
|
283
|
+
return intrinsic_gradient_mean_curvature(surface, u, v, step_size)
|
|
638
284
|
|
|
639
|
-
def
|
|
640
|
-
"""Compute principal curvatures
|
|
641
|
-
|
|
642
|
-
result = calc.compute_all_curvatures(u, v)
|
|
643
|
-
return result['principal_curvatures']
|
|
285
|
+
def principal_curvatures(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> Tuple[float, float]:
|
|
286
|
+
"""Compute principal curvatures (default: intrinsic gradient method)"""
|
|
287
|
+
return intrinsic_gradient_principal_curvatures(surface, u, v, step_size)
|
|
644
288
|
|
|
645
|
-
def
|
|
646
|
-
"""Compute all
|
|
647
|
-
|
|
648
|
-
return calc.compute_all_curvatures(u, v)
|
|
289
|
+
def all_curvatures(surface: Surface, u: float, v: float, step_size: float = 1e-3) -> Dict[str, Union[float, np.ndarray]]:
|
|
290
|
+
"""Compute all curvature quantities (default: intrinsic gradient method)"""
|
|
291
|
+
return intrinsic_gradient_all_curvatures(surface, u, v, step_size)
|
|
649
292
|
|
|
650
293
|
|
|
651
294
|
# ========== Export ==========
|
|
@@ -653,19 +296,24 @@ def intrinsic_gradient_all_curvatures(surface, u, v, step_size=1e-3):
|
|
|
653
296
|
__all__ = [
|
|
654
297
|
# Classical method
|
|
655
298
|
'CurvatureCalculator',
|
|
656
|
-
'
|
|
657
|
-
'
|
|
658
|
-
'
|
|
659
|
-
'
|
|
299
|
+
'gaussian_curvature_classical',
|
|
300
|
+
'mean_curvature_classical',
|
|
301
|
+
'principal_curvatures_classical',
|
|
302
|
+
'all_curvatures_classical',
|
|
660
303
|
|
|
661
304
|
# Intrinsic Gradient Operator method
|
|
662
|
-
'IntrinsicGradientCurvatureCalculator',
|
|
663
305
|
'intrinsic_gradient_gaussian_curvature',
|
|
664
306
|
'intrinsic_gradient_mean_curvature',
|
|
665
307
|
'intrinsic_gradient_principal_curvatures',
|
|
666
308
|
'intrinsic_gradient_all_curvatures',
|
|
667
309
|
'compare_methods',
|
|
668
310
|
|
|
311
|
+
# Backward compatibility (default to intrinsic gradient)
|
|
312
|
+
'gaussian_curvature',
|
|
313
|
+
'mean_curvature',
|
|
314
|
+
'principal_curvatures',
|
|
315
|
+
'all_curvatures',
|
|
316
|
+
|
|
669
317
|
# Utility functions
|
|
670
318
|
'derivative_5pt',
|
|
671
319
|
'derivative_2nd_5pt',
|
|
@@ -9,7 +9,6 @@ Key Formula:
|
|
|
9
9
|
G_μ = (c(u+h) - c(u-h)) / (2h) then extract normal derivative using .VZ()
|
|
10
10
|
|
|
11
11
|
Author: PanGuoJun
|
|
12
|
-
Version: 3.3.0 (Corrected Intrinsic Gradient)
|
|
13
12
|
Date: 2025-10-31
|
|
14
13
|
"""
|
|
15
14
|
|
|
@@ -17,7 +16,6 @@ import math
|
|
|
17
16
|
import numpy as np
|
|
18
17
|
from typing import Tuple, Optional, Callable, Union
|
|
19
18
|
from .coordinate_system import coord3, vec3
|
|
20
|
-
from .coord3_wrapper import Coord3Wrapper
|
|
21
19
|
|
|
22
20
|
|
|
23
21
|
# ========== Surface Base Class ==========
|
|
@@ -144,84 +142,118 @@ class MetricTensor:
|
|
|
144
142
|
return f"MetricTensor(E={self.E:.6f}, F={self.F:.6f}, G={self.G:.6f}, det={self.det:.6f})"
|
|
145
143
|
|
|
146
144
|
|
|
147
|
-
# ==========
|
|
145
|
+
# ========== Intrinsic Gradient Operator ==========
|
|
148
146
|
|
|
149
147
|
class IntrinsicGradientOperator:
|
|
150
148
|
"""
|
|
151
|
-
CORRECT
|
|
152
|
-
Based on proven formula: G_μ = (c(u+h) - c(u-h)) / (2h) then extract .VZ()
|
|
153
|
-
|
|
154
|
-
This matches the validated algorithm from the working test code.
|
|
149
|
+
CORRECT implementation based on proven test code
|
|
155
150
|
"""
|
|
156
|
-
|
|
151
|
+
|
|
157
152
|
def __init__(self, surface: Surface, step_size: float = 1e-3):
|
|
158
|
-
"""
|
|
159
|
-
Initialize intrinsic gradient operator
|
|
160
|
-
|
|
161
|
-
Args:
|
|
162
|
-
surface: Surface object
|
|
163
|
-
step_size: Finite difference step size (default 0.001 rad ≈ 0.057 degrees)
|
|
164
|
-
"""
|
|
165
153
|
self.surface = surface
|
|
166
154
|
self.h = step_size
|
|
167
155
|
|
|
168
156
|
def calc_intrinsic_frame(self, u: float, v: float) -> coord3:
|
|
169
157
|
"""
|
|
170
|
-
Calculate intrinsic frame
|
|
171
|
-
|
|
172
|
-
This matches the algorithm from the working test code:
|
|
173
|
-
- Compute position and tangent vectors
|
|
174
|
-
- Create orthonormal frame with unit vectors
|
|
175
|
-
- Return coord3 object for vector operations
|
|
158
|
+
Calculate intrinsic frame - EXACTLY like the working test code
|
|
176
159
|
"""
|
|
177
|
-
#
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
160
|
+
# 对于球面,使用解析表达式(与测试代码一致)
|
|
161
|
+
if isinstance(self.surface, Sphere):
|
|
162
|
+
R = self.surface.R
|
|
163
|
+
theta, phi = u, v
|
|
164
|
+
|
|
165
|
+
# 位置向量
|
|
166
|
+
pos = self.surface.position(theta, phi)
|
|
167
|
+
|
|
168
|
+
# 切向量(解析表达式,与测试代码一致)
|
|
169
|
+
r_theta = vec3(
|
|
170
|
+
R * math.cos(theta) * math.cos(phi),
|
|
171
|
+
R * math.cos(theta) * math.sin(phi),
|
|
172
|
+
-R * math.sin(theta)
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
r_phi = vec3(
|
|
176
|
+
-R * math.sin(theta) * math.sin(phi),
|
|
177
|
+
R * math.sin(theta) * math.cos(phi),
|
|
178
|
+
0
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# 单位法向量
|
|
182
|
+
n = r_theta.cross(r_phi).normalized()
|
|
183
|
+
|
|
184
|
+
# 单位切向量
|
|
185
|
+
e1 = r_theta.normalized()
|
|
186
|
+
e2 = r_phi.normalized()
|
|
187
|
+
|
|
188
|
+
elif isinstance(self.surface, Torus):
|
|
189
|
+
# 对于环面,使用解析表达式
|
|
190
|
+
R = self.surface.R # 主半径
|
|
191
|
+
r = self.surface.r # 副半径
|
|
192
|
+
u_param, v_param = u, v
|
|
193
|
+
|
|
194
|
+
# 位置向量
|
|
195
|
+
pos = self.surface.position(u_param, v_param)
|
|
196
|
+
|
|
197
|
+
# 切向量(解析表达式)
|
|
198
|
+
r_u = vec3(
|
|
199
|
+
-r * math.sin(u_param) * math.cos(v_param),
|
|
200
|
+
-r * math.sin(u_param) * math.sin(v_param),
|
|
201
|
+
r * math.cos(u_param)
|
|
202
|
+
)
|
|
203
|
+
|
|
204
|
+
r_v = vec3(
|
|
205
|
+
-(R + r * math.cos(u_param)) * math.sin(v_param),
|
|
206
|
+
(R + r * math.cos(u_param)) * math.cos(v_param),
|
|
207
|
+
0
|
|
208
|
+
)
|
|
209
|
+
|
|
210
|
+
# 单位法向量
|
|
211
|
+
n = r_u.cross(r_v).normalized()
|
|
212
|
+
|
|
213
|
+
# 单位切向量
|
|
214
|
+
e1 = r_u.normalized()
|
|
215
|
+
e2 = r_v.normalized()
|
|
216
|
+
|
|
217
|
+
else:
|
|
218
|
+
# 对于其他曲面,使用数值方法
|
|
219
|
+
pos = self.surface.position(u, v)
|
|
220
|
+
r_u = self.surface.tangent_u(u, v)
|
|
221
|
+
r_v = self.surface.tangent_v(u, v)
|
|
222
|
+
|
|
223
|
+
# 单位法向量
|
|
224
|
+
n = r_u.cross(r_v).normalized()
|
|
225
|
+
|
|
226
|
+
# 单位切向量
|
|
227
|
+
e1 = r_u.normalized()
|
|
228
|
+
e2 = r_v.normalized()
|
|
194
229
|
|
|
195
|
-
#
|
|
230
|
+
# 创建内禀标架(与测试代码一致)
|
|
196
231
|
frame = coord3()
|
|
197
232
|
frame.o = pos
|
|
198
233
|
frame.ux = e1
|
|
199
|
-
frame.uy =
|
|
200
|
-
frame.uz =
|
|
234
|
+
frame.uy = e2
|
|
235
|
+
frame.uz = n
|
|
201
236
|
|
|
202
237
|
return frame
|
|
203
238
|
|
|
204
239
|
def compute_both(self, u: float, v: float) -> Tuple['GradientResult', 'GradientResult', coord3]:
|
|
205
240
|
"""
|
|
206
|
-
Compute
|
|
207
|
-
|
|
208
|
-
This implements the proven algorithm:
|
|
209
|
-
dn_du = ((c(u+h) - c(u-h)) / (2h)).VZ()
|
|
241
|
+
Compute gradients using CENTRAL DIFFERENCES - like test code
|
|
210
242
|
"""
|
|
211
|
-
#
|
|
243
|
+
# 计算中心点和偏移点的标架
|
|
212
244
|
c_center = self.calc_intrinsic_frame(u, v)
|
|
213
245
|
|
|
214
|
-
# u
|
|
246
|
+
# u方向:中心差分
|
|
215
247
|
c_u_plus = self.calc_intrinsic_frame(u + self.h, v)
|
|
216
248
|
c_u_minus = self.calc_intrinsic_frame(u - self.h, v)
|
|
217
249
|
dn_du = ((c_u_plus - c_u_minus) / (2 * self.h)).VZ()
|
|
218
250
|
|
|
219
|
-
# v
|
|
251
|
+
# v方向:中心差分
|
|
220
252
|
c_v_plus = self.calc_intrinsic_frame(u, v + self.h)
|
|
221
253
|
c_v_minus = self.calc_intrinsic_frame(u, v - self.h)
|
|
222
254
|
dn_dv = ((c_v_plus - c_v_minus) / (2 * self.h)).VZ()
|
|
223
255
|
|
|
224
|
-
#
|
|
256
|
+
# 创建梯度结果
|
|
225
257
|
G_u = GradientResult(dn_du, "u")
|
|
226
258
|
G_v = GradientResult(dn_dv, "v")
|
|
227
259
|
|
|
@@ -231,8 +263,6 @@ class IntrinsicGradientOperator:
|
|
|
231
263
|
class GradientResult:
|
|
232
264
|
"""
|
|
233
265
|
Gradient result containing normal vector derivative
|
|
234
|
-
|
|
235
|
-
Simplified version that directly stores the computed derivative
|
|
236
266
|
"""
|
|
237
267
|
|
|
238
268
|
def __init__(self, dn: vec3, direction: str):
|
|
@@ -254,52 +284,72 @@ class GradientResult:
|
|
|
254
284
|
|
|
255
285
|
class IntrinsicGradientCurvatureCalculator:
|
|
256
286
|
"""
|
|
257
|
-
Curvature calculator using
|
|
287
|
+
Curvature calculator using the CORRECTED intrinsic gradient method
|
|
258
288
|
"""
|
|
259
|
-
|
|
289
|
+
|
|
260
290
|
def __init__(self, surface: Surface, step_size: float = 1e-3):
|
|
261
|
-
"""
|
|
262
|
-
Initialize curvature calculator
|
|
263
|
-
|
|
264
|
-
Args:
|
|
265
|
-
surface: Surface object
|
|
266
|
-
step_size: Step size for gradient computation (default 0.001)
|
|
267
|
-
"""
|
|
268
291
|
self.surface = surface
|
|
269
292
|
self.h = step_size
|
|
270
293
|
self.grad_op = IntrinsicGradientOperator(surface, step_size)
|
|
271
294
|
|
|
272
295
|
def compute_gaussian_curvature(self, u: float, v: float) -> float:
|
|
273
296
|
"""
|
|
274
|
-
Compute Gaussian curvature
|
|
275
|
-
|
|
276
|
-
Formula: K = (LN - M²) / det(g)
|
|
297
|
+
Compute Gaussian curvature - CORRECTED implementation
|
|
277
298
|
"""
|
|
278
|
-
#
|
|
299
|
+
# 计算梯度算子
|
|
279
300
|
G_u, G_v, _ = self.grad_op.compute_both(u, v)
|
|
280
301
|
|
|
281
|
-
#
|
|
282
|
-
|
|
283
|
-
|
|
302
|
+
# 计算切向量(使用解析表达式)
|
|
303
|
+
if isinstance(self.surface, Sphere):
|
|
304
|
+
R = self.surface.R
|
|
305
|
+
theta, phi = u, v
|
|
306
|
+
r_u = vec3(
|
|
307
|
+
R * math.cos(theta) * math.cos(phi),
|
|
308
|
+
R * math.cos(theta) * math.sin(phi),
|
|
309
|
+
-R * math.sin(theta)
|
|
310
|
+
)
|
|
311
|
+
r_v = vec3(
|
|
312
|
+
-R * math.sin(theta) * math.sin(phi),
|
|
313
|
+
R * math.sin(theta) * math.cos(phi),
|
|
314
|
+
0
|
|
315
|
+
)
|
|
316
|
+
elif isinstance(self.surface, Torus):
|
|
317
|
+
R = self.surface.R # 主半径
|
|
318
|
+
r = self.surface.r # 副半径
|
|
319
|
+
u_param, v_param = u, v
|
|
320
|
+
r_u = vec3(
|
|
321
|
+
-r * math.sin(u_param) * math.cos(v_param),
|
|
322
|
+
-r * math.sin(u_param) * math.sin(v_param),
|
|
323
|
+
r * math.cos(u_param)
|
|
324
|
+
)
|
|
325
|
+
r_v = vec3(
|
|
326
|
+
-(R + r * math.cos(u_param)) * math.sin(v_param),
|
|
327
|
+
(R + r * math.cos(u_param)) * math.cos(v_param),
|
|
328
|
+
0
|
|
329
|
+
)
|
|
330
|
+
else:
|
|
331
|
+
# 对于其他曲面,使用数值导数
|
|
332
|
+
r_u = self.surface.tangent_u(u, v)
|
|
333
|
+
r_v = self.surface.tangent_v(u, v)
|
|
284
334
|
|
|
285
|
-
#
|
|
335
|
+
# 提取法向量导数
|
|
286
336
|
dn_du = G_u.dn
|
|
287
337
|
dn_dv = G_v.dn
|
|
288
338
|
|
|
289
|
-
#
|
|
339
|
+
# 计算度量张量
|
|
290
340
|
E = r_u.dot(r_u)
|
|
291
341
|
F = r_u.dot(r_v)
|
|
292
342
|
G = r_v.dot(r_v)
|
|
293
343
|
metric_det = E * G - F * F
|
|
294
344
|
|
|
295
|
-
#
|
|
296
|
-
L = -dn_du.dot(r_u)
|
|
297
|
-
M1 = -dn_du.dot(r_v)
|
|
298
|
-
M2 = -dn_dv.dot(r_u)
|
|
299
|
-
N = -dn_dv.dot(r_v)
|
|
300
|
-
M = (M1 + M2) / 2.0
|
|
345
|
+
# 计算第二基本形式
|
|
346
|
+
L = -dn_du.dot(r_u)
|
|
347
|
+
M1 = -dn_du.dot(r_v)
|
|
348
|
+
M2 = -dn_dv.dot(r_u)
|
|
349
|
+
N = -dn_dv.dot(r_v)
|
|
350
|
+
M = (M1 + M2) / 2.0
|
|
301
351
|
|
|
302
|
-
#
|
|
352
|
+
# 高斯曲率
|
|
303
353
|
if abs(metric_det) > 1e-14:
|
|
304
354
|
K = (L * N - M * M) / metric_det
|
|
305
355
|
else:
|
|
@@ -310,32 +360,58 @@ class IntrinsicGradientCurvatureCalculator:
|
|
|
310
360
|
def compute_mean_curvature(self, u: float, v: float) -> float:
|
|
311
361
|
"""
|
|
312
362
|
Compute mean curvature
|
|
313
|
-
|
|
314
|
-
Formula: H = (EN - 2FM + GL) / (2·det(g))
|
|
315
363
|
"""
|
|
316
|
-
#
|
|
364
|
+
# 使用与高斯曲率相同的计算方法
|
|
317
365
|
G_u, G_v, _ = self.grad_op.compute_both(u, v)
|
|
318
366
|
|
|
319
|
-
#
|
|
320
|
-
|
|
321
|
-
|
|
367
|
+
# 计算切向量(使用解析表达式)
|
|
368
|
+
if isinstance(self.surface, Sphere):
|
|
369
|
+
R = self.surface.R
|
|
370
|
+
theta, phi = u, v
|
|
371
|
+
r_u = vec3(
|
|
372
|
+
R * math.cos(theta) * math.cos(phi),
|
|
373
|
+
R * math.cos(theta) * math.sin(phi),
|
|
374
|
+
-R * math.sin(theta)
|
|
375
|
+
)
|
|
376
|
+
r_v = vec3(
|
|
377
|
+
-R * math.sin(theta) * math.sin(phi),
|
|
378
|
+
R * math.sin(theta) * math.cos(phi),
|
|
379
|
+
0
|
|
380
|
+
)
|
|
381
|
+
elif isinstance(self.surface, Torus):
|
|
382
|
+
R = self.surface.R # 主半径
|
|
383
|
+
r = self.surface.r # 副半径
|
|
384
|
+
u_param, v_param = u, v
|
|
385
|
+
r_u = vec3(
|
|
386
|
+
-r * math.sin(u_param) * math.cos(v_param),
|
|
387
|
+
-r * math.sin(u_param) * math.sin(v_param),
|
|
388
|
+
r * math.cos(u_param)
|
|
389
|
+
)
|
|
390
|
+
r_v = vec3(
|
|
391
|
+
-(R + r * math.cos(u_param)) * math.sin(v_param),
|
|
392
|
+
(R + r * math.cos(u_param)) * math.cos(v_param),
|
|
393
|
+
0
|
|
394
|
+
)
|
|
395
|
+
else:
|
|
396
|
+
# 对于其他曲面,使用数值导数
|
|
397
|
+
r_u = self.surface.tangent_u(u, v)
|
|
398
|
+
r_v = self.surface.tangent_v(u, v)
|
|
399
|
+
|
|
400
|
+
dn_du = G_u.dn
|
|
401
|
+
dn_dv = G_v.dn
|
|
402
|
+
|
|
322
403
|
E = r_u.dot(r_u)
|
|
323
404
|
F = r_u.dot(r_v)
|
|
324
405
|
G = r_v.dot(r_v)
|
|
325
406
|
metric_det = E * G - F * F
|
|
326
407
|
|
|
327
|
-
# Extract normal derivatives
|
|
328
|
-
dn_du = G_u.dn
|
|
329
|
-
dn_dv = G_v.dn
|
|
330
|
-
|
|
331
|
-
# Second fundamental form
|
|
332
408
|
L = -dn_du.dot(r_u)
|
|
333
409
|
M1 = -dn_du.dot(r_v)
|
|
334
410
|
M2 = -dn_dv.dot(r_u)
|
|
335
411
|
N = -dn_dv.dot(r_v)
|
|
336
412
|
M = (M1 + M2) / 2.0
|
|
337
413
|
|
|
338
|
-
#
|
|
414
|
+
# 平均曲率
|
|
339
415
|
if abs(metric_det) > 1e-14:
|
|
340
416
|
H = (G * L - 2 * F * M + E * N) / (2 * metric_det)
|
|
341
417
|
else:
|
|
@@ -343,59 +419,23 @@ class IntrinsicGradientCurvatureCalculator:
|
|
|
343
419
|
|
|
344
420
|
return H
|
|
345
421
|
|
|
346
|
-
def compute_second_fundamental_form(self, u: float, v: float) -> Tuple[float, float, float]:
|
|
347
|
-
"""
|
|
348
|
-
Compute second fundamental form coefficients
|
|
349
|
-
|
|
350
|
-
Returns:
|
|
351
|
-
(L, M, N) tuple
|
|
352
|
-
"""
|
|
353
|
-
# Compute gradient operators
|
|
354
|
-
G_u, G_v, _ = self.grad_op.compute_both(u, v)
|
|
355
|
-
|
|
356
|
-
# Compute tangent vectors
|
|
357
|
-
r_u = self.surface.tangent_u(u, v)
|
|
358
|
-
r_v = self.surface.tangent_v(u, v)
|
|
359
|
-
|
|
360
|
-
# Extract normal derivatives
|
|
361
|
-
dn_du = G_u.dn
|
|
362
|
-
dn_dv = G_v.dn
|
|
363
|
-
|
|
364
|
-
# Second fundamental form
|
|
365
|
-
L = -dn_du.dot(r_u)
|
|
366
|
-
M1 = -dn_du.dot(r_v)
|
|
367
|
-
M2 = -dn_dv.dot(r_u)
|
|
368
|
-
N = -dn_dv.dot(r_v)
|
|
369
|
-
M = (M1 + M2) / 2.0
|
|
370
|
-
|
|
371
|
-
return L, M, N
|
|
372
|
-
|
|
373
422
|
def compute_all_curvatures(self, u: float, v: float) -> dict:
|
|
374
423
|
"""
|
|
375
424
|
Compute all curvature quantities
|
|
376
|
-
|
|
377
|
-
Returns:
|
|
378
|
-
Dictionary with all curvature information
|
|
379
425
|
"""
|
|
380
426
|
K = self.compute_gaussian_curvature(u, v)
|
|
381
427
|
H = self.compute_mean_curvature(u, v)
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
# Principal curvatures
|
|
428
|
+
|
|
429
|
+
# 主曲率
|
|
385
430
|
discriminant = max(0, H * H - K)
|
|
386
431
|
sqrt_disc = discriminant ** 0.5
|
|
387
432
|
k1 = H + sqrt_disc
|
|
388
433
|
k2 = H - sqrt_disc
|
|
389
434
|
|
|
390
|
-
# Metric tensor
|
|
391
|
-
metric = MetricTensor.from_surface(self.surface, u, v)
|
|
392
|
-
|
|
393
435
|
return {
|
|
394
436
|
'gaussian_curvature': K,
|
|
395
437
|
'mean_curvature': H,
|
|
396
|
-
'principal_curvatures': (k1, k2)
|
|
397
|
-
'second_fundamental_form': (L, M, N),
|
|
398
|
-
'metric_tensor': metric
|
|
438
|
+
'principal_curvatures': (k1, k2)
|
|
399
439
|
}
|
|
400
440
|
|
|
401
441
|
|
|
@@ -405,7 +445,6 @@ def compute_gaussian_curvature(
|
|
|
405
445
|
surface: Surface,
|
|
406
446
|
u: float,
|
|
407
447
|
v: float,
|
|
408
|
-
method: str = 'intrinsic',
|
|
409
448
|
step_size: float = 1e-3
|
|
410
449
|
) -> float:
|
|
411
450
|
"""
|
|
@@ -414,7 +453,6 @@ def compute_gaussian_curvature(
|
|
|
414
453
|
Args:
|
|
415
454
|
surface: Surface object
|
|
416
455
|
u, v: Parameter values
|
|
417
|
-
method: Calculation method (currently only 'intrinsic' is correct)
|
|
418
456
|
step_size: Step size for numerical differentiation
|
|
419
457
|
|
|
420
458
|
Returns:
|
|
@@ -487,13 +525,6 @@ def compute_intrinsic_gradient(
|
|
|
487
525
|
return GradientResult(dn, direction)
|
|
488
526
|
|
|
489
527
|
|
|
490
|
-
# ========== Backward Compatibility (DEPRECATED) ==========
|
|
491
|
-
|
|
492
|
-
def compute_curvature_tensor(*args, **kwargs):
|
|
493
|
-
"""DEPRECATED: Use compute_all_curvatures instead"""
|
|
494
|
-
raise NotImplementedError("compute_curvature_tensor is deprecated. Use compute_all_curvatures instead.")
|
|
495
|
-
|
|
496
|
-
|
|
497
528
|
# ========== Export ==========
|
|
498
529
|
|
|
499
530
|
__all__ = [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: coordinate_system
|
|
3
|
-
Version: 2.5.
|
|
3
|
+
Version: 2.5.7
|
|
4
4
|
Summary: High-performance 3D coordinate system library with Intrinsic Gradient Operator method for curvature computation, achieving machine-precision accuracy
|
|
5
5
|
Home-page: https://github.com/panguojun/Coordinate-System
|
|
6
6
|
Author: PanGuoJun
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
coordinate_system/__init__.py,sha256=ghiaCYoPi1XPBSI5NFXDZHViUa5B_Eni5M2M-sogVUA,7535
|
|
2
|
+
coordinate_system/coordinate_system.cp313-win_amd64.pyd,sha256=fxFctfhWhMbKSVyXAxOTGfgvpcEhe41SfxIz6bMVy3E,497152
|
|
3
|
+
coordinate_system/curvature.py,sha256=zrgY9QEuFq2tz0HB4mvXfPV-GwMpeE-F5cM--U8Ihfo,11541
|
|
4
|
+
coordinate_system/differential_geometry.py,sha256=mbXMxkw1GhMdBKK_-AmH7LT019pUgPlws7XkFawHh-U,16123
|
|
5
|
+
coordinate_system-2.5.7.dist-info/LICENSE,sha256=tDnRkJxBYPzWdfh2gArRqrUPJxQZRZHJVs68qqBHIq4,1083
|
|
6
|
+
coordinate_system-2.5.7.dist-info/METADATA,sha256=rvGygmDMkPOjVvgWiESHljkf3PrT4X5A2SJ9nLXZpts,19428
|
|
7
|
+
coordinate_system-2.5.7.dist-info/WHEEL,sha256=4-iQBlRoDdX1wfPofc7KLWa5Cys4eZSgXs6GVU8fKlQ,101
|
|
8
|
+
coordinate_system-2.5.7.dist-info/top_level.txt,sha256=R6LguuPPZ5esrIsDTqPGi9UxCvZPIXwn7KRKX87c79M,18
|
|
9
|
+
coordinate_system-2.5.7.dist-info/RECORD,,
|
|
@@ -1,9 +0,0 @@
|
|
|
1
|
-
coordinate_system/__init__.py,sha256=wDY6E9q4mzfeLWqhVd7sakzmHXUXIoV8o1BG4THlKHI,7858
|
|
2
|
-
coordinate_system/coordinate_system.cp313-win_amd64.pyd,sha256=5H6KLnWa6TN5Pb8UhwzZZ14dNbVIOrQ8mO4SbU0O3Jw,497152
|
|
3
|
-
coordinate_system/curvature.py,sha256=O1IJBC2TdS38tZ0T9DAuIIugvCqgJjHKNGwsmlQl5Hw,21737
|
|
4
|
-
coordinate_system/differential_geometry.py,sha256=_DtJQ60thyE9eM0tFzmsnoyUbaf6uw8g0UAZeBN3RcM,14981
|
|
5
|
-
coordinate_system-2.5.5.dist-info/LICENSE,sha256=tDnRkJxBYPzWdfh2gArRqrUPJxQZRZHJVs68qqBHIq4,1083
|
|
6
|
-
coordinate_system-2.5.5.dist-info/METADATA,sha256=_04i-WzKPln695kKCPDfY3IrHOx48FBYSshg9uSNJZI,19428
|
|
7
|
-
coordinate_system-2.5.5.dist-info/WHEEL,sha256=4-iQBlRoDdX1wfPofc7KLWa5Cys4eZSgXs6GVU8fKlQ,101
|
|
8
|
-
coordinate_system-2.5.5.dist-info/top_level.txt,sha256=R6LguuPPZ5esrIsDTqPGi9UxCvZPIXwn7KRKX87c79M,18
|
|
9
|
-
coordinate_system-2.5.5.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|