讨论 / 纯粹的数学题,who can do it?!
desprado2 2013-01-02 16:58:00
点我顶贴 收藏 删除
rt
#1 drcool@2014-01-16 21:50:38
回复 删除
先将(dx,dy)正规化,即模是1,射线和圆求交,(x+t*dx,y+t*dy),t必须大于0,取t的最小值就是和射线最先碰到的圆。

求到交点后,连接圆心和交点的向量设为z,从圆心指向交点,向量正规化,求该向量和(dx,dy)的向量点积的绝对值,设为w,((dx,dy)+w*z)*2-(dx,dy)即为反射向量,正规化该向量,进行下一轮计算。

ps: w*z是反射向量在w上的投影,(dx,dy)+w*z求出了垂直于w的向量....具体的画个图就明白了,利用向量运算的平行四边形法则进行推导......

#2 沧海一声喵@2018-01-25 19:27:48
回复 删除
#include <cstdio>

#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;}

查看更多回复
提交回复