求到交点后,连接圆心和交点的向量设为z,从圆心指向交点,向量正规化,求该向量和(dx,dy)的向量点积的绝对值,设为w,((dx,dy)+w*z)*2-(dx,dy)即为反射向量,正规化该向量,进行下一轮计算。
ps: w*z是反射向量在w上的投影,(dx,dy)+w*z求出了垂直于w的向量....具体的画个图就明白了,利用向量运算的平行四边形法则进行推导......
#include <cmath>
#include <algorithm>
#include <vector>
using namespace std;
typedef struct yuan{
int num;
double x,y,d,r;
}yuan;
int cmp(const yuan &s,const yuan &t){
return s.d<t.d;}
int main(){
yuan h[26];int k,n,i,flag=1;
double x,y,dx,dy,p,x1,y1,a,b,w;vector<int> v;
scanf("%d",&n);
for(k=1;k<=n;k++){
scanf("%lf%lf%lf",&h[k].x,&h[k].y,&h[k].r);
h[k].num=n+1-k;}
scanf("%lf%lf%lf%lf",&x,&y,&dx,&dy);
p=sqrt(dx*dx+dy*dy);dx=dx/p;dy=dy/p;
while(flag&&v.size()<=10){
flag=0;
for(i=1;i<=n;i++) h[i].d=sqrt((h[i].x-x)*(h[i].x-x)+(h[i].y-y)*(h[i].y-y));
sort(h+1,h+n+1,cmp);
for(i=1;i<=n;i++){
p=(h[i].x-x)*dx+(h[i].y-y)*dy;
if(p<=h[i].d&&p>=sqrt(h[i].d*h[i].d-h[i].r*h[i].r)) {flag=1;break;}}
if(i<=n){
v.push_back(h[i].num);
a=(h[i].x-x)*dx+(h[i].y-y)*dy;
p=a-sqrt(a*a-h[i].d*h[i].d+h[i].r*h[i].r);
x1=x+p*dx;y1=y+p*dy;
w=(x1-h[i].x)*dx+(y1-h[i].y)*dy;
w=fabs(w/h[i].r);
a=2*w*(x1-h[i].x)/h[i].r+dx;
b=2*w*(y1-h[i].y)/h[i].r+dy;
x=x1;y=y1;dx=a;dy=b;}}
if(v.size()>10){
for(i=0;i<10;i++) printf("%d ",v[i]);
printf("...");}
else{
for(i=0;i<v.size();i++) printf("%d ",v[i]);
printf("fine");}
return 0;}