PCL - MLS代碼研讀(五)- 曲率計算函數
前言
本篇延續PCL - MLS代碼研讀(二),繼續介紹曲率計算函數。
calculatePrincipalCurvatures
Eigen::Vector2f
pcl::MLSResult::calculatePrincipalCurvatures (const double u, const double v) const
{
Eigen::Vector2f k (1e-5, 1e-5);
//k1,k2:principal curvature
// Note: this use the Monge Patch to derive the Gaussian curvature and Mean Curvature found here http://mathworld.wolfram.com/MongePatch.html
// Then:
// k1 = H + sqrt(H^2 - K)
// k2 = H - sqrt(H^2 - K)
if (order > 1 && c_vec.size () >= (order + 1) * (order + 2) / 2 && std::isfinite (c_vec[0]))
{
const PolynomialPartialDerivative d = getPolynomialPartialDerivative (u, v);
const double Z = 1 + d.z_u * d.z_u + d.z_v * d.z_v;
//連結裡e,f,g的分母
const double Zlen = std::sqrt (Z);
//Gaussian curvature
const double K = (d.z_uu * d.z_vv - d.z_uv * d.z_uv) / (Z * Z);
//mean curvature
const double H = ((1.0 + d.z_v * d.z_v) * d.z_uu - 2.0 * d.z_u * d.z_v * d.z_uv + (1.0 + d.z_u * d.z_u) * d.z_vv) / (2.0 * Zlen * Zlen * Zlen);
//按照這裡的公式計算k1及k2: https://mathworld.wolfram.com/PrincipalCurvatures.html
const double disc2 = H * H - K;
assert (disc2 >= 0.0);
const double disc = std::sqrt (disc2);
k[0] = H + disc;
k[1] = H - disc;
//k[0]的絕對值要比較小?
if (std::abs (k[0]) > std::abs (k[1])) std::swap (k[0], k[1]);
}
else
{
PCL_ERROR ("No Polynomial fit data, unable to calculate the principal curvatures!\n");
}
return (k);
}
principal curvature的公式推導需要微分幾何領域的知識,已超出筆者的知識範圍。因此這裡僅將算好的公式與代碼做對照。
參考Monge Patch, K = h u u h v v − h u v 2 ( 1 + h u 2 + h v 2 ) 2 K = \frac{h_{uu}h_{vv} - h_{uv}^2}{(1+h_u^2+h_v^2)^2} K=(1+hu2+hv2)2huuhvv−huv2, H = ( 1 + h v 2 ) h u u − 2 h u h v h u v + ( 1 + h u 2 ) h v v 2 ( 1 + h u 2 + h v 2 ) 3 / 2 H = \frac{(1+h_v^2)h_{uu}-2h_uh_vh_{uv}+(1+h_u^2)h_{vv}}{2(1+h_u^2+h_v^2)^{3/2}} H=2(1+hu2+hv2)3/2(1+hv2)huu−2huhvhuv+(1+hu2)hvv。
參照Principal Curvatures,兩個principal curvature為: κ 1 = H + H 2 − K , κ 2 = H − H 2 − K \kappa_1 = H + \sqrt{H^2-K},\kappa_2 = H - \sqrt{H^2-K} κ1=H+H2−K,κ2=H−H2−K。
公式裡的
h
u
,
h
v
,
h
u
u
,
h
v
v
,
h
u
v
h_u,h_v,h_{uu},h_{vv},h_{uv}
hu,hv,huu,hvv,huv分別對應代碼中的d.z_u
,d.z_v
,d.z_uu
,d.z_vv
,d.z_uv
,代表曲面多項式在u,v兩個方向上的偏微分。知道這點後,其餘部分應該可以很容易地看懂了。
另外要注意的一點是,在連結裡給出的公式中,
κ
1
\kappa_1
κ1是大於
κ
2
\kappa_2
κ2的,但代碼裡則要求k[0]
的絕對值要小於k[1]
,原因不明。