From f3f0edffe5899070c9b597bf6ab67eb9d90c34b4 Mon Sep 17 00:00:00 2001 From: Jakub Melka Date: Tue, 17 Sep 2019 19:47:35 +0200 Subject: [PATCH] Tensor meshing, first part --- PdfForQtLib/sources/pdfpattern.cpp | 164 +++++++++++++++++++++++++++++ PdfForQtLib/sources/pdfpattern.h | 98 +++++++++++++++++ 2 files changed, 262 insertions(+) diff --git a/PdfForQtLib/sources/pdfpattern.cpp b/PdfForQtLib/sources/pdfpattern.cpp index d374ea2..2ac1bea 100644 --- a/PdfForQtLib/sources/pdfpattern.cpp +++ b/PdfForQtLib/sources/pdfpattern.cpp @@ -1678,6 +1678,170 @@ void PDFGouradTriangleShading::addSubdividedTriangles(const PDFMeshQualitySettin } } +QPointF PDFTensorPatch::getValue(PDFReal u, PDFReal v) const +{ + return getValue(u, v, 0, 0); +} + +QPointF PDFTensorPatch::getValue(PDFReal u, PDFReal v, int derivativeOrderU, int derivativeOrderV) const +{ + QPointF result; + + for (int i = 0; i < 3; ++i) + { + for (int j = 0; j < 3; ++j) + { + return m_P[i][j] * B(i, u, derivativeOrderU) * B(j, v, derivativeOrderV); + } + } + + return result; +} + +PDFReal PDFTensorPatch::getCurvature_u(PDFReal u, PDFReal v) const +{ + QPointF dSdu = getDerivative_u(u, v); + QPointF dSduu = getDerivative_uu(u, v); + + PDFReal squaredLengthOfdSdu = QPointF::dotProduct(dSdu, dSdu); + + if (qFuzzyIsNull(squaredLengthOfdSdu)) + { + // We assume, that curvature, due to zero length of the tangent vector, is also zero + return 0.0; + } + + // Well known formula, how to compute curvature of curve f(x): + // K = ( df/dx * df/dyy - df/dxx * df/dy ) / ( (df/dx)^2 + (df/dy)^2 ) ^ (3/2) + PDFReal curvature = std::fabs(dSdu.x() * dSduu.y() - dSdu.y() * dSduu.x()) / std::pow(squaredLengthOfdSdu, 1.5); + return curvature; +} + +PDFReal PDFTensorPatch::getCurvature_v(PDFReal u, PDFReal v) const +{ + QPointF dSdv = getDerivative_v(u, v); + QPointF dSdvv = getDerivative_vv(u, v); + + PDFReal squaredLengthOfdSdv = QPointF::dotProduct(dSdv, dSdv); + + if (qFuzzyIsNull(squaredLengthOfdSdv)) + { + // We assume, that curvature, due to zero length of the tangent vector, is also zero + return 0.0; + } + + // Well known formula, how to compute curvature of curve f(x): + // K = ( df/dx * df/dyy - df/dxx * df/dy ) / ( (df/dx)^2 + (df/dy)^2 ) ^ (3/2) + PDFReal curvature = std::fabs(dSdv.x() * dSdvv.y() - dSdv.y() * dSdvv.x()) / std::pow(squaredLengthOfdSdv, 1.5); + return curvature; +} + +constexpr PDFReal PDFTensorPatch::B(int index, PDFReal t, int derivativeOrder) +{ + switch (index) + { + case 0: + return B0(t, derivativeOrder); + + case 1: + return B1(t, derivativeOrder); + + case 2: + return B2(t, derivativeOrder); + + case 3: + return B3(t, derivativeOrder); + + default: + break; + } + + return std::numeric_limits::signaling_NaN(); +} + +constexpr PDFReal PDFTensorPatch::B0(PDFReal t, int derivative) +{ + switch (derivative) + { + case 0: + return pow3(1.0 - t); + + case 1: + return -3.0 * pow2(1.0 - t); + + case 2: + return 6.0 * (1.0 - t); + + case 3: + return -6.0; + + default: + break; + } + + return std::numeric_limits::signaling_NaN(); +} + +constexpr PDFReal PDFTensorPatch::B1(PDFReal t, int derivative) +{ + switch (derivative) + { + case 0: + return 3.0 * t * pow2(1.0 - t); + + case 1: + return 9.0 * pow2(t) - 12.0 * t + 3.0; + + case 2: + return 18.0 * t - 12.0; + + case 3: + return 18.0; + } + + return std::numeric_limits::signaling_NaN(); +} + +constexpr PDFReal PDFTensorPatch::B2(PDFReal t, int derivative) +{ + switch (derivative) + { + case 0: + return 3.0 * pow2(t) * (1.0 - t); + + case 1: + return -9.0 * pow2(t) + 6.0 * t; + + case 2: + return -18.0 * t + 6.0; + + case 3: + return -18.0; + } + + return std::numeric_limits::signaling_NaN(); +} + +constexpr PDFReal PDFTensorPatch::B3(PDFReal t, int derivative) +{ + switch (derivative) + { + case 0: + return pow3(t); + + case 1: + return 3.0 * pow2(t); + + case 2: + return 6.0 * t; + + case 3: + return 6.0; + } + + return std::numeric_limits::signaling_NaN(); +} + // TODO: Apply graphic state of the pattern // TODO: Implement settings of meshing in the settings dialog diff --git a/PdfForQtLib/sources/pdfpattern.h b/PdfForQtLib/sources/pdfpattern.h index 07bc614..425311d 100644 --- a/PdfForQtLib/sources/pdfpattern.h +++ b/PdfForQtLib/sources/pdfpattern.h @@ -370,6 +370,104 @@ private: PDFInteger m_verticesPerRow = 0; }; +class PDFTensorPatch +{ +public: + using PointMatrix = std::array, 4>; + + explicit inline PDFTensorPatch(PointMatrix P) : m_P(P) { } + + /// Calculates value at point in the patch. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + QPointF getValue(PDFReal u, PDFReal v) const; + + /// Calculates value at point in the patch, possibly derivation, if derivation + /// variables are positive. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + /// \param derivativeOrderU Derivation order in direction u (0 means no derivation) + /// \param derivativeOrderV Derivation order in direction v (0 means no derivation) + QPointF getValue(PDFReal u, PDFReal v, int derivativeOrderU, int derivativeOrderV) const; + + /// Calculates first derivate in the surface, in the direction of variable u. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + QPointF getDerivative_u(PDFReal u, PDFReal v) const { return getValue(u, v, 1, 0); } + + /// Calculates second derivate in the surface, in the direction of variable u. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + QPointF getDerivative_uu(PDFReal u, PDFReal v) const { return getValue(u, v, 2, 0); } + + /// Calculates first derivate in the surface, in the direction of variable v. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + QPointF getDerivative_v(PDFReal u, PDFReal v) const { return getValue(u, v, 0, 1); } + + /// Calculates second derivate in the surface, in the direction of variable v. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + QPointF getDerivative_vv(PDFReal u, PDFReal v) const { return getValue(u, v, 0, 2); } + + /// Calculates curvature of the given point in the surface, in the direction of u. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + PDFReal getCurvature_u(PDFReal u, PDFReal v) const; + + /// Calculates curvature of the given point in the surface, in the direction of v. + /// \param u Horizontal coordinate of the patch, must be in range [0, 1] + /// \param v Vertical coordinate of the patch, must be in range [0, 1] + PDFReal getCurvature_v(PDFReal u, PDFReal v) const; + +private: + /// Computes Bernstein polynomial B0, B1, B2, B3, for parameter t. + /// If \p derivative is zero, then it evaluates polynomial's value, + /// otherwise it computes value of the derivation of Bx, up to degree 3 + /// derivation. + /// \param index Index of polynomial, from 0 to 3 (B0, B1, B2, B3) + /// \param t Parameter of polynomial function + /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation) + static constexpr PDFReal B(int index, PDFReal t, int derivativeOrder); + + /// Computes Bernstein polynomial B0 for parameter t. + /// If \p derivative is zero, then it evaluates polynomial's value, + /// otherwise it computes value of the derivation of B0, up to degree 3 + /// derivation. + /// \param t Parameter of polynomial function + /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation) + static constexpr PDFReal B0(PDFReal t, int derivative); + + /// Computes Bernstein polynomial B1 for parameter t. + /// If \p derivative is zero, then it evaluates polynomial's value, + /// otherwise it computes value of the derivation of B1, up to degree 3 + /// derivation. + /// \param t Parameter of polynomial function + /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation) + static constexpr PDFReal B1(PDFReal t, int derivative); + + /// Computes Bernstein polynomial B2 for parameter t. + /// If \p derivative is zero, then it evaluates polynomial's value, + /// otherwise it computes value of the derivation of B2, up to degree 3 + /// derivation. + /// \param t Parameter of polynomial function + /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation) + static constexpr PDFReal B2(PDFReal t, int derivative); + + /// Computes Bernstein polynomial B3 for parameter t. + /// If \p derivative is zero, then it evaluates polynomial's value, + /// otherwise it computes value of the derivation of B3, up to degree 3 + /// derivation. + /// \param t Parameter of polynomial function + /// \param derivativeOrder Derivative order (0 - value, 1 - first derivation, 2 - second derivation, 3 - third derivation) + static constexpr PDFReal B3(PDFReal t, int derivative); + + static constexpr PDFReal pow2(PDFReal x) { return x * x; } + static constexpr PDFReal pow3(PDFReal x) { return x * x * x; } + + PointMatrix m_P; +}; + } // namespace pdf #endif // PDFPATTERN_H