#if !defined(__VECTORN_H) #define __VECTORN_H #include //プリコンパイルヘッダが作成できないメッセージを抑制する #pragma option -w-pch //------------------- /* ★警告 すべてのモジュールとその相互関係が試験できているわけではない。 ★c:\src\commmon\test\vecmath を試験ベンチとすべし 改造をしたら、すくなくともその行の近傍に改造をした日時記述を入れておかないと 外への悪影響があるときに発見しにくいよ。 (C)Mathematical Assist Design Lab. (C)数理設計研究所 Hal.T 1986.1 基本設計 関数タイプ 1996/1/1 ANSI対応 クラステンプレート型 1998/11/20 Hal.T 全体的な整備とANSI2への対応 1999/10/5 Hal.T ラジアン、度のクラス整備 2000/01 Spehrical は1引数では構築されず、3つ必要 VecNsの参照宣言のときにめぐりめぐってdoubleではなくSphericalとして 扱われ(0,0,0,1)になってしまったから  2004/12/15 WRITECSV V2Dのバグ修正   //====================================================== クラス名と内容 //====================================================== template class Vec2; //2要素ベクトル template class Vec3; //3要素ベクトル template class VecN; //N要素ベクトル ポインタ配列 template class VecNs; //N要素 静的配列 template class VecMtx; //N、M要素行列 class Spherical; //球座標仮定義 template class SphericalVector //球座標+別のデータ構造 template int GetSign(T d) //符号判定 0を含む+は整数1負側は-1 int round(double x) // 浮動小数点数の四捨五入による整数化 inline double round(double x, int keta) //小数点以下の桁数指定 template double Deg2Rad(T d) //度とラジアンの変換 template double Rad2Deg(T d) template class DEG; //角度扱い template class RADIAN //ファイル入出力 template class U> int ReadBin template class U> int WriteBin //CSV入出力 template class U> int ReadCSV template class U> int WriteCSV //====================================================== ★2行2列以外では最初にIdentityで単位行列にする 2000/02/21 Hal.T void RotateZ(double p) など 2,3,N次元ベクトル、球面座標の演算ライブラリ クラスの中に静的にベクトルを実現する場合にはコンストラクタに 引数が持ち込めない。 VecMtxなどでは次数初期化関数を用意してあるので、それで初期化する。 コンパイラによりHファイル内にコードを全部書かなくてはいけないことがある  そこでテンプレートらしくすべてを定義文としてHファイルに納めた  言葉の定義: 学術図書出版 代数学と幾何学 P5 「行列の横に並んでいる数の組を行といい、上から順に第一行、、、第m行という。 また横に並んでいる数の組を列といい、左から順に第一列、、第n列という。 したがってAijは第i行、第j列の成分または元素といい、行列自身は(Aij)のように 略記する」 Rowは行、columは列である(MathCAD,HELPより) 違う! 行は column、 列はrow である 2006/06/14 Hal.T 関数テンプレートはクラス定義の中に書くと、クラスの内部関数としてしか 使えないので、外に書く abs など --------使い方の注意----------- ★ポインタ型で配列を生成するとき 次数を持ち込めないので標準のコンストラクタをnewで生成した後に VecN.SetDimN(n) VecMtx.SetDimN(n,m) で次元を確定させメモリを確保させる。 例: N次元ベクトル 4次のベクトルをm個ポインタで配列したいときには VecN *v31; 他の部分で宣言 { if(v31) delete [] v31; v31 = new VecN [m]; for(int n=0; n V2[256];  ではヘッダレベルでなにも関数が実体化されていないのでエラーが起きる。  ダミーとして  Vec2 VP2, V2[256];  とすれば生成される ★--------ライブラリ・メンテナンス上の注意----------- class VecN { VecN operator+(VecN &q) { VecN vt(*this); for(int k=0; k #include #include //-------------------------------------- //StrictEqualが定義されていると"="による自動型変換が無効になりAssignのみになる #define StrictEqual //コンパイラオプション VecNsに定数比較があるので、その警告を出させない #pragma option -w-ccc //-------------------------------------- //このファイルで定義されているもの //定数 #define PI1 3.1415926535897932384626433832795 /* π */ #ifndef PI #define PI PI1 #endif #define PI2 6.2831853071795864769252867665590 /* 2π */ #define PI4 12.566370614359172953850573533118 /* 4π */ #define PID2 1.5707963267948966192313216916397 /* π/2 */ #define PID18_ 0.17453292519943295769236907684886 /* π/18 */ #define PID180 0.017453292519943295769236907684886 /* π/180 */ #define DEG2RAD PID180 #define RAD2DEG 57.295779513082320876798154814105 /* 180/π */ #define PIPI 9.8696044010893586188344909998761 /* π^2 */ //#pragma option -Jgx template class Vec2; //2要素ベクトル // power,abs,~(=絶対値),+,-,*,/,==,!=,+=,-=,*=,/=,+p,-p //[]による参照もできる template class Vec3; //3要素ベクトル // Vec2への参照で初期化できる // power,abs,~(=絶対値),+,-,*(スカラー積),^(ベクトル積), // /,==,!=,+=,-=,*=,/=,+p,-p //[]による参照もできる //N要素ベクトル 静的配列 template class VecNs; template class VecN; //N要素ベクトル ポインタ配列 // power,abs2,abs,~(=絶対値),+,-,*(スカラー積),^(ベクトル積), // /,==,!=,+=,-=,*=,/=,+p,-p // SetDimN()次元数の設定 // =(球座標からの変換), =Vec3よりの変換 template class VecMtx; //N、M要素行列 // power,abs2,abs,~(=絶対値),+,-,*(スカラー積),^(ベクトル積), // /,==,!=,+=,-=,*=,/=,+p,-p // SetDimN()次元数の設定 // ColumN, RowN 次数の取得 // Det,Det2,Det3 式の値 // Rotate 回転行列の作成 RotateV,X,Y,Z // SolveC1,mul // identity、単位行列の生成 class Spherical; //球座標仮定義 //-------------------------------------- //符号判定 0を含む+側は整数で1負側は-1 template int GetSign(T d) { return (d>=0)? 1 : -1; } // 浮動小数点数の四捨五入による整数化 int round(double x) { return x < 0.0 ? ceil( x - 0.5 ): floor( x + 0.5 ); } // 浮動小数点数の四捨五入による整数化 小数点以下の桁数指定 inline double round(double x, int keta) { double k = pow10(keta); x*=k; x = x < 0.0 ? ceil( x - 0.5 ): floor( x + 0.5 ); return x/=k; } //-------------------------------------- //度とラジアンの変換 template double Deg2Rad(T d) { return d*PID180; } template double Rad2Deg(T d) { return d*RAD2DEG; } //-------------------------------------- //角度扱い(度とラジアン) #ifndef StrictEqual template class DEG; //仮定義 template class RADIAN { public: //data T a; // constructors RADIAN(T p) { a = p; } RADIAN() { a = 0; } //0から2πの範囲に収める void adj(void) { if(0<=a && a operator+(RADIAN &q) { return RADIAN(a+q.a); } RADIAN operator-(RADIAN &q) { return RADIAN(a-q.x); } RADIAN operator*(T k) { return RADIAN(a*k);} //スカラ倍 RADIAN operator/(T k) { return RADIAN(a/k);} //スカラ除算 int operator==(RADIAN &p) { return p.a==a; } int operator!=(RADIAN &p) { return p.a!=a; } //これ自身に対するオペレート RADIAN &operator+=(RADIAN &z) { a+=z.a; return *this; } RADIAN &operator+=(T z) { a+=z; return *this; } RADIAN &operator-=(RADIAN &z) { a-=z.a; return *this; } RADIAN &operator-=(T z) { a-=z; return *this; } RADIAN &operator*=(T v) { a *= v; return *this; } RADIAN &operator/=(T v) { a /= v; return *this; } RADIAN operator+() { return *this; } RADIAN operator-() { return RADIAN(-x); } RADIAN Assign(DEG &x) { a = Deg2Rad(x.a); return *this; } operator T() { return a; } //自動型変換 RADIAN operator=(DEG &x) { return Assign(x); } }; template class DEG { public: //data T a; // constructors DEG(T p) { a = p; } DEG() { a = 0; } //0から360未満の範囲に収める void adj(void) { if(0<=a && a<360.0) return; int n = a/360.0; if(a<0.0) n--; a -= n*360.0; } //四則演算 DEG operator+(DEG &q) { return DEG(a+q.a); } DEG operator-(DEG &q) { return DEG(a-q.x); } DEG operator*(T k) { return DEG(a*k);} //スカラ倍 DEG operator/(T k) { return DEG(a/k);} //スカラ除算 int operator==(DEG &p) { return p.a==a; } int operator==(DEG p) { return p.a==a; } int operator!=(DEG &p) { return p.a!=a; } int operator<(DEG p) { return p.a &operator+=(T z) { a+=z; return *this; } DEG &operator-=(T z) { a-=z; return *this; } DEG &operator+=(DEG &z) { a+=z.a; return *this; } DEG &operator-=(DEG &z) { a-=z.a; return *this; } DEG &operator*=(T v) { a *= v; return *this; } DEG &operator/=(T v) { a /= v; return *this; } DEG operator+() { return *this; } DEG operator-() { return DEG(-x); } DEG Assign(RADIAN &x) { a = Rad2Deg(x.a); return *this; } operator T() { return a; } //自動型変換 DEG operator=(RADIAN &x) { return Assign(x); } }; #endif //StrictEqual //} #include //-------------------------------------- //ファイル入出力 template class U> int ReadBin(char *na, U *v, int n) { return v->ReadBin(na, v, n); } template class U> int WriteBin(char *na, U *v, int n) { return v->WriteBin(na, v, n); } //-------------------------------------- //CSV入出力 /* 例: void __fastcall TForm1::Button25Click(TObject *Sender) {  V3D v3[3], vv[40];   v3[0].x=1; v3[1].x=3; v3[2].x=5;  WriteCSV("test.csv", v3, 3);  int n=ReadCSV("test.csv", vv, 4); VecNのCSV読み書きは動かない VecNs を使うこと 2005/05/27 } */ // ファイル名、 読み取り場所、 読み取る数 template class U> int ReadCSV(char *na, U *v, int n) { int m; ifstream ifs(na, ios::in); for(m=0; m> *v++; if(ifs.eof()) m--; ifs.close(); return m; //読み取ったデータ数を返す } template class U> int WriteCSV(char *na, U *v, int n) { ofstream ofs(na, ios::out); for(; n>0; n--) ofs << *v++; ofs.close(); return n; //書き残ったデータ数を返す } //-------------------------------------- /*固定小数点 16bit中央に小数点位置があるFFT用 intは32ビット デバッグ中だよお 2005/06/14 */ class FIX16_16 { public: //data int x; // constructors FIX16_16() { x = 0; } FIX16_16(double d) { x = d*65536; } FIX16_16(int d) { x = d<<16; } FIX16_16(int d, unsigned int e) { x = d<<16 + e; } //絶対値 FIX16_16 abs(void) { return x & 0x7FFFFFF; } //このクラスへの代入 自動変換 FIX16_16 &operator=(const int &d) { x = d<<16; return *this; } FIX16_16 &operator=(const double &d) { x = d*65536; return *this; } FIX16_16 &Assign(int d) { x=d<<16; return *this; } //このクラスからデフォルト型への代入 自動変換 operator int() const { return x>>16; } operator float() const { return x/65536.0; } //OK //四則演算 ここから下はまだ試験していない FIX16_16 operator+(FIX16_16 &q) { return FIX16_16(x+q.x); } FIX16_16 operator-(FIX16_16 &q) { return FIX16_16(x-q.x); } FIX16_16 operator*(FIX16_16 &q) { return (x*q.x); } //スカラー積 FIX16_16 operator*(int k) { return FIX16_16(x*k);} //スカラ倍 FIX16_16 operator/(int k) { return FIX16_16(x/k);} //スカラ除算 //これ自身に対するオペレート FIX16_16 &operator+=(FIX16_16 &z) { x+=z.x; return *this; } FIX16_16 &operator-=(FIX16_16 &z) { x-=z.x; return *this; } FIX16_16 &operator*=(int v) { x *= v; return *this; } FIX16_16 &operator/=(int v) { x /= v; return *this; } FIX16_16 operator+() { return *this; } FIX16_16 operator-() { return FIX16_16(-x); } }; //-------------------------------------- //2次のベクトル template class Vec2 { public: //data T x, y; // constructors Vec2(T p, T q) { x = p; y = q; } Vec2() { x=y=0; } //パワー値 T power(void) { return (x*x + y*y); } T power(Vec2 &v) { return (v.x*v.x + v.y*v.y); } //絶対値 T operator~() { return sqrt(x*x + y*y); } T abs(void) { return sqrt(x*x + y*y); } T abs(Vec2 &v) { return sqrt(v.x*v.x + v.y*v.y); } //規格化 長さを1にする void Standard(void) { *this /= abs(*this); } //四則演算 Vec2 operator+(Vec2 &q) { return Vec2(x+q.x, y+q.y); } Vec2 operator-(Vec2 &q) { return Vec2(x-q.x, y-q.y); } T operator*(Vec2 &q) { return (x*q.x + y*q.y); } //スカラー積 Vec2 operator*(T k) { return Vec2(x*k, y*k);} //スカラ倍 Vec2 operator/(T k) { return Vec2(x/k, y/k);} //スカラ除算 //int operator==(Vec2 &p) { return p.x==x && p.y==y; } //int operator!=(Vec2 &p) { return p.x!=x || p.y!=y; } //ベクトル積で面積、3DのZ値を帰す double operator^(Vec2 &q) { return x*q.y-y*q.x; } //これ自身に対するオペレート Vec2 &operator+=(Vec2 &z) { x+=z.x; y+=z.y; return *this; } Vec2 &operator-=(Vec2 &z) { x-=z.x; y-=z.y; return *this; } Vec2 &operator*=(T v) { x *= v; y*=v; return *this; } Vec2 &operator/=(T v) { x /= v; y/=v; return *this; } Vec2 operator+() { return *this; } Vec2 operator-() { return Vec2(-x, -y); } //x y の代わりの[]引数による参照 T& operator[](int n) { return (n==0)? x : y; } //代入  Vec2 &Assign(T &v) { x=y=v; return *this; } //全て同じ値 Vec2 &Assign(Vec2 &v) { x=v.x; y=v.y; return *this; } Vec2 &Assign(Vec3 &v) { x=v.x; y=v.y; return *this; } Vec2 &Assign(VecNs &v) { x=v[0]; y=v[1]; return *this; } Vec2 &Assign(VecN &v) { x=v[0]; y=v[1]; return *this; } friend ostream &operator<<(ostream &s, Vec2 &p) { s << p.x << ", " << p.y << endl; return s; } friend istream &operator>>(istream &s, Vec2 &p) { char buf[1024]; double x, y; s.getline(buf, 1024); sscanf(buf, "%lf,%lf", &x , &y); p.x = x; p.y = y; return s; } int WriteBin(FILE *fp) { return fwrite(&x, sizeof(T), 2, fp); } int WriteBin(FILE *fp, Vec2 *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, Vec2 *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { return fread(&x, sizeof(T), 2, fp); } int ReadBin(FILE *fp, Vec2 *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, Vec2 *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; /* 関数テンプレートはクラス定義の中に書くと、クラスの内部関数としてしか 使えないので、外に書く */ template T abs(Vec2 v) { return sqrt(v.x*v.x + v.y*v.y); }; template T power(Vec2 v) { return (v.x*v.x + v.y*v.y); } //STLのuniqueを使うために関数テンプレートに変えた 2001/2/21 Hal.T template bool operator==(const Vec2 &p, const Vec2 &q) { return p.x==q.x && p.y==q.y; } template bool operator!=(const Vec2 &p, const Vec2 &q) { return p.x!=q.x || p.y!=q.y; } //-------------------------------------- //3次のベクトル //ベクトル積などの計算順序は使うときに()で保証すること template class Vec3 { public: //data T x, y, z; // constructors Vec3() { x=y=z=0; } Vec3(T p, T q, T r) { x=p; y=q; z=r; } Vec3(Vec2 &v2) { x=v2.x; y=v2.y; z=0.0; } //パワー値 T power(void) { return (x*x + y*y + z*z); } T power(Vec3 &v) { return (v.x*v.x + v.y*v.y + v.z*v.z); } //絶対値 T operator~() { return sqrt(x*x + y*y + z*z); } T abs(void) const { return sqrt(x*x + y*y + z*z); } T abs(const Vec3 &v) { return sqrt(v.x*v.x + v.y*v.y + v.z*v.z); } //規格化 長さを1にする void Standard(void) { *this /= abs(*this); } //四則演算 Vec3 operator+(Vec3 &q) { return Vec3(x+q.x, y+q.y, z+q.z); } Vec3 operator-(Vec3 &q) { return Vec3(x-q.x, y-q.y, z-q.z); } T operator*(Vec3 &q) { return (x*q.x + y*q.y + z*q.z); } //スカラー積 Vec3 operator^(Vec3 &q) //ベクトル積 { return Vec3(y*q.z-z*q.y, z*q.x-x*q.z, x*q.y-y*q.x); } Vec3 operator*(T k) { return Vec3(x*k, y*k, z*k); } //スカラ倍 Vec3 operator/(T k) { return Vec3(x/k, y/k, z/k); } //スカラー除算 //bool operator==(const Vec3 &p) { return p.x==x && p.y==y && p.z==z; } //bool operator!=(const Vec3 &p) { return p.x!=x || p.y!=y || p.z!=z; } //これ自身に対するオペレート Vec3 &operator+=(Vec3 &a) { x+=a.x; y+=a.y; z+=a.z; return *this; } Vec3 &operator-=(Vec3 &a) { x-=a.x; y-=a.y; z-=a.z; return *this; } Vec3 &operator*=(T v) { x*=v; y*=v; z*=v; return *this; } Vec3 &operator/=(T v) { x/=v; y/=v; z/=v; return *this; } Vec3 operator+() { return *this; } Vec3 operator-() { return Vec3(-x, -y, -z); } Vec3& operator=(const Vec3 &p) { x=p.x; y=p.y; z=p.z; return *this; } Vec3& round(int keta) { x=::round(x, keta); y=::round(y,keta); z=::round(z,keta); return *this; } Vec3& Reciprocal(void) { x=1/x; y=1/y, z=1/z; return *this; } //逆数化 Vec3& Reciprocal(const T &src) { x=src/x; y=src/y; z=src/z; return *this; } //逆数化 src/x //型の違うものの代入はAssignとする Vec3& Assign(const T &src) { x=src; y=src; z=src; return *this; } Vec3& Assign(const Vec2 &p) { x=p.x; y=p.y; z=0; return *this; } Vec3& Assign(const Vec3 &p) { x=p.x; y=p.y; z=p.z; return *this; } Vec3& Assign(const VecN &p) { x=p.vp[0]; y=p.vp[1]; z=p.vp[2]; return *this; } Vec3& Assign(const VecNs &src) { x=src.v[0]; y=src.v[1]; z=src.v[2]; return *this; } Vec3& Assign(const VecNs &src) { x=src.v[0]; y=src.v[1]; z=src.v[2]; return *this; } //球座標から直交座標に変換する Vec3& Assign(const Spherical &src) { double rxy; x=(rxy=src.r*cos(src.theta))*cos(src.phi); y=rxy*sin(src.phi); z=src.r*sin(src.theta); return *this; } #ifndef StrictEqual //{ Vec3& operator=(const T &src) { return Assign(src); } // Vec3& operator=(const Vec3 &src) { return Assign(src); } // Vec3& operator=(const Vec3 &src) { return Assign(src); } Vec3& operator=(const VecN &src) { return Assign(src); } Vec3& operator=(const VecNs &src) { return Assign(src); } Vec3& operator=(const VecNs &src) { return Assign(src); } Vec3& operator=(const Spherical &src) { return Assign(src); } #endif //} T& operator[](int n) { return (n==0)? x : ((n==1)? y : z); } friend ostream &operator<<(ostream &s, Vec3 &p) { s << p.x << ", " << p.y << ", " << p.z << endl; return s; } friend istream &operator>>(istream &s, Vec3 &p) { char buf[1024]; double x, y, z; s.getline(buf, 1024); sscanf(buf, "%lf,%lf,%lf", &x , &y, &z); p.x = x; p.y = y; p.z = z; return s; } int WriteBin(FILE *fp) { return fwrite(&x, sizeof(T), 3, fp); } int WriteBin(FILE *fp, Vec3 *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, Vec3 *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { return fread(&x, sizeof(T), 3, fp); } int ReadBin(FILE *fp, Vec3 *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, Vec3 *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; template T power(Vec3 v) { return (v.x*v.x + v.y*v.y + v.z*v.z); } template T abs(Vec3 v) { return sqrt(v.x*v.x + v.y*v.y + v.z*v.z); } //STLのuniqueを使うために関数テンプレートに変えた 2001/2/21 Hal.T template bool operator==(const Vec3 &p, const Vec3 &q) { return p.x==q.x && p.y==q.y && p.z==q.z; } template bool operator!=(const Vec3 &p, const Vec3 &q) { return p.x!=q.x || p.y!=q.y || p.z!=q.z; } //-------------------------------------- /*N次元ベクトル ポインタ配列型 4次のベクトルをm個ポインタで配列したいときには VecN *v31; 他の部分で宣言 { if(v31) delete [] v31; v31 = new VecN [m]; for(int n=0; n class VecN { public: int vn; //要素数 T *vp; //ベクトルデータへのポインタ // constructors VecN() { vp=0; vn=0; } VecN(const VecN &v) //既存の内容で初期化する { vp = new T[vn = v.vn]; for(int k=0; k &p) { return p.vn; } //次元(要素数)を返す void Clear(T d) { //全部の初期化 for(int k=0; k &v) { T d=0.0; for(int k=0; k &v) { T d=0.0; for(int k=0; k operator+(VecN &q) { VecN vt(*this); for(int k=0; k operator-(VecN &q) { VecN vt(*this); for(int k=0; k &q) //スカラ積 { T t=0; for(int k=0; k operator*(T a) { VecN vt(*this); for(int k=0; k operator/(T a) { VecN vt(*this); for(int k=0; k &operator+=(VecN const &p) { for(int k=0; k &operator-=(VecN const &p) { for(int k=0; k &operator*=(T a) { for(int k=0; k &operator/=(T a) { for(int k=0; k operator+() { return *this; } //+符号 VecN operator-() //−符号 { VecN vt(this->vn); for(int k=0; k& operator=(const T &src) { for(int k=0; k& operator=(const VecN &src) { for(int k=0; k& operator=(const Vec3 &src) { vp[0]=src.x; vp[1]=src.y; vp[2]=src.z; return *this; } //納まる範囲でコピーする VecN& Assign(const Vec2 &v2) { vp[0]=v2.x; if(vn>=2) vp[1] = v2.y; return *this; } VecN& Assign(const Vec3 &v3) { vp[0]=v3.x; if(vn>=2) vp[1] = v3.y; if(vn>=3) vp[2] = v3.z; return *this; } VecN& Assign(const VecN &vv) { int n; for(n=0; n& operator=(const Spherical &src) { return Assign(src); } #endif //} VecN& Assign(const Spherical &src) { double rxy; vp[0]=(rxy=src.r*cos(src.theta))*cos(src.phi); vp[1]=rxy*sin(src.phi); vp[2]=src.r*sin(src.theta); if(vn>3) vp[3]=1.0; return *this; } friend ostream &operator<<(ostream &s, VecN &p){ //2005/05/27 BUG不可解 s << p.vp[0]; for(int n=1; n>(istream &s, VecN &p) { char *cp, buf[1024]; double x; s.getline(buf, 1024); for(int n=0, cp=buf; n *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, VecN *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { return fread(vp, sizeof(T), vn, fp); } int ReadBin(FILE *fp, VecN *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, VecN *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; template T abs(VecN v) { T d=0.0; for(int k=0; k T power(VecN v) { T d=0.0; for(int k=0; k bool operator==(const VecN &p, const VecN &q) { int k=0, t=-1; for(; k bool operator!=(const VecN &p, const VecN &q) { for(int k=0; k v4() VecNs v4(v4a) 他への参照 VecNs v4=v4a # VecNs v4(3.3) 数値データ double p[4] = {1,2,3,4}; VecNs v4(p) 数値配列へのポインタ */ template class VecNs { public: T v[jigen]; //ベクトルデータへのポインタ // constructors VecNs() { for(int n=0; n &v) { T d=0.0; for(int k=0; k &v) { T d=0.0; for(int k=0; k operator+(VecNs &q) { VecNs vt(*this); for(int k=0; k operator-(VecNs &q) { VecNs vt(*this); for(int k=0; k &q) //スカラ積 { T t=0; for(int k=0; k operator*(T a) { VecNs vt(*this); for(int k=0; k operator/(T a) { VecNs vt(*this); for(int k=0; k &q) { int k=0, t=-1; for(; k &q) { for(int k=0; k &operator+=(VecNs const &p) { for(int k=0; k &operator-=(VecNs const &p) { for(int k=0; k &operator*=(T a) { for(int k=0; k &operator/=(T a) { for(int k=0; k operator+() { return *this; } //+符号 VecNs operator-() //−符号 { VecNs vt; for(int k=0; k& operator=(const VecNs &src) { for(int k=0; k& operator=(const T &src) { for(int k=0; k& operator=(const Vec3 &src) { v[0]=src.x; v[1]=src.y; v[2]=src.z; return *this; } //球面座標からの変換 アフィン変換用 最後の項は1にする VecNs& operator=(const Spherical &src) { return Assign(src); } #endif //} //球座標からのコピー アフィン変換用に4次なら4次目は1にする  VecNs& Assign(const Spherical &src) { double rxy; v[0]=(rxy=src.r*cos(src.theta))*cos(src.phi); v[1]=rxy*sin(src.phi); v[2]=src.r*sin(src.theta); if(jigen>3) v[3]=1.0; return *this; } VecNs& Assign(const Vec2 &v2) { v[0] = v2.x; if(jigen>=2) v[1] = v2.y; return *this; } VecNs& Assign(const Vec3 &v3) { v[0] = v3.x; if(jigen>=2) v[1] = v3.y; if(jigen>=3) v[2] = v3.z; return *this; } VecNs& Assign(const VecNs &vv) { //同じサイズのコピー for(int n=0; n& Assign(const T *p) { for(int n=0; n &p) { s << p.v[0]; for(int n=1; n>(istream &s, VecNs &p) { char *cp, buf[1024]; double x; s.getline(buf, 1024); cp = buf; for(int n=0; n *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, VecNs *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { return fread(v, sizeof(T), jigen, fp); } int ReadBin(FILE *fp, VecNs *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, VecNs *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; template int ReadCSVs(char *na, VecNs *v, int n) { int m; ifstream ifs(na, ios::in); for(m=0; m> *v++; if(ifs.eof()) m--; ifs.close(); return m; //読み取ったデータ数を返す } template int WriteCSVs(char *na, VecNs *v, int n) { ofstream ofs(na, ios::out); for(; n>0; n--) ofs << *v++; ofs.close(); return n; //書き残ったデータ数を返す } //絶対値 template T abs(VecNs &v) { T d=0.0; for(int k=0; k T power(VecNs &v) { T d=0.0; for(int k=0; k T * AssignCopy(T *p, VecNs &v) { T *q=p; for(int k=0; k bool operator==(const VecNs &p, const VecNs &q) { int k=0, t=-1; for(; k bool operator!=(const VecNs &p, const VecNs &q) { for(int k=0; k class VecMtx //: public VecN { private: public: int Row, Colum; VecN *vp; // constructors VecMtx() { Colum=Row=0; vp=0; } //次数の定義 SetDim(c,r)を呼び出すこと VecMtx(int row, int colum){ Colum = colum; Row = row; vp = new VecN [Row]; for(int k = 0; k [Row]; for(int k = 0; k [Row]; for(int k = 0; k &v3, double p) { double c, c1, s; Vec3 v = v3; c1 = 1.0-(c = cos(p)); s = sin(p); if(v.power()==0.0) { Identity(); return; } v.Standard(); vp[0][0]=c1*v.x*v.x+c; vp[0][1]=c1*v.x*v.y-v.z*s; vp[0][2]=c1*v.x*v.z+v.y*s; vp[1][0]=c1*v.x*v.y+v.z*s; vp[1][1]=c1*v.y*v.y+c; vp[1][2]=c1*v.y*v.z-v.x*s; vp[2][0]=c1*v.x*v.z-v.y*s; vp[2][1]=c1*v.y*v.z+v.x*s; vp[2][2]=c1*v.z*v.z+c; } void RotateVA(Vec3 &v3) { RotateV(v3, abs(v3)); } //回転表現 X,Y,Z 要素だけを変化させる  //3行3列以外では最初にIdentityで単位行列にしてから実行する void RotateZ(double x, double y) { vp[0][0] = vp[1][1] = x; vp[1][0] = -(vp[0][1]= y); } //2行2列以外では最初にIdentityで単位行列にしてから実行する 2000/02/21 Hal.T void RotateZ(double p) { if(Row != 2 || Colum != 2) Identity(); vp[0][0] = vp[1][1] = cos(p); vp[1][0] = -(vp[0][1]= sin(p)); } void RotateX(double p) { if(Row != 2 || Colum != 2) Identity(); vp[1][1] = vp[2][2] = cos(p); vp[1][2] = -(vp[2][1]= sin(p)); } void RotateY(double p) { if(Row != 2 || Colum != 2) Identity(); vp[0][0] = vp[2][2] = cos(p); vp[0][2] = -(vp[2][0]= sin(p)); } void SolveC1(void) // 対角を1にして、係数を第一列に吐き出す { int nC1, nC2; T tmpCC; for(nC1 = 1; nC1 < Row; nC1++) { tmpCC = vp[nC1][nC1]; for(nC2 = 1; nC2 < Row; nC2++) { if(nC1 != nC2) vp[nC2] -= vp[nC1]*(vp[nC2][nC1]/tmpCC); } } for(nC1=1; nC1 < Row; nC1++) { // 行列の対角要素を1に規格化する tmpCC = 1.0/vp[nC1][nC1]; vp[nC1] *= tmpCC; } } VecN& operator[](int n) { return (*this).vp[n]; } //Tの内部仕様にもよるが単純コピーでよければColum*Rowの量だけmemcpyすればよい VecMtx& operator=(const VecMtx &src) { if(src.Colum != Colum || src.Row != Row) return *this; for(int k = 0; k operator*(VecMtx &a, T d){ VecMtx c(a.Row, a.Colum); // for(int m=0; m operator*(T d) { VecMtx &a = *this; VecMtx c(a.Row, a.Colum); for(int m=0; m operator*(VecMtx &b) { VecMtx &a = *this; VecMtx c(a.Row, a.Colum); c.mul(a,b); return c;} Vec3 operator*(Vec3 &b) { VecMtx &a = *this; Vec3 c; c.x = a[0][0]*b.x+a[0][1]*b.y+a[0][2]*b.z; c.y = a[1][0]*b.x+a[1][1]*b.y+a[1][2]*b.z; c.z = a[2][0]*b.x+a[2][1]*b.y+a[2][2]*b.z; return c; } //Affin変換用 //VecMtx*VecN 行列の右からベクトルを乗算する //行とベクトルの次数があわなければ零で埋まった行列を帰す VecN operator*(VecN &b){ VecMtx &a = *this; int i = a.RowN(); VecN c(i); if(b.vn != ColumN()) return c; for(int n=0; n &a, VecMtx &b) { if(a.Colum != b.Row || a.Row != b.Colum) return; for(int i=0; i & Assign(const VecMtx &vm) { int r, c; for(r=0; r &p) { for(int n=0; n>(istream &s, VecMtx &p) { for(int n=0; n> p.vp[n++]; return s; } //以下の二つの関数は基本レベルの変数タイプだけを扱う char int double int WriteBin(FILE *fp) { int m, k; for(int n=0; n *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, VecMtx *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { int m, k; for(int n=0; n *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, VecMtx *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; //====================================== //-------------------------------------- //row行 col列 直方行列 VecNs を使った行列 template class VecMs { private: public: VecNs v[Row]; VecMs() {} int RowN(void) { return Row; } //行数 int ColumN(void) { return Colum; } //列数 void Identity(void) { //単位行列の生成 Row>Columならエラーを起こす for(int n=0; n &v3, double p) { double c, c1, s; Vec3 vt = v3; c1 = 1.0-(c = cos(p)); s = sin(p); if(vt.power()==0.0) { Identity(); return; } vt.Standard(); v[0][0]=c1*vt.x*vt.x+c; v[0][1]=c1*vt.x*vt.y-vt.z*s; v[0][2]=c1*vt.x*vt.z+vt.y*s; v[1][0]=c1*vt.x*vt.y+vt.z*s; v[1][1]=c1*vt.y*vt.y+c; v[1][2]=c1*vt.y*vt.z-vt.x*s; v[2][0]=c1*vt.x*vt.z-vt.y*s; v[2][1]=c1*vt.y*vt.z+vt.x*s; v[2][2]=c1*vt.z*vt.z+c; } void RotateVA(Vec3 &v3) { RotateV(v3, abs(v3)); } //回転表現 X,Y,Z 要素だけを変化させる  //3行3列以外では最初にIdentityで単位行列にしてから実行する void RotateZ(double x, double y) { if(Row != 2 || Colum != 2) Identity(); v[0][0] = v[1][1] = x; v[1][0] = -(v[0][1]= y); } void RotateZ(double p) { if(Row != 2 || Colum != 2) Identity(); v[0][0] = v[1][1] = cos(p); v[1][0] = -(v[0][1]= sin(p)); } void RotateX(double p) { if(Row != 2 || Colum != 2) Identity(); v[1][1] = v[2][2] = cos(p); v[1][2] = -(v[2][1]= sin(p)); } void RotateY(double p) { if(Row != 2 || Colum != 2) Identity(); v[0][0] = v[2][2] = cos(p); v[0][2] = -(v[2][0]= sin(p)); } void SolveC1(void) // 対角を1にして、係数を第一列に吐き出す { int nC1, nC2; T tmpCC; for(nC1 = 1; nC1 < Row; nC1++) { tmpCC = v[nC1][nC1]; for(nC2 = 1; nC2 < Row; nC2++) { if(nC1 != nC2) v[nC2] -= v[nC1]*(v[nC2][nC1]/tmpCC); } } for(nC1=1; nC1 < Row; nC1++) { // 行列の対角要素を1に規格化する tmpCC = 1.0/v[nC1][nC1]; v[nC1] *= tmpCC; } } VecNs& operator[](int n) { return v[n]; } VecMs operator*(T d) { //定数培 VecMs c; for(int m=0; m operator*(Vec2 &b) { VecMs &a = *this; Vec2 c; c.x = a[0][0]*b.x+a[0][1]*b.y; c.y = a[1][0]*b.x+a[1][1]*b.y; return c; } Vec3 operator*(Vec3 &b) { VecMs &a = *this; Vec3 c; c.x = a[0][0]*b.x+a[0][1]*b.y+a[0][2]*b.z; c.y = a[1][0]*b.x+a[1][1]*b.y+a[1][2]*b.z; c.z = a[2][0]*b.x+a[2][1]*b.y+a[2][2]*b.z; return c; } //Affin変換用 //VecMs*VecNs 行列の右からベクトルを乗算する //行とベクトルの次数があわなければ零で埋まった行列を帰す VecNs operator*(VecNs &b){ VecNs c; for(int n=0; n &a, VecMs &b) { if(a.ColumN() != b.RowN() || a.RowN() != b.ColumN()) return; for(int i=0; i operator*(VecMs &b) { VecMs &a = *this; VecMs c; c.mul(a,b); return c;} //3行3列の逆行列 void Inverse(void) { if(Colum==3 && Row==3) Inverse33(); } void Inverse33(void) { double x00 = v[0][0], x01 = v[0][1], x02 = v[0][2]; double x10 = v[1][0], x11 = v[1][1], x12 = v[1][2]; double x20 = v[2][0], x21 = v[2][1], x22 = v[2][2]; double bunbo = x00*(x11*x22-x12*x21)+x01*(x12*x20-x10*x22)+x02*(x10*x21-x11*x20); bunbo =1.0/bunbo; v[0][0] = (x11*x22-x12*x21)*bunbo; v[0][1] = (x02*x21-x01*x22)*bunbo; v[0][2] = (x01*x12-x02*x11)*bunbo; v[1][0] = (x12*x20-x10*x22)*bunbo; v[1][1] = (x00*x22-x02*x20)*bunbo; v[1][2] = (x02*x10-x00*x12)*bunbo; v[2][0] = (x10*x21-x11*x20)*bunbo; v[2][1] = (x01*x20-x00*x21)*bunbo; v[2][2] = (x00*x11-x01*x10)*bunbo; } //転置行列への変換 void Transpose(void) { if(ColumN()!=RowN()) return; //行と列があわなければなにもしない int n,m; T c; for(n=0; n & Assign(const VecMs &vm) { for(int r=0; r &p) { for(int n=0; n>(istream &s, VecMs &p) { for(int n=0; n> p.v[n++]; return s; } //以下の二つの関数は基本レベルの変数タイプだけを扱う char int double int WriteBin(FILE *fp) { int m, k; for(int n=0; n *v, int n) { int i=0, m=0; do { m+=(i=v->WriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, VecMs *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { int m, k; for(int n=0; n *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, VecMs *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; //-------------------------------------- template int ReadBin(char *na, VecMs *v, int n) { return v->ReadBin(na, v, n); } //-------------------------------------- template int WriteBin(char *na, VecMs *v, int n) { return v->WriteBin(na, v, n); } //====================================== //球座標 内部で正規化されるので必ずラジアンで扱うこと //2000/11/20 修正 x=y=0のときにエラーを起こしてしまう class Spherical { public: double r; //動径 double phi; //XY面内、+Z軸から見てX軸基準に左回りの角度 double theta;//XY面から+Z軸への傾き角度 //code Spherical() { r = phi = theta = 0.0; } Spherical(double rr, double pp, double tt) { r = rr; phi = pp; theta = tt; adj(); } explicit Spherical(const Vec3 &v3) { Assign(v3); } //演算 2000/02/03 Hal.T //4次であっても3次として計算する #ifndef StrictEqual //{ Spherical& operator=(VecN &src) { return Assign(src); } Spherical& operator=(VecNs &src) { return Assign(src); } #endif //} //2000/11/20 修正 x=y=0のときにエラーを起こしてしまう Spherical& Assign(const Vec3 &v3) { if((r=v3.abs())==0) { phi=theta=0; } else { phi = (v3.x==0 && v3.y==0)? 0 : atan2(v3.y, v3.x); theta = atan2(v3.z, sqrt(v3.x*v3.x+v3.y*v3.y)); } return *this; } Spherical& Assign(VecN &src) { Vec3 v3; v3.Assign(src); r = v3.abs(); phi = atan2(v3.y, v3.x); theta = atan2(v3.z, sqrt(v3.x*v3.x+v3.y*v3.y)); return *this; } Spherical& Assign(VecNs &src) { Vec3 v3; v3.Assign(src); r = v3.abs(); phi = atan2(v3.y, v3.x); theta = atan2(v3.z, sqrt(v3.x*v3.x+v3.y*v3.y)); return *this; } // r>=0.0, theta =±π/2,phi=0から2πの範囲に収める void adj(void) { int n; if(r<0.0) { r=-r; phi+=PI1; theta=-theta; } //r>=0.0にする if(PID2PID2 && theta<=(PI1)) { //90-180 theta = PI1-theta; phi+=PI1; } else if(theta>PI1 && theta<(PI1+PID2)) { //180-270 theta = theta-PI1; phi+=PI1; } else if(theta>=(PI1+PID2)) { //270-360 theta -= PI2; } } if(0<=phi && phiWriteBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int WriteBin(char *name, Spherical *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "wb"))>0) m = WriteBin(fp, v, n); fclose(fp); return m; } int ReadBin(FILE *fp) { return fread(&r, sizeof(double), 3, fp); } int ReadBin(FILE *fp, Spherical *v, int n) { int i=0, m=0; do { m+=(i=v->ReadBin(fp)); v++; n--; } while(n>0 && i>0); return m; } int ReadBin(char *name, Spherical *v, int n) { int m=0; FILE *fp; if((fp = fopen(name, "rb"))>0) m = ReadBin(fp, v, n); fclose(fp); return m; } }; //STLのuniqueを使うために関数テンプレートに変えた 2001/2/21 Hal.T bool operator==(const Spherical &p, const Spherical &q) { return p.r==q.r && p.phi==q.phi && p.theta==q.theta; } bool operator!=(const Spherical &p, const Spherical &q) { return p.r!=q.r || p.phi!=q.phi || p.theta!=q.theta; } //====================================== //数理構造 //球座標+別のデータ構造 template class SphericalVector : public Spherical { public: T v; //code SphericalVector():Spherical() {} SphericalVector(T vv, double rr=0, double pp=0.0, double tt = 0.0) : Spherical(rr, pp, tt), v(vv) {} // Spherical(rr, pp, tt) { v.Assign(vv); } SphericalVector& Assign(SphericalVector &p) { r=p.r; phi=p.phi; theta=p.theta; v=p.v; return *this; } }; //====================================== //1度は実体の寸前まで作成しておけば 配列の時にエラーが出ない class DumyVector { Vec2 Vec2_int; Vec3 Vec3_int; VecN VecN_int; VecMtx VecMtx_int; Vec2 Vec2_double; Vec3 Vec3_double; VecN VecN_double; VecNs VecNs4_double; VecMtx VecMtx_double; }; //====================================== typedef Vec2 V2I; typedef Vec2 V2F; typedef Vec2 V2D; typedef Vec3 V3I; typedef Vec3 V3F; typedef Vec3 V3D; typedef VecNs V3Ds; typedef VecNs V4Ds; typedef VecMtx VMI; typedef VecMtx VMF; typedef VecMtx VMD; /* VecNs, VecMsの注意書き 一般に静的に確保されるものは宣言時にサイズが確定していなければならない */ //====================================== #endif // __VECTORN_H