1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
#include "MeshTransform.hpp"
#include "MeshImpl.hpp"
#include "CLArgs.hpp"
#include "MsqError.hpp"

#include <iostream>

using namespace MBMesquite;

const char ROTATE_FLAG    = 'r';
const char SCALE_FLAG     = 's';
const char TRANSLATE_FLAG = 't';

class RotateArg : public CLArgs::DoubleListArgI
{
  private:
    MeshTransform* mTransform;

  public:
    RotateArg( MeshTransform* xform ) : mTransform( xform ) {}
    bool value( const std::vector< double >& vals );
};
class ScaleArg : public CLArgs::DoubleListArgI
{
  private:
    MeshTransform* mTransform;

  public:
    ScaleArg( MeshTransform* xform ) : mTransform( xform ) {}
    bool value( const std::vector< double >& vals );
};
class TranslateArg : public CLArgs::DoubleListArgI
{
  private:
    MeshTransform* mTransform;

  public:
    TranslateArg( MeshTransform* xform ) : mTransform( xform ) {}
    bool value( const std::vector< double >& vals );
};
bool RotateArg::value( const std::vector< double >& vals )
{
    mTransform->add_rotation( Vector3D( vals[1], vals[2], vals[3] ), vals[0] * M_PI / 180 );
    return true;
}
bool ScaleArg::value( const std::vector< double >& vals )
{
    for( unsigned i = 0; i < vals.size(); ++i )
        if( vals[i] <= 0 ) return false;
    if( vals.size() == 1 )
        mTransform->add_scale( vals[0] );
    else
        mTransform->add_scale( Vector3D( vals[0], vals[1], vals[2] ) );
    return true;
}
bool TranslateArg::value( const std::vector< double >& vals )
{
    mTransform->add_translation( Vector3D( vals[0], vals[1], vals[2] ) );
    return true;
}

int main( int argc, char* argv[] )
{
    MeshTransform xform;
    RotateArg rotate_arg( &xform );
    ScaleArg scale_arg( &xform );
    TranslateArg translate_arg( &xform );
    CLArgs::ToggleArg freeonly, skin;

    CLArgs args( "vtkxform", "Transform a mesh",
                 "Apply one or more transformations to vertex coordinates "
                 "in a mesh read from a VTK file." );

    const char* ROTATE_VALS[] = { "a", "i", "j", "k" };
    args.double_list_flag( ROTATE_FLAG, "Specify a rotation as an angle in degrees counter-clockwise about a vector",
                           &rotate_arg );
    args.limit_list_flag( ROTATE_FLAG, 4, ROTATE_VALS );

    const char* SCALE_VALS[] = { "s", "sx", "sy", "sz" };
    args.double_list_flag( SCALE_FLAG, "Specify factor(s) by which to scale mesh about origin", &scale_arg );
    args.limit_list_flag( SCALE_FLAG, 1, SCALE_VALS );
    args.limit_list_flag( SCALE_FLAG, 3, SCALE_VALS + 1 );

    const char* TRANSLATE_VALS[] = { "dx", "dy", "dz" };
    args.double_list_flag( TRANSLATE_FLAG, "Specify translation of vertex coordinates.", &translate_arg );
    args.limit_list_flag( TRANSLATE_FLAG, 3, TRANSLATE_VALS );

    args.toggle_flag( 'f', "Do not move fixed vertices.", &freeonly );
    args.toggle_flag( 'k', "Mark boundary vertices as fixed", &skin );

    args.add_required_arg( "input_file" );
    args.add_required_arg( "output_file" );

    std::vector< std::string > files;
    if( !args.parse_options( argc, argv, files, std::cerr ) )
    {
        args.print_usage( std::cerr );
        exit( 1 );
    }
    std::string input_file  = files[0];
    std::string output_file = files[1];

    MeshImpl mesh;
    MsqError err;
    mesh.read_vtk( input_file.c_str(), err );
    if( err )
    {
        std::cerr << err << std::endl << "Failed to read file: " << input_file << std::endl;
        return 1;
    }

    if( skin.value() )
    {
        mesh.mark_skin_fixed( err, false );
        if( err )
        {
            std::cerr << err << std::endl << "Failed to skin mesh from file: " << input_file << std::endl;
            return 1;
        }
    }

    xform.skip_fixed_vertices( freeonly.value() );
    MeshDomainAssoc mesh_and_domain = MeshDomainAssoc( &mesh, 0 );
    xform.loop_over_mesh( &mesh_and_domain, 0, err );
    if( err )
    {
        std::cerr << err << std::endl;
        return 2;
    }

    mesh.write_vtk( output_file.c_str(), err );
    if( err )
    {
        std::cerr << err << std::endl << "Failed to write file: " << output_file << std::endl;
        return 1;
    }

    return 0;
}