理解したくない.とりあえず使いたいからサンプルよこせというむけに, サンプルクラスを提供しましょう.
- データを書き出すフォルダーを指定してインスタンスを作成
- 等分割直交格子領域を好きなだけ追加
- そこに格子点データを好きなだけ追加
- ファイル名を指定して保存すると,XML-VTKで保存する
代物です.
使い方としては
#include "vtk_image.hpp" ... VTK_IMAGE Writer("fucking_vtk"); //ホームフォルダ$HOME/fucking_vtkフォルダーに出力 Writer.Parameter=&あんたのパラメータ; //あとで値設定関数にパラメータを与える場合,こうする ... //領域を追加していく.いくつ足しても良い double x_r[3]={-5.,+5.,0.01}; // X座標の範囲は[-5,5] 格子幅0.01 double y_r[3]={0.0,+5.,0.01}; // Y座標の範囲は[0,5] 格子幅0.01 // Z座標を定義しても良い. ここでは2D問題ということでZ格子点数が1 int num[3]={int(round((x_r[1]-x_r[0])/x_r[2])),int(round((y_r[1]-y_r[0])/y_r[2])),1}; Eigen::Vector3d ORG={x_r[0],y_r[0],0.}; Eigen::Vector3d DX={x_r[2],y_r[2],0.}; Eigen::Vector3i NX={num[0],num[1],1}; int myAssHole=Writer.AddImage(ORG,DX,NX); // 領域に整数の番号が与えられる ... //格子点データを追加していく {//座標を追加 std::vector<std::string> name = { "x_1", "x_2", "x_3"}; //成分数だけ名前を定義 Writer.AddPointData("x",name); //総称名,成分名で追加 Writer.SetPointData(myAssHole,"x",[](Eigen::Vector3d X,void* p){ return X.data(); //Eigenはdata()が配列へのポインターを与える }); // データ追加関数を与えて格子データをある領域に追加 //データ追加関数は, function(Eigen::Vector3d X,void* p)に固定である. X座標に応じて //値へのポインタを返すラムダ式を与える. ベクトルの場合, 配列へのポインタを返す. //pは,ここで与えたあんたのパラメータであるので必要なら使う. パラメータは単一の値でも良いし //複雑怪奇なクラスへのポインターでも良い. } {//別の関数も追加. ここではスカラー関数を追加してみる Writer.AddPointData("n"); Writer.SetPointData(myAssHole,"n",[](Eigen::Vector3d X,void* p){ auto& Motherfucker=*(あんたのパラメータクラス *) p; double th1=atan2(X[1],X[0]+0.5); double th2=atan2(X[1],X[0]-0.5); double n_val=Motherfucker.int_000(th1,th2);//あんたのクラスの計算は禁止されていない return &n_val; }); } ... Writer.Save("baka.vtm"); //フォルダーにVTMファイルが保存される
これを使うには, 次のコードをあなたのプロジェクトに(たとえば vtk_image.hpp とかの名前で)追加します.なお
- Eigen, Boost/FileSystemを使います.
- libvtkCommonCore, libvtkCommonDataModel, libvtkIOXMLを使います.
ので,ライブラリーの設定は必要です.
#ifndef vtk_image_hpp
#define vtk_image_hpp
#include <Eigen/Dense>
#include <boost/filesystem.hpp>
#include <vtkSmartPointer.h>
#include <vtkMultiBlockDataSet.h> //1ケースに多数の領域が含まれる場合,これが必要
#include <vtkXMLMultiBlockDataWriter.h> //多数の領域を一発で保存する
#include <vtkImageData.h> //等分割直方格子の領域を使います
#include <vtkDoubleArray.h> //セルや格子点に取り付ける物理量を定義します.
#include <vtkPointData.h> //格子点のデータ
class VTK_IMAGE
{
boost::filesystem::path folder;
vtkSmartPointer<vtkMultiBlockDataSet> multi;
vtkSmartPointer<vtkImageData> current_image;
vtkSmartPointer<vtkDataArray> current_array;
vtkSmartPointer<vtkDoubleArray> current_double;
int num_domain=0;
int current_components=1;
bool SelectPointData(int id,std::string name)
{
//指定領域を選択
try
{
current_image = vtkImageData::SafeDownCast(multi->GetBlock(id));
}
catch (std::exception& e)
{
std::cout << "No such imageだぴょーん[id= " << id << "]" << std::endl;
return false;
}
//指定関数を選択
try
{
for(int ifunc=0;ifunc<current_image->GetPointData()->GetNumberOfArrays();ifunc++)
{
current_array=current_image->GetPointData()->GetArray(ifunc);
current_components=current_array->GetNumberOfComponents();
if (current_array->GetName()==name)
{
current_double=vtkDoubleArray::SafeDownCast(current_array);
return true;
}
if (current_components==1) continue;
//うっかり成分名を指定した場合に助ける
for(int ic=0;ic<current_components;ic++)
if (current_array->GetComponentName(ic)==name) return true;
}
}
catch (std::exception& e)
{
std::cout << "No such componentだぴょーん[id= " << id << "]" << std::endl;
return false;
}
return false;
};
public:
void* Parameter;
VTK_IMAGE(std::string path):folder(path)
{//書き出しフォルダーを指定して初期化
boost::filesystem::path homedir=getenv("HOME");
if (!boost::filesystem::exists(homedir/folder))
boost::filesystem::create_directory(homedir/folder);
boost::filesystem::current_path(homedir/folder);
multi=vtkSmartPointer<vtkMultiBlockDataSet>::New();
}
int AddImage(Eigen::Vector3d origin,Eigen::Vector3d space,Eigen::Vector3i num)
{//領域を追加
current_image=vtkSmartPointer<vtkImageData>::New();
current_image->SetOrigin(origin.data()); //領域の原点
current_image->SetSpacing(space.data()); //X-Y-Z方向の格子の間隔
int imageExtent[6]={0,num[0],0,num[1],0,num[2]}; //領域の格子点数
current_image->SetExtent(imageExtent); //領域の原点
int id=num_domain++;
multi->SetBlock(id,current_image);
return id;
}
bool AddPointData(std::string name)
{//スカラー関数を追加
for(int id=0;id<multi->GetNumberOfBlocks();id++)
{
current_image = vtkImageData::SafeDownCast(multi->GetBlock(id));
auto function = vtkDoubleArray::New();
function->SetNumberOfComponents(1);
function->SetName(name.c_str());
function->SetNumberOfTuples(current_image->GetNumberOfPoints());
int ifunc=current_image->GetPointData()->AddArray(function);
}
return true;
}
bool AddPointData(std::string name,std::vector<std::string> names)
{//ベクトル関数を追加
for(int id=0;id<multi->GetNumberOfBlocks();id++)
{
current_image = vtkImageData::SafeDownCast(multi->GetBlock(id));
auto function = vtkDoubleArray::New();
function->SetNumberOfComponents(names.size());
function->SetName(name.c_str());
for(int ic=0;ic<names.size();ic++)
function->SetComponentName(ic, names[ic].c_str());
function->SetNumberOfTuples(current_image->GetNumberOfPoints());
int ifunc=current_image->GetPointData()->AddArray(function);
}
return true;
}
bool Save(std::string filename)
{//ファイル名を指定して書き出し
boost::filesystem::path file(filename);
auto writer=vtkSmartPointer<vtkXMLMultiBlockDataWriter>::New();
writer->SetFileName(file.c_str()); //掃除屋にファイル名を設定
writer->SetInputData(multi); //掃除屋にボディーを引き渡す
writer->Write(); //掃除を実行
}
bool SetPointData(int id,std::string name,double* (*f)(Eigen::Vector3d x,void* p))
{
if (!SelectPointData(id,name)) return false;
for(vtkIdType pId=0;pId<current_image->GetNumberOfPoints();pId++)
{
Eigen::Vector3d XCoord;
current_image->GetPoint(pId,XCoord.data());
auto* fval=(*f)(XCoord,Parameter);
if (current_components==1)
current_double->SetValue(pId,fval[0]);
else
for(int ic=0;ic<current_components;ic++)
current_double->SetComponent(pId,ic,fval[ic]);
}
};
};
#endif /* vtk_image_hpp */以上