123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148 |
- // David Eberly, Geometric Tools, Redmond WA 98052
- // Copyright (c) 1998-2020
- // Distributed under the Boost Software License, Version 1.0.
- // https://www.boost.org/LICENSE_1_0.txt
- // https://www.geometrictools.com/License/Boost/LICENSE_1_0.txt
- // Version: 4.0.2019.08.13
- #pragma once
- #include <Mathematics/Matrix2x2.h>
- #include <Mathematics/ParametricSurface.h>
- #include <Mathematics/Vector3.h>
- #include <memory>
- namespace WwiseGTE
- {
- template <typename Real>
- class DarbouxFrame3
- {
- public:
- // Construction. The curve must persist as long as the DarbouxFrame3
- // object does.
- DarbouxFrame3(std::shared_ptr<ParametricSurface<3, Real>> const& surface)
- :
- mSurface(surface)
- {
- }
- // Get a coordinate frame, {T0, T1, N}. At a nondegenerate surface
- // points, dX/du and dX/dv are linearly independent tangent vectors.
- // The frame is constructed as
- // T0 = (dX/du)/|dX/du|
- // N = Cross(dX/du,dX/dv)/|Cross(dX/du,dX/dv)|
- // T1 = Cross(N, T0)
- // so that {T0, T1, N} is a right-handed orthonormal set.
- void operator()(Real u, Real v, Vector3<Real>& position, Vector3<Real>& tangent0,
- Vector3<Real>& tangent1, Vector3<Real>& normal) const
- {
- std::array<Vector3<Real>, 3> jet;
- mSurface->Evaluate(u, v, 1, jet.data());
- position = jet[0];
- tangent0 = jet[1];
- Normalize(tangent0);
- tangent1 = jet[2];
- Normalize(tangent1);
- normal = UnitCross(tangent0, tangent1);
- tangent1 = Cross(normal, tangent0);
- }
- // Compute the principal curvatures and principal directions.
- void GetPrincipalInformation(Real u, Real v, Real& curvature0, Real& curvature1,
- Vector3<Real>& direction0, Vector3<Real>& direction1) const
- {
- // Tangents: T0 = (x_u,y_u,z_u), T1 = (x_v,y_v,z_v)
- // Normal: N = Cross(T0,T1)/Length(Cross(T0,T1))
- // Metric Tensor: G = +- -+
- // | Dot(T0,T0) Dot(T0,T1) |
- // | Dot(T1,T0) Dot(T1,T1) |
- // +- -+
- //
- // Curvature Tensor: B = +- -+
- // | -Dot(N,T0_u) -Dot(N,T0_v) |
- // | -Dot(N,T1_u) -Dot(N,T1_v) |
- // +- -+
- //
- // Principal curvatures k are the generalized eigenvalues of
- //
- // Bw = kGw
- //
- // If k is a curvature and w=(a,b) is the corresponding solution
- // to Bw = kGw, then the principal direction as a 3D vector is
- // d = a*U+b*V.
- //
- // Let k1 and k2 be the principal curvatures. The mean curvature
- // is (k1+k2)/2 and the Gaussian curvature is k1*k2.
- // Compute derivatives.
- std::array<Vector3<Real>, 6> jet;
- mSurface->Evaluate(u, v, 2, jet.data());
- Vector3<Real> derU = jet[1];
- Vector3<Real> derV = jet[2];
- Vector3<Real> derUU = jet[3];
- Vector3<Real> derUV = jet[4];
- Vector3<Real> derVV = jet[5];
- // Compute the metric tensor.
- Matrix2x2<Real> metricTensor;
- metricTensor(0, 0) = Dot(jet[1], jet[1]);
- metricTensor(0, 1) = Dot(jet[1], jet[2]);
- metricTensor(1, 0) = metricTensor(0, 1);
- metricTensor(1, 1) = Dot(jet[2], jet[2]);
- // Compute the curvature tensor.
- Vector3<Real> normal = UnitCross(jet[1], jet[2]);
- Matrix2x2<Real> curvatureTensor;
- curvatureTensor(0, 0) = -Dot(normal, derUU);
- curvatureTensor(0, 1) = -Dot(normal, derUV);
- curvatureTensor(1, 0) = curvatureTensor(0, 1);
- curvatureTensor(1, 1) = -Dot(normal, derVV);
- // Characteristic polynomial is 0 = det(B-kG) = c2*k^2+c1*k+c0.
- Real c0 = Determinant(curvatureTensor);
- Real c1 = (Real)2 * curvatureTensor(0, 1) * metricTensor(0, 1) -
- curvatureTensor(0, 0) * metricTensor(1, 1) -
- curvatureTensor(1, 1) * metricTensor(0, 0);
- Real c2 = Determinant(metricTensor);
- // Principal curvatures are roots of characteristic polynomial.
- Real temp = std::sqrt(std::max(c1 * c1 - (Real)4 * c0 * c2, (Real)0));
- Real mult = (Real)0.5 / c2;
- curvature0 = -mult * (c1 + temp);
- curvature1 = -mult * (c1 - temp);
- // Principal directions are solutions to (B-kG)w = 0,
- // w1 = (b12-k1*g12,-(b11-k1*g11)) OR (b22-k1*g22,-(b12-k1*g12)).
- Real a0 = curvatureTensor(0, 1) - curvature0 * metricTensor(0, 1);
- Real a1 = curvature0 * metricTensor(0, 0) - curvatureTensor(0, 0);
- Real length = std::sqrt(a0 * a0 + a1 * a1);
- if (length > (Real)0)
- {
- direction0 = a0 * derU + a1 * derV;
- }
- else
- {
- a0 = curvatureTensor(1, 1) - curvature0 * metricTensor(1, 1);
- a1 = curvature0 * metricTensor(0, 1) - curvatureTensor(0, 1);
- length = std::sqrt(a0 * a0 + a1 * a1);
- if (length > (Real)0)
- {
- direction0 = a0 * derU + a1 * derV;
- }
- else
- {
- // Umbilic (surface is locally sphere, any direction
- // principal).
- direction0 = derU;
- }
- }
- Normalize(direction0);
- // Second tangent is cross product of first tangent and normal.
- direction1 = Cross(direction0, normal);
- }
- private:
- std::shared_ptr<ParametricSurface<3, Real>> mSurface;
- };
- }
|