Phong-Rodrigues Extrinsic Vector-Field Processing (Version 1.15)

links executables examples compilation usage changes

This software supports vector-field processing using the extrinsically defined Phong-Rodrigues basis. Supported applications include computation of:
LINKS

EXECUTABLES

EXAMPLES (WITH SAMPLE DATA)
For testing purposes, the provided archive contains the "kitten" model with two tangent vector-field constraints, as well as two tangent vector-fields defined over the torus.
COMPILATION

USAGE
    Set-up
    The implementation is header-only.
    • To perform Phong-Rodrigues vector-field processing, you will need to include the file Include/SimplicialMeshProcessing.h, which defines the functionality within the MishaK::SimplicialMesh namespace.
    • Most of the functionality is defined by the class EmbeddedPhongMesh<2>.
    • To define a mesh object, call the constructor:
      EmbeddedPhongMesh<2>::EmbeddedPhongMesh( std::vector< MishaK::Point<double,3> > & vertices , std::vector< MishaK::Point<double,3> > & normals , std::vector< MishaK::SimplexIndex<2> > & triangles );
      The geometry is represented as an indexed mesh, with:
      • The (shared) vertices and normals described using std::vectors of type MishaK::Point<double,3>, which acts as an array of size 3 and additionally supports algebraic operations.
      • The triangle connectivity is described using an std::vector of type MishaK::SimplexIndex<2>, which acts as an array of size 3, giving the indices of the three corners of the triangle.
      Note that the constructed mesh captures the vertex, normal, and triangle information by reference, so geometry should not be deleted until after all the processing is completed.
    System Representation
    • System matrices are represented using Eigen's sparse-matrix Eigen::SparseMatrix<double> class and system vectors are represented using the Eigen::VectorXd class. For a triangle mesh with |V| vertices, the extrinsic representation of the vector-field has 3·|V| degrees of freedom, with the three Euclidean coordinates of the vector at vertex i encoded in entries 3·i, 3·i+1, and 3·i+2.
    • In practice, processing is done over tangent vector-fields, so that there are only two degrees of freedom per vertex. This can be realized by selecting a frame for each vertex, perpendicular to the vertex's normal, and describing the vertex's tangent vector with respect to the frame. To facilitate this, the class defines the member function:
      Eigen::SparseMatrix<double> EmbeddedPhongMesh<2>::tangentProlongation( void )
      which returns a sparse 3·|V|×2·|V| matrix mapping a representation of tangent vectors in terms of two degrees of freedom at a vertex (with respect to a frame perpendicular to the normal) to the Euclidean coordinates of the vectors at the vertices. The frame is chosen to be orthonormal, so that if P is the matrix returned by the method, the matrix P.transpose()*P is the 3·|V|×3·|V| matrix describing the operation of projecting out the normal component. Thus, for example:
      • Given a symmetric 3·|V|×2·|V| matrix Q describing the energy of a vector-field expressed in terms Euclidean coordinates, the matrix representing the restriction of the energy in the frame coordinates is:
        P.transpose()*Q*P
      • Given a 2·|V|-dimensional vector v describing the tangent-vectors at the vertices, with respect to the frame, the vector representing the prolonged tangent-vectors in Euclidean coordinates is:
        P*v
      • Given a 3·|V|-dimensional vector d describing the dual of a vector-field with respect to the Euclidean coordinates (i.e. the integral of the vector-field against each of the 3·|V| Euclidean Phong-Rodrigues basis vector-fields), the vector representing the restriction of the dual in the frame coordinates is:
        P.transpose()*d
      • Finally, because the implementation defines the prolongation matrix P using an orthonormal frame, given a 3·|V|-dimensional vector v describing the tangent-vectors at the vertices in Euclidean coordinates the representation of the tangent-vectors in the frame coordinates is:
        P*v
    System Energies
    The system supports computing symmetric, positive (semi-)definite 3·|V|×3·|V| matrices representing different energies. All the functionalities are templated off of an unsigned int describing the number of quadrature samples to be used per triangle when computing integrals.
    • The mass matrix for extrinsic vector-fields can be obtained by invoking the member function:
      Eigen::SparseMatrix<double> EmbeddedPhongMesh<2>::template massMatrix<QuadratureSamples>( void )
    • The stiffness matrix for extrinsic vector-fields, with respect to the connection energy, can be obtained by invoking the member function:
      Eigen::SparseMatrix<double> EmbeddedPhongMesh<2>::template stiffnessMatrix<QuadratureSamples>( void )
    • The stiffness matrix for extrinsic vector-fields, with respect to a particular component (or combination of components) of the covariant derivative, can be obtained by invoking the member function:
      Eigen::SparseMatrix<double> EmbeddedPhongMesh<2>::template stiffnessMatrix<QuadratureSamples,Component>( void )
      with Component an unsigned int flag indicating whether the divergence, curl, and/or anti-holomorphic components should be used in defining the stiffness. Possible values for Component include:
      • SimplexProcessing::StiffnessComponent::Divergence()
      • SimplexProcessing::StiffnessComponent::Curl()
      • SimplexProcessing::StiffnessComponent::AntiHolomorphic()
      • SimplexProcessing::StiffnessComponent::Connection()
      • SimplexProcessing::StiffnessComponent::Holomorphic()
      • SimplexProcessing::StiffnessComponent::Hodge()
      • SimplexProcessing::StiffnessComponent::Killing()
    Vector-Field Representation
    While a vector-field can be represented as an std::vector of MishaK::Point<double,3> objects describing the Euclidean coordinates of the (tangent) vector-field values at the vertices, the code also supports a more abstract functional representation. In particular, if an object VectorField satisfies the concept:
    concept HasMeshVectorField = requires( const VectorField f , size_t idx , MishaK::Point<double,2> p ) { { f[idx](p) } -> std::same_as< MishaK::Point<double,3> > };
    behaving as an array of functions on triangles (with triangles indexed by idx and triangle positions described by p) that return the Euclidan representation of a vector, then the dual representation of the vector-field represented by such an object as a vector of size 3·|V|, obtained by integrating against the extrinsic Phong-Rodrigues basis vector-fields, can be obtained by invoking the member function:
    Eigen::VectorXd EmbeddedPhongMesh<2>::template massVector<QuadratureSamples>( VectorField && VF )
    Example: Computing the Killing Vector-Field
    Given vertex positions, vertex normals, and triangle incidence, the (most) Killing vector-field can be obtained as follows:
    • Construct an EmbeddedPhongMesh<2> object,
    • Compute the extrinsic mass and Killing stiffness energy matrices,
    • Restrict those to tangent energy matrices,
    • Solve the generalized eigen-value problem to get the tangent vector-field with smallest Killing energy, and
    • Prolong to obtain the Euclidean representation of the vector-field at each vertex.
    Assuming three quadrature samples per triangle, this can be implemented as follows:
    static const unsigned int QuadratureSamples = 3;
    
    // Set the triangle mesh information
    std::vector< MishaK::Point<double,3> > vertices , normals;
    std::vector< MishaK::SimplexIndex<2> > triangles;
    // ...
    
    // Initialize the mesh
    MishaK::SimplicialMesh::EmbeddedPhongMesh<2> mesh( vertices , normals , triangles );
    
    // Compute the extrinsic/Euclidean system matrices
    Eigen::SparseMatrix<double> mass_euclidean = mesh.template massMatrix< QuadratureSamples >();
    Eigen::SparseMatrix<double> stiffness_euclidean = mesh.template stiffnessMatrix< QuadratureSamples , MishaK::SimplexProcessing::StiffnessComponent::Killing() >();
    
    // Compute the prolongation matrix from tangent to Euclidean coordinates
    Eigen::SparseMatrix<double> prolongation = mesh.tangentProlongation();
    
    // Compute the tangent system matrices
    Eigen::SparseMatrix<double> mass_tangent = prolongation.transpose() * mass_euclidean * prolongation;
    Eigen::SparseMatrix<double> stiffness_tangent = prolongation.transpose() * stiffness_euclidean * prolongation;
    
    // Compute the smallest generalized eigen-vector of the pair of systems {stiffness_tangent,mass_tangent}
    Eigen::VectorXd killing_tangent;
    // ...
    
    // Compute the corresponding extrinsic/Euclidean vector-field representation
    Eigen::VectorXd killing_euclidean = prolongation * killing_tangent;
    

HISTORY OF CHANGES
Version 1.00: Version 1.10: Version 1.15:

HOME