/*
	AramakiOnline
	Copyright (C) 2008 superbacker

	This program is free software; you can redistribute it and/or modify it under the terms
	of the GNU General Public License as published by the Free Software Foundation;
	either version 3 of the License, or (at your option) any later version.

	This program is distributed in the hope that it will be useful, but WITHOUT ANY
	WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
	FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

	You should have received a copy of the GNU General Public License along with this
	program. If not, see <http://www.gnu.org/licenses/>.
 */

#ifndef POINT3D_H_
#define POINT3D_H_

struct Point3d {
	double x,y,z;

	inline Point3d() : x(0),y(0),z(0) {}

	inline Point3d(double x,double y,double z) : x(x),y(y),z(z) {}

	//スカラーを求める
	inline double scalar() const {
		return sqrt(x*x+y*y+z*z);
	}

	//正規化
	inline void normalize() {
		double scalar;

		//スカラーを求める
		scalar=this->scalar();

		//大きさがない
		if (scalar==0.0) return;

		//各成分をスカラーで割る
		x/=scalar;
		y/=scalar;
		z/=scalar;
	}

	//加法
	inline Point3d operator+(const Point3d &point) const {
		Point3d newPoint;

		newPoint.x=x+point.x;
		newPoint.y=y+point.y;
		newPoint.z=z+point.z;

		return newPoint;
	}

	inline Point3d &operator+=(const Point3d &point) {
		x+=point.x;
		y+=point.y;
		z+=point.z;

		return *this;
	}

	//減法
	inline Point3d operator-(const Point3d &point) const {
		Point3d newPoint;

		newPoint.x=x-point.x;
		newPoint.y=y-point.y;
		newPoint.z=z-point.z;

		return newPoint;
	}

	inline Point3d &operator-=(const Point3d &point) {
		x-=point.x;
		y-=point.y;
		z-=point.z;

		return *this;
	}

	//実数倍
	inline Point3d operator*(double scale) const {
		Point3d newPoint;

		newPoint.x=x*scale;
		newPoint.y=y*scale;
		newPoint.z=z*scale;

		return newPoint;
	}

	inline Point3d &operator*=(double scale) {
		x*=scale;
		y*=scale;
		z*=scale;

		return *this;
	}

	//内積を求める
	inline double dot(const Point3d &point) const {
		return x*point.x+y*point.y+z*point.z;
	}

	//外積を求め代入
	inline void cross(const Point3d &point,const Point3d &point2) {
		x=point.y*point2.z-point.z*point2.y;
		y=point.z*point2.x-point.x*point2.z;
		z=point.x*point2.y-point.y*point2.x;
	}

	//法線ベクトルを生成
	inline void normalVector(const Point3d &vertex1,const Point3d &vertex2,const Point3d &vertex3) {
		Point3d p1,p2;

		p1=vertex2-vertex1;
		p2=vertex3-vertex1;

		cross(p1,p2);
	}
};

#endif /* POINT3D_H_ */
