MOAB: Mesh Oriented datABase
(version 5.4.1)
|
Utility to do curve smoothing. More...
#include <DeformingDomainWrapper.hpp>
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 |
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.
Mesh characteristics to attempt to preserve.
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 };
Definition at line 174 of file DeformingDomainWrapper.cpp.
: metricType( DEFAULT_CURVE_TYPE ), initFractTag( DEFAULT_CURVE_TAG ) { }
Definition at line 178 of file DeformingDomainWrapper.cpp.
{}
std::string MBMesquite::DeformingCurveSmoother::get_initial_fraction_tag | ( | ) | const [inline] |
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; }
Scheme MBMesquite::DeformingCurveSmoother::get_mesh_characteristic | ( | ) | const [inline] |
Definition at line 296 of file DeformingDomainWrapper.hpp.
References metricType.
{ return metricType; }
TagHandle MBMesquite::DeformingCurveSmoother::get_tag | ( | Mesh * | mesh, |
MsqError & | err | ||
) | [private] |
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; }
void MBMesquite::DeformingCurveSmoother::set_mesh_characteristic | ( | Scheme | t | ) | [inline] |
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
.
mesh_instance | This 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_array | The 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_length | The number of handles in vertex_array . |
geometry | The curve or 1D domain geometry. |
type | The 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.
mesh_instance | This 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_array | The 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_length | The number of handles in vertex_array . |
geometry | The 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 ); }
std::string MBMesquite::DeformingCurveSmoother::initFractTag [private] |
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().
Definition at line 364 of file DeformingDomainWrapper.hpp.
Referenced by get_mesh_characteristic(), set_mesh_characteristic(), and smooth_curve().