かなり前の記事「放物運動を微少時間刻みで考えてみる」で作成したコードの要素をクラス化してみようと思う。要素数が増えたときの対応や、違う現象を表現しようとするときにクラス化しているのと、していないのとでは、効率がかなり違う気がする。
クラスに含めるパラメータは
- 現在の位置
- 1ステップ前の位置
- 現在の速度
- 1ステップ前の速度
ひとまず、これらをひとまとめとして扱えるようにする。
- Element.hpp
#ifndef __ELEMENT_HPP__ #define __ELEMENT_HPP__ namespace DECS{ enum RELATIVE_STEP{ CURRENT, PREVIOUS }; enum AXIS{ X, Y }; class Element{ private: double curPos_[2]; double prePos_[2]; double curVel_[2]; double preVel_[2]; protected: public: Element(); Element(double x, double y, double vx, double vy); ~Element(); double getPos(RELATIVE_STEP rs, AXIS axis) const; double getVel(RELATIVE_STEP rs, AXIS axis) const; void setPos(RELATIVE_STEP rs, AXIS axis, double value); void setVel(RELATIVE_STEP rs, AXIS axis, double value); }; } #endif // __ELEMENT_HPP__
- Element.cpp
#include "Element.hpp" namespace DECS{ Element::Element() { this->curPos_[0] = 0.0; this->curPos_[1] = 0.0; this->prePos_[0] = 0.0; this->prePos_[1] = 0.0; this->curVel_[0] = 0.0; this->curVel_[1] = 0.0; this->preVel_[0] = 0.0; this->preVel_[1] = 0.0; } Element::Element(double x, double y, double vx, double vy) { this->curPos_[0] = x; this->curPos_[1] = y; this->prePos_[0] = x; this->prePos_[1] = y; this->curVel_[0] = 0.0; this->curVel_[1] = 0.0; this->preVel_[0] = vx; this->preVel_[1] = vy; } Element::~Element() { } double Element::getPos(RELATIVE_STEP rs, AXIS axis) const { switch(rs){ case CURRENT: return this->curPos_[axis]; case PREVIOUS: return this->prePos_[axis]; default: return 0.0; } } double Element::getVel(RELATIVE_STEP rs, AXIS axis) const { switch(rs){ case CURRENT: return this->curVel_[axis]; case PREVIOUS: return this->preVel_[axis]; default: return 0.0; } } void Element::setPos(RELATIVE_STEP rs, AXIS axis, double value) { switch(rs){ case CURRENT: this->curPos_[axis] = value; break; case PREVIOUS: this->prePos_[axis] = value; break; } } void Element::setVel(RELATIVE_STEP rs, AXIS axis, double value) { switch(rs){ case CURRENT: this->curVel_[axis] = value; break; case PREVIOUS: this->preVel_[axis] = value; break; } } }
アクセッサでは列挙RELATIVE_STEPを使用して、相対的なステップを指定できるようにしたが、1行の記述が長くなってしまうので、素直に相対ステップごとにアクセッサを用意した方がいいような気もする。
このクラスを使ってメイン関数を書き直すと次のようになる。
#include <fstream> #include <cstdlib> #include "Element.hpp" using namespace std; int main(int argc, char* argv[]) { DECS::Element element(0.0, 400.0, 30.0, 0.0); double dt = 0.0001; // 1ステップの微少時間 double a[2] = {0.0, -9.81}; // 加速度 int totalStep = 100000; // 総ステップ数 double p[2][200]; // 保存用座標 ofstream outf("./output.txt"); //結果出力ファイル int count = 0; p[0][0] = element.getPos(DECS::CURRENT, DECS::X); p[1][0] = element.getPos(DECS::CURRENT, DECS::Y); for(int i = 1; i < totalStep; i++){ element.setVel(DECS::CURRENT, DECS::X, element.getVel(DECS::PREVIOUS, DECS::X) + a[0] * dt); element.setVel(DECS::CURRENT, DECS::Y, element.getVel(DECS::PREVIOUS, DECS::Y) + a[1] * dt); element.setPos(DECS::CURRENT, DECS::X, element.getPos(DECS::PREVIOUS, DECS::X) + (element.getVel(DECS::CURRENT, DECS::X) + element.getVel(DECS::PREVIOUS, DECS::X)) * dt / 2); element.setPos(DECS::CURRENT, DECS::Y, element.getPos(DECS::PREVIOUS, DECS::Y) + (element.getVel(DECS::CURRENT, DECS::Y) + element.getVel(DECS::PREVIOUS, DECS::Y)) * dt / 2); count++; if(count == 500){ count = 0; p[0][i/500] = element.getPos(DECS::CURRENT, DECS::X); p[1][i/500] = element.getPos(DECS::CURRENT, DECS::Y); } element.setPos(DECS::PREVIOUS, DECS::X, element.getPos(DECS::CURRENT, DECS::X)); element.setPos(DECS::PREVIOUS, DECS::Y, element.getPos(DECS::CURRENT, DECS::Y)); element.setVel(DECS::PREVIOUS, DECS::X, element.getVel(DECS::CURRENT, DECS::X)); element.setVel(DECS::PREVIOUS, DECS::Y, element.getVel(DECS::CURRENT, DECS::Y)); } for(int i = 0; i < 200; i++){ outf << p[0][i] << endl; outf << p[1][i] << endl; } return EXIT_SUCCESS; }
やはり、パラメータを使って値を更新していく記述がゴチャゴチャしてしまうので、なにかシンプルになるような仕様にした方がいいように思えてきた。また、現時点の状態では表現できないことが多すぎて、全然使い物にならない。とりあえずやってみ たレベルなので、ちょっと手を入れていこうと思う。
結果は「放物運動を微少時間刻みで考えてみる」と同じようになる。
This could not possibly have been more hlepufl!
投稿情報: Gregoria | 2012/06/21 11:57