题意:求一条射线经过一系列球反射后的反射点
分析:从起点出发,求出射线与球的最近交点,然后更改反射线为入射线循环找射线与球的最近交点,直到没有球与射线相交。
#include < iostream >
#include < cmath >
using namespace std;
struct point{
double x,y,z;
point( double xx = 0 , double yy = 0 , double zz = 0 ){ // 构造函数
x = xx,y = yy,z = zz;
}
point operator ^ ( double h){
return point(x * h,y * h,z * h);
}
double operator ^ (point h){ // 点乘
return x * h.x + y * h.y + z * h.z;
}
point operator + (point h){
return point(x + h.x,y + h.y,z + h.z);
}
point operator - (point h){
return point(x - h.x,y - h.y,z - h.z);
}
point operator * (point b){ // 叉乘
return point(y * b.z - b.y * z, z * b.x - b.z * x, x * b.y - b.x * y);
}
double len2() const {
return x * x + y * y + z * z;
}
double len() const {
return sqrt(len2());
}
point turnlen( double l) const { // 改变长度
double r = l / len();
return point(x * r,y * r,z * r);
}
void input()
{
scanf( " %lf%lf%lf " , & x, & y, & z);
}
}p1,p2,ans;
struct sphere{
point c;
double r;
void input(){
c.input();
scanf( " %lf " , & r);
}
}sph[ 110 ];
int n;
const double eps = 1e - 8 ;
int sgn( double x)
{
if (fabs(x) < eps) return 0 ;
return x > 0 ? 1 : - 1 ;
}
bool intersection(sphere s,point p1,point p2,point & c) // 求p2-p1与球s的交点c
{
double d = ((p1 - s.c) * (p2 - s.c)).len() / (p1 - p2).len(); // 球心到p2-p1的距离
if (sgn(d - s.r) >= 0 )
return false ;//pp 球心与直线p2-p1的垂足
point pp = (sgn(d) == 0 ? s.c:s.c + ((p1 - s.c) * (p2 - s.c) * (p1 - p2)).turnlen(d) );if (sgn((pp - p1) ^ (p2 - p1)) <= 0 ) // 如果pp在p2-p1的反向延长线上 返回false
return false ;
c = pp + (p1 - p2).turnlen(sqrt(s.r * s.r - d * d));
return true ;
}
point reflection(point p1,point rep,point c) // p1关于rep-c的对称点
{
double d = ((rep - p1) * (c - p1)).len() / (rep - c).len();
return p1 + ((rep - p1) * (c - p1) * (rep - c)).turnlen(d * 2.0 );
}
void compute()
{
while ( true ){
point c;
int k =- 1 ;
for ( int i = 0 ;i < n;i ++ ) // 找到与射线相交的最近的球
{
point tmp;
if (intersection(sph[i],p1,p2,tmp)){
if (k ==- 1 || sgn((tmp - p1).len() - (c - p1).len()) < 0 ){
c = tmp;
k = i;
}
}
}
if (k ==- 1 )
break ;
p2 = reflection(p1,sph[k].c,c); // p2反射线上一点
p1 = c; // 反射点
}
ans = p1;
}
int main()
{
while (scanf( " %d " , & n),n)
{
p1 = point();
p2.input();
for ( int i = 0 ;i < n;i ++ )
sph[i].input();
compute();
printf( " %.8lf %.8lf %.8lf\n " ,ans.x,ans.y,ans.z);
}
return 0 ;
}