• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            算法學社
            記錄難忘的征途
            posts - 141,comments - 220,trackbacks - 0
            題目描述:

               給一個點光源(x0,y0),向(x1,y1)處發射射線。p0,p1,p2三個點是三棱鏡,折射率為n。求最后光線與x軸的交點。

            算法分析:
               
               此題非常爽... 各種幾何...

               首先判斷射線是否和p0,p1,p2構成的三條線段相交,如果相交,判斷交點與(x0,y0)的距離,來確定第一個折射面。
               求交的過程不多說了,我用的是叉積求面積的方法。

               利用角度各種加減計算出入射光線與法線的夾角(可正可負)。從而計算出射光線line1。

               再用相同的方法計算出射光線2。這里需要判斷全發射的情況。 然后計算與x軸的交點就可以了。

            #include<cstdio>
            #include<iostream>
            #include<complex>
            #include<cmath>
            using namespace std;
            #define Y imag
            #define X real
            const double eps = 1e-9;
            const char *err = "Error";
            const double pi = acos(-1.0);
            typedef complex<double> pnt;
            static double dot(const pnt &a, const pnt& b) {return X(conj(a)*b);}
            static double cross(const pnt &a, const pnt &b) {return imag(conj(a)*b);}
            // final judge
            void work(const pnt& s, double argu) {
                while(argu<0) argu+=2*pi;
                while(argu >= 2*pi) argu -=2*pi;
                if(argu < pi+eps) {
                    puts(err);
                    return ;
                }
                argu = - argu;
            //    cout<<argu<<endl;
                printf("%.3lf\n", X(s) +( abs(argu + 3*pi/2)<eps ? 0 :  Y(s)/tan(argu) ));
            }
            // segment intersection
            pnt jdg(const pnt& p0, const pnt& p1,const pnt& p3, const pnt& p2){
                if(cross(p3-p0,p1-p0) * cross(p2-p0,p1-p0) > -eps) return p0;
                double s1 = cross(p2-p1,p0-p1), s2 = cross(p3-p1,p0-p1);
                s1 = abs(s1), s2 = abs(s2);
                double x = (X(p2) *s2 + X(p3)*s1) / (s1+ s2);
                double y = (Y(p2) *s2 + Y(p3)*s1) / (s1+ s2);
                pnt p(x,y);
                if(cross(p3-p2,p1-p2)*cross(p3-p2,p0-p2)>0 && abs(p-p0) < abs(p-p1)) return p0;
                return p;
            }
            // cal reflex
            double cal(double arg0, double arg1, double tmp) {
            //    cout<<arg0<<" "<<arg1<<" "<<tmp<<endl;
                double t1 =arg1+pi/2-(arg0+pi);
                double s1 = sin(t1);
                double s2 = s1/tmp;
                //cout<<t1<<" "<<asin(s2)<<endl;    
                if(s2>=1.0 || s2 <=-1.0) return 1e10;
                else return arg1-pi/2-asin(s2);
            }
            // main
            int main(){
                int tst;
                double tmp;
                cin >> tst;
                pnt p[3];
                while(tst--) {
                    double x1,y1,x2,y2;
                    while(cin >> x1 >> y1 >> x2 >> y2){
                        pnt p1(x1,y1), p2(x2,y2), p0;
                        int s = -1;
                        double mx = 1e10;
                        for(int i=0;i<3;i++){
                            cin >> x1 >> y1;
                            p[i] = pnt(x1,y1);
                        }
                        cin >> tmp;
                        // comfirm p0
                        for(int i=0;i<3;i++) {
                            pnt P = jdg(p1,p2,p[i],p[(i+1)%3]);
                            if(P == p1) continue;
                            double v = abs(p1-P);
                            if(v < mx) mx = v, s = i, p0 = P;
                        }
                        if(s == -1){
                            work(p1, arg(p2-p1));
                            continue;
                        }
                        pnt p3;
                        double t = 0;
                        if(cross(p2-p1, p[(s+1)%3] - p[s])<0)t = pi;
                        double arg0 = cal(arg(p2-p1),arg(p[(s+1)%3] - p[s])+t,tmp);
                        pnt np = pnt(X(p0) + 200*cos(arg0), Y(p0) + 200*sin(arg0));
                        // use p0,arg0 to comfirm p3
            //            cout<<"p0 :"<<X(p0)<<" "<<Y(p0)<<" "<<arg0<<endl;
            //            cout<<"np :"<<X(np)<<" "<<Y(np)<<endl;
                         int k = -1;
                        for(int i=0;i<3;i++) {
                            if(i==s) continue;
                            pnt P = jdg(p0,np,p[i],p[(i+1)%3]);
                            if(P == p0) continue;
                            k = i;p3 = P;
                        }
                        // p3 arg1 x-axis
                        t = 0;
                        if(cross(p3-p0, p[(k+1)%3] - p[k])<0)t = pi;
                        double arg1 = cal(arg(p3 - p0), arg(p[(k+1)%3] - p[k])+t, 1.0/tmp);
            //            cout<<"p3: "<<" "<<X(p3)<<" "<<Y(p3)<<" "<<arg1<<endl;
                        if(arg1 == 1e10) {
                            puts(err);
                            continue;
                        }
                        work(p3,arg1);
                    }
                }
            }
            posted on 2012-08-05 14:35 西月弦 閱讀(464) 評論(0)  編輯 收藏 引用 所屬分類: 解題報告
            久久成人影院精品777| 国产色综合久久无码有码| 日韩久久久久久中文人妻| 久久亚洲AV成人无码电影| 精品国产乱码久久久久久郑州公司 | 国产三级久久久精品麻豆三级| 久久久久AV综合网成人| 亚洲精品NV久久久久久久久久| 久久精品aⅴ无码中文字字幕不卡| 久久777国产线看观看精品| 日批日出水久久亚洲精品tv| 国内精品人妻无码久久久影院 | 国内精品伊人久久久久| 青春久久| 亚洲天堂久久精品| 99久久综合狠狠综合久久止| 青青草原精品99久久精品66| 精品久久久久中文字| 久久九九青青国产精品| 久久亚洲国产精品一区二区| 久久AV无码精品人妻糸列| 综合久久一区二区三区| 99久久99久久精品国产片| AV狠狠色丁香婷婷综合久久| 少妇无套内谢久久久久| 久久SE精品一区二区| 一极黄色视频久久网站| 欧美粉嫩小泬久久久久久久| 日韩一区二区三区视频久久| 久久香蕉国产线看观看乱码| 久久久久久久人妻无码中文字幕爆| 四虎久久影院| 亚洲欧洲精品成人久久奇米网| 久久久久无码国产精品不卡| 思思久久99热只有频精品66| 久久精品免费全国观看国产| 久久一本综合| 久久婷婷人人澡人人爽人人爱| 久久国产AVJUST麻豆| 亚洲第一极品精品无码久久| 青青草国产精品久久|