mikecat_mixc 2013-12-29 15:18:36

[C] 数学の答えをプログラムに書いた結果www このエントリーをはてなブックマークに追加

投稿者からのアピールポイント

3次元空間での直線と円筒の交点を求めるため、

軸からの距離がr

(pl[0]+t*dl[0]-pc[0]-s*dc[0])*(pl[0]+t*dl[0]-pc[0]-s*dc[0])+
    (pl[1]+t*dl[1]-pc[1]-s*dc[1])*(pl[1]+t*dl[1]-pc[1]-s*dc[1])+
    (pl[2]+t*dl[2]-pc[2]-s*dc[2])*(pl[2]+t*dl[2]-pc[2]-s*dc[2])=r*r

および、円筒の軸から交点へ向かうベクトルが垂直

(pl[0]+t*dl[0]-pc[0]-s*dc[0])*dc[0]+
    (pl[1]+t*dl[1]-pc[1]-s*dc[1])*dc[1]+
    (pl[2]+t*dl[2]-pc[2]-s*dc[2])*dc[2]=0

という条件を使用し、wxMaximaを参考にまとめた結果をプログラムに乗せました。とくに前半がかなり読みにくくて闇。

/*
 * 直線と円筒の交点を求める。直線はpl+t*dl、円筒の軸はpc+s*dcで表される。
 * @param ot 交点のtを出力する配列
 * @param os 交点のsを出力する配列
 * @param pl 入力の直線の基準点(t==0)
 * @param dl 入力の直線の方向ベクトル
 * @param pc 入力の円筒の軸の基準点(s==0)
 * @param dc 入力の円筒の方向ベクトル
 * @param r 円筒の半径
 * @return 交点の数
 */
int getLineCylinderHitPoint(
		double ot[2],double os[2],const double pl[3],const double dl[3],
		const double pc[3],const double dc[3],double r) {
	/* 最初の式の係数 */
	double a_tt,a_ss,a_ts,a_t,a_s,a_const;
	/* 二番目の式の係数 */
	double b_t,b_s,b_const;
	/* s=p*t+q */
	double p,q;
	/* tを求める二次方程式の係数 */
	double e_tt,e_t,e_const;
	double e_D; /* 判別式 */

	/* a_tt*t*t+a_ts*t*s+a_ss*s*s+a_t*t+a_s*s+a_const=0 */
	a_tt=dl[0]*dl[0]+dl[1]*dl[1]+dl[2]*dl[2];
	a_ts=-2.0*(dc[0]*dl[0]+dc[1]*dl[1]+dc[2]*dl[2]);
	a_t=2.0*(dl[0]*pl[0]+dl[1]*pl[1]+dl[2]*pl[2]-dl[0]*pc[0]-dl[1]*pc[1]-dl[2]*pc[2]);
	a_ss=dc[0]*dc[0]+dc[1]*dc[1]+dc[2]*dc[2];
	a_s=2.0*(-dc[0]*pl[0]-dc[1]*pl[1]-dc[2]*pl[2]+dc[0]*pc[0]+dc[1]*pc[1]+dc[2]*pc[2]);
	a_const=pl[0]*pl[0]+pl[1]*pl[1]+pl[2]*pl[2]+pc[0]*pc[0]+pc[1]*pc[1]+pc[2]*pc[2]
		-2.0*(pc[0]*pl[0]+pc[1]*pl[1]+pc[2]*pl[2])-r*r;

	/* b_s*s=b_t*t+b_const */
	b_t=dc[0]*dl[0]+dc[1]*dl[1]+dc[2]*dl[2];
	b_s=dc[0]*dc[0]+dc[1]*dc[1]+dc[2]*dc[2];
	b_const=dc[0]*pl[0]+dc[1]*pl[1]+dc[2]*pl[2]-dc[0]*pc[0]-dc[1]*pc[1]-dc[2]*pc[2];

	if(-EPS<b_s && b_s<EPS)return 0;
	p=b_t/b_s;
	q=b_const/b_s;

	/* e_tt*t*t+e_t*t+e_const=0 */
	e_tt=a_ss*p*p+a_ts*p+a_tt;
	e_t=(2*a_ss*p+a_ts)*q+a_s*p+a_t;
	e_const=a_ss*q*q+a_s*q+a_const;

	/* 一次方程式を解く */
	if(-EPS<e_tt && e_tt<EPS) {
		if(-EPS<e_t && e_t<EPS) {
			/* 解が無いまたは無限個ある */
			return 0;
		} else {
			ot[0]=-e_const/e_t;
			os[0]=p*ot[0]+q;
			return 1;
		}
	}

	/* 二次方程式を解く */
	e_D=e_t*e_t-4.0*e_tt*e_const;
	if(e_D<=-EPS) {
		return 0;
	} else if(e_D<EPS) {
		ot[0]=-e_t/(2.0*e_tt);
		os[0]=p*ot[0]+q;
		return 1;
	} else {
		double D_sqrt=sqrt(e_D);
		ot[0]=(-e_t-D_sqrt)/(2.0*e_tt);
		os[0]=p*ot[0]+q;
		ot[1]=(-e_t+D_sqrt)/(2.0*e_tt);
		os[1]=p*ot[1]+q;
		return 2;
	}
}

コメント

まだコメントがありません。最初にコメントを残しませんか?


このウンコードに臭った人は、こちらのウンコードにも臭ってます

[JavaScript] これではまった

このエントリーをはてなブックマークに追加

しばらくなやんだよ。なんでだよといいたか...

var a=b=3,//これはOK
before=result=new Arr...

鑑賞する »

[C++] 横着はやめて

このエントリーをはてなブックマークに追加

初期化子書くのが面倒なのは分かりますが…...

class hoge
{
public:
	hoge() { memset...

鑑賞する »

[Java] is禁止令

このエントリーをはてなブックマークに追加

ウンコードの趣旨とは違い、レビューで指摘...

// Mod yamada Start

// 一般的に考えて真偽値を返すメ...

鑑賞する »