MOAB: Mesh Oriented datABase  (version 5.4.1)
MBMesquite::DeformingCurveSmoother Class Reference

Utility to do curve smoothing. More...

#include <DeformingDomainWrapper.hpp>

+ Collaboration diagram for MBMesquite::DeformingCurveSmoother:

Public Types

enum  Scheme { EQUAL, PROPORTIONAL }
 Mesh characteristics to attempt to preserve. More...

Public Member Functions

MESQUITE_EXPORT DeformingCurveSmoother ()
MESQUITE_EXPORT ~DeformingCurveSmoother ()
void set_initial_fraction_tag (const std::string &tag_name)
 Specify tag used to get/set cached initial mesh data.
std::string get_initial_fraction_tag () const
 Get tag used to store initial mesh characteristics.
void set_mesh_characteristic (Scheme t)
 Specify which mesh characteristics to preserve.
Scheme get_mesh_characteristic () const
MESQUITE_EXPORT void store_initial_mesh (Mesh *mesh_instance, const Mesh::VertexHandle *vertex_array, int vertex_array_length, CurveDomain *geometry, MsqError &err)
 Record relative edge length from initial mesh.
MESQUITE_EXPORT void smooth_curve (Mesh *mesh_instance, const Mesh::VertexHandle *vertex_array, int vertex_array_length, CurveDomain *geometry, Scheme type, MsqError &err)
 Redistribute vertices along a curve or 1D domain.

Private Member Functions

TagHandle get_tag (Mesh *mesh, MsqError &err)

Private Attributes

Scheme metricType
std::string initFractTag
 name of tag used to store arc length fractions

Detailed Description

Utility to do curve smoothing.

This class implements a simple utility to redistribute vertices on a curve (1D domain). It can operate in two modes. If the charactristic is EQUAL, it will redistribute the vertices such that the arc length between each vertex is equal. In the PROPORTIONAL mode the application must call store_initial_mesh for each curve before the domain is deformed. store_initial_mesh will record the fractional arc length between vertices so that smooth_curve can redistribute the vertices such that the space between the vertices is the same fractional arc length.

Definition at line 250 of file DeformingDomainWrapper.hpp.


Member Enumeration Documentation

Mesh characteristics to attempt to preserve.

Enumerator:
EQUAL 

space curve vertices equally

PROPORTIONAL 

preserve relative spacing from initial mesh

Definition at line 260 of file DeformingDomainWrapper.hpp.

    {
        EQUAL,        //!< space curve vertices equally
        PROPORTIONAL  //!< preserve relative spacing from initial mesh
    };

Constructor & Destructor Documentation


Member Function Documentation

Get tag used to store initial mesh characteristics.

Return the tag handle passed to set_initial_fraction_tag or if store_initial_mesh, the the tag created by in.

Definition at line 285 of file DeformingDomainWrapper.hpp.

References initFractTag.

    {
        return initFractTag;
    }

Definition at line 296 of file DeformingDomainWrapper.hpp.

References metricType.

    {
        return metricType;
    }

Definition at line 289 of file DeformingDomainWrapper.cpp.

References MBMesquite::Mesh::DOUBLE, initFractTag, MBMesquite::MsqError::INVALID_MESH, MSQ_ERRZERO, MSQ_SETERR, MBMesquite::Mesh::tag_get(), and MBMesquite::Mesh::tag_properties().

Referenced by smooth_curve(), and store_initial_mesh().

{
    TagHandle h = mesh->tag_get( initFractTag, err );
    MSQ_ERRZERO( err );
    std::string name;
    Mesh::TagType type;
    unsigned len;
    mesh->tag_properties( h, name, type, len, err );
    MSQ_ERRZERO( err );
    if( type != Mesh::DOUBLE || len != 1 )
    {
        MSQ_SETERR( err )
        ( MsqError::INVALID_MESH, "Tag \"%s\" exists but is not 1 double value per vertex.", initFractTag.c_str() );
    }
    return h;
}
void MBMesquite::DeformingCurveSmoother::set_initial_fraction_tag ( const std::string &  tag_name) [inline]

Specify tag used to get/set cached initial mesh data.

This optimizer uses the initial mesh (prior to deformation of the domain) as a reference when smoothing the mesh on the deformed domain. This function can be used to store initial mesh data. If the tag already exists then t must have a type of DOUBLE and a size of one value. the tag used to store those initial coordinates. It must have a type of DOUBLE and a size of one value.

Definition at line 275 of file DeformingDomainWrapper.hpp.

References initFractTag.

    {
        initFractTag = tag_name;
    }

Specify which mesh characteristics to preserve.

Definition at line 291 of file DeformingDomainWrapper.hpp.

References metricType, and t.

    {
        metricType = t;
    }
void MBMesquite::DeformingCurveSmoother::smooth_curve ( Mesh mesh_instance,
const Mesh::VertexHandle vertex_array,
int  vertex_array_length,
CurveDomain geometry,
Scheme  type,
MsqError err 
)

Redistribute vertices along a curve or 1D domain.

Smooth the curve mesh by redistributing the vertices using one of the schemes defined in Scheme.

Parameters:
mesh_instanceThis mesh instance need not contain only the vertices of this curve, but if using the PROPORTIONAL scheme it must have the tag data defined by the earlier call to store_initial_mesh.
vertex_arrayThe array of handles corresponding to vertices on the curve and its end points. Vertices must be ordered and in the forward direction along the curve, where the forward direction is whichever direction the CurveDomain instance considers a positive arc length for the position_from_length call. The array must also contain both the start and end vertex for the curve, and if the curve is closed, the single start/end vertex must occur at both the start and end of the list. The first and last vertex in the array will *not* be moved. If the geometric points (0D domains) they are constrained to lie on have moved, the caller must move them to those new locations before calling this function.
vertex_array_lengthThe number of handles in vertex_array.
geometryThe curve or 1D domain geometry.
typeThe scheme to use. If using PROPORTIONAL, then store_initial_mesh must be called for the same vertices and mesh instance before any deformation.

Definition at line 226 of file DeformingDomainWrapper.cpp.

References MBMesquite::CurveDomain::arc_length(), EQUAL, get_tag(), MBMesquite::MsqError::INVALID_MESH, MBMesquite::length_squared(), metricType, MSQ_ERRRTN, MSQ_SETERR, MBMesquite::CurveDomain::position_from_length(), moab::sum(), MBMesquite::Mesh::tag_get_vertex_data(), MBMesquite::Vector3D::to_array(), MBMesquite::Mesh::vertex_set_coordinates(), and MBMesquite::Mesh::vertices_get_coordinates().

Referenced by main().

{
    if( nverts < 2 )
    {
        MSQ_SETERR( err )
        ( "Invalid curve mesh.  Need at least two end vertices.", MsqError::INVALID_MESH );
        return;
    }

    // Verify that end vertices are on curve.  We cannot snap end vertices
    // to ends of curve for application because we don't know where the
    // ends of the curve are.
    MsqVertex coords[2], coords2;
    Mesh::VertexHandle ends[2] = { verts[0], verts[nverts - 1] };
    for( int i = 0; i < 2; ++i )
    {
        mesh->vertices_get_coordinates( ends + i, coords + i, 1, err );MSQ_ERRRTN( err );
        geom->position_from_length( coords[i].to_array(), 0, coords2.to_array(), err );MSQ_ERRRTN( err );
        if( ( coords[i] - coords2 ).length_squared() > DBL_EPSILON )
        {
            MSQ_SETERR( err )
            ( "Curve end vertices do not line on curve.  Move ends to curve end points first", MsqError::INVALID_MESH );
            return;
        }
    }
    const double total = geom->arc_length( coords[0].to_array(), coords[1].to_array(), err );MSQ_ERRRTN( err );

    std::vector< double > vals( nverts - 1 );
    if( metricType == EQUAL )
    {
        std::fill( vals.begin(), vals.end(), 1.0 / ( nverts - 1 ) );
        // fracsum = 1.0;
    }
    else
    {  // metricType == PROPORTIONAL
        TagHandle tag = get_tag( mesh, err );MSQ_ERRRTN( err );
        mesh->tag_get_vertex_data( tag, nverts - 2, verts + 1, &vals[0], err );MSQ_ERRRTN( err );
        double sum = std::accumulate( vals.begin(), vals.end() - 1, 0.0 );
        if( 1.0 - sum > 1e-8 )
            vals.back() = 1.0 - sum;
        else
        {
            vals.back() = *std::min_element( vals.begin(), vals.end() - 1 );
            sum += vals.back();
            for( size_t i = 0; i < vals.size(); ++i )
                vals[i] /= sum;
        }
    }

    double frac_sum = 0.0;
    for( int i = 1; i < nverts - 1; ++i )
    {
        frac_sum += vals[i - 1];
        geom->position_from_length( coords[0].to_array(), total * frac_sum, coords[1].to_array(), err );MSQ_ERRRTN( err );
        mesh->vertex_set_coordinates( verts[i], coords[1], err );MSQ_ERRRTN( err );
    }
}
void MBMesquite::DeformingCurveSmoother::store_initial_mesh ( Mesh mesh_instance,
const Mesh::VertexHandle vertex_array,
int  vertex_array_length,
CurveDomain geometry,
MsqError err 
)

Record relative edge length from initial mesh.

Record the necessary characteristics of the initial mesh required for a later all to smooth_curve using the PROPORTIONAL mode.

Parameters:
mesh_instanceThis mesh instance need not contain only the vertices of this curve, but it must preserve tag data on the curve vertices for use in smooth_curve.
vertex_arrayThe array of handles corresponding to vertices on the curve and its end points. Vertices must be ordered and in the forward direction along the curve, where the forward direction is whichever direction the CurveDomain instance considers a positive arc length for the position_from_length call. The array must also contain both the start and end vertex for the curve, and if the curve is closed, the single start/end vertex must occur at both the start and end of the list.
vertex_array_lengthThe number of handles in vertex_array.
geometryThe curve or 1D domain geometry.

Definition at line 180 of file DeformingDomainWrapper.cpp.

References MBMesquite::MsqError::clear(), MBMesquite::Mesh::DOUBLE, MBMesquite::MsqError::error_code(), get_tag(), initFractTag, MBMesquite::MsqError::INVALID_MESH, MBMesquite::length(), MSQ_ERRRTN, MSQ_SETERR, MBMesquite::MsqError::TAG_ALREADY_EXISTS, MBMesquite::Mesh::tag_create(), MBMesquite::Mesh::tag_set_vertex_data(), and MBMesquite::Mesh::vertices_get_coordinates().

Referenced by main().

{
    if( nverts < 2 )
    {
        MSQ_SETERR( err )
        ( "Invalid curve mesh.  Need at least two end vertices.", MsqError::INVALID_MESH );
        return;
    }

    // get edge lengths
    std::vector< double > vals( nverts - 1 );
    MsqVertex coords[2];
    int prev = 0;
    mesh->vertices_get_coordinates( verts, coords + prev, 1, err );MSQ_ERRRTN( err );
    for( int i = 1; i < nverts; ++i )
    {
        int next = 1 - prev;
        mesh->vertices_get_coordinates( verts + i, coords + next, 1, err );MSQ_ERRRTN( err );
        vals[i - 1] = ( coords[0] - coords[1] ).length();
        prev        = next;
    }

    // convert to length fraction before each iterior vertex
    // (sum of lengths of adjacent edges over total curve length)
    const double total = std::accumulate( vals.begin(), vals.end(), 0.0 );
    for( int i = 1; i < nverts - 1; ++i )
        vals[i - 1] = vals[i - 1] / total;
    vals.resize( nverts - 2 );

    // create tag
    TagHandle tag = mesh->tag_create( initFractTag, Mesh::DOUBLE, 1, 0, err );
    if( err.error_code() == MsqError::TAG_ALREADY_EXISTS )
    {
        err.clear();
        tag = get_tag( mesh, err );
    }
    MSQ_ERRRTN( err );

    // store tag data on interior vertices
    mesh->tag_set_vertex_data( tag, nverts - 2, verts + 1, &vals[0], err );MSQ_ERRRTN( err );
}

Member Data Documentation

name of tag used to store arc length fractions

Definition at line 365 of file DeformingDomainWrapper.hpp.

Referenced by get_initial_fraction_tag(), get_tag(), set_initial_fraction_tag(), and store_initial_mesh().

List of all members.


The documentation for this class was generated from the following files:
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines