예제 #1
0
    private void drawClosingLine2(VesselElements ve, double firstx, double firsty, double firstz, double lastx, double lasty, double lastz)
    {
        Vector3 First = new Vector3((float)firstx, (float)firsty, (float)firstz);
        Vector3 Last  = new Vector3((float)lastx, (float)lasty, (float)lastz);

        double[] result   = new double[3];
        double[] location = new double[3];

        for (float i = 0.0f; i <= 1.0f; i += 0.1f)
        {
            Vector3 point = Vector3.Slerp(First, Last, i);
            point.Normalize();
            result[0] = point.x;
            result[1] = point.y;
            result[2] = point.z;
            Coordinate.transformICRStoGCS(ve, result, location);
            if (i == 0.5f)
            {
                Debug.Log("First=" + firstx + ":" + firsty + ":" + firstz);
                Debug.Log("Last=" + lastx + ":" + lasty + ":" + lastz);
                Debug.Log("result=" + result[0] + ":" + result[1] + ":" + result[2]);
                Debug.Log("result=" + location[0] + ":" + location[1]);
            }
            drawShadowTexture(location[0], location[1], Color.red);
        }
    }
예제 #2
0
    //本影・半影の輪郭を計算する。qは角度で与えられる
    private static void getOutline(VesselElements ve, double l, double tan, double q, double[] result)
    {
        if (result.Length != 3)
        {
            return;
        }

        double x      = 0.0;
        double y      = 0.0;
        double z      = 1.0; //zの初期値
        double Q      = q / 180 * Math.PI;
        double lastz  = 0.0; //前のzの値
        double delta  = 0.0;
        double cos_d  = Math.Cos(ve.getDeclination() / 180 * Math.PI);
        double sin_d  = Math.Sin(ve.getDeclination() / 180 * Math.PI);
        double cos_d2 = cos_d * cos_d;
        int    count  = 0;

        while (Math.Abs(z - lastz) > 10e-7)//zが10の-7乗未満に収束しない場合ループ
        {
            lastz = z;
            delta = l - z * tan;
            x     = ve.getX0() + delta * Math.Cos(Q);
            y     = ve.getY0() + delta * Math.Sin(Q);

            double x2 = x * x;
            double y2 = y * y;

            z = (-Constants.e2 * y * cos_d * sin_d + Math.Sqrt((1 - Constants.e2) * (1.0 - x2 - y2 - Constants.e2 * (1.0 - x2) * cos_d2))) /
                (1.0 - Constants.e2 * cos_d2);

            if (count++ > 10)
            {
                break;         //10回を超えたら強制的に打ち切り
            }
        }

        result[0] = x;
        result[1] = y;
        result[2] = z;
    }
예제 #3
0
    //基準面上の半影における点の偏角Qを計算する
    public static double getPenumbralQ(VesselElements ve, double[] point)
    {
        if (point == null || point.Length != 3)
        {
            return(Double.NaN);
        }

        double delta = ve.getL1() - point[2] * ve.getTanf1();

        double Q = Math.Acos((point[0] - ve.getX0()) / delta) / Math.PI * 180.0;

        if ((point[1] - ve.getY0()) < 0.0)
        {
            Q = -Q;                            //y方向が負ならば角度を反転する。
        }
        if (Q < 0.0)
        {
            Q += 360.0;
        }

        return(Q);
    }
예제 #4
0
    //半影と地球外周楕円の交点を計算する
    public static void getCrossPoint(VesselElements ve, double[] result1, double[] result2)
    {
        if (result1.Length != 3 || result2.Length != 3)
        {
            return;
        }

        double x0    = ve.getX0();
        double y0    = ve.getY0();
        double l1    = ve.getL1();
        double r0    = Math.Sqrt(x0 * x0 + y0 * y0);
        double theta = Math.Atan2(y0, x0); //ラジアン。変換しない。
        double d     = ve.getDeclination() / 180.0 * Math.PI;
        double cos_d = Math.Cos(d);
        double sin_d = Math.Sin(d);

        double E2 = (Constants.e2 * cos_d * cos_d) / (1.0 - Constants.e2 * sin_d * sin_d);

        double rhoplus   = 1.0; //初期値
        double gammaplus = 0.0;

        int count = 0;

        //正の値の近似計算
        while (true)
        {
            double angle = Math.Acos((r0 * r0 + rhoplus * rhoplus - l1 * l1) / (2.0 * r0 * rhoplus)); //近似計算//正の値
            if (angle < 0.0)
            {
                angle = -angle;
            }

            gammaplus = angle + theta;
            double newrhoplus = Math.Sqrt((1.0 - E2) / (1.0 - E2 * Math.Cos(gammaplus) * Math.Cos(gammaplus)));

            double dif = Math.Abs(newrhoplus - rhoplus);
            rhoplus = newrhoplus;

            if (dif < 10e-7)
            {
                break;
            }
            if (count++ > 8)
            {
                break;
            }
        }

        double rhominus   = 1.0;
        double gammaminus = 0.0;

        count = 0;

        //負の値の近似計算
        while (true)
        {
            double angle = Math.Acos((r0 * r0 + rhominus * rhominus - l1 * l1) / (2.0 * r0 * rhominus)); //近似計算//正の値
            if (angle > 0.0)
            {
                angle = -angle;
            }

            gammaminus = angle + theta;
            double newrhominus = Math.Sqrt((1.0 - E2) / (1.0 - E2 * Math.Cos(gammaminus) * Math.Cos(gammaminus)));

            double dif = Math.Abs(newrhominus - rhominus);
            rhominus = newrhominus;

            if (dif < 10e-7)
            {
                break;
            }
            if (count++ > 8)
            {
                break;
            }
        }
        result1[0] = rhoplus * Math.Cos(gammaplus);
        result1[1] = rhoplus * Math.Sin(gammaplus);
        result1[2] = 0.0;
        result2[0] = rhominus * Math.Cos(gammaminus);
        result2[1] = rhominus * Math.Sin(gammaminus);
        result2[2] = 0.0;

        //    System.out.println("rhoplus = " + rhoplus + " rhominus =" + rhominus);
    }
예제 #5
0
 //半影の輪郭を計算する
 public static void getPenumbralOutline(VesselElements ve, double q, double[] result)
 {
     getOutline(ve, ve.getL1(), ve.getTanf1(), q, result);
 }
예제 #6
0
    //食分を計算する
    public static void getD(VesselElements ve, double longitude, double latitude, double altitude)//, double[] result)
    {
        longitude = longitude / 180.0 * Math.PI;
        latitude  = latitude / 180.0 * Math.PI;

        //測地緯度と地心緯度の差を計算
        double deltalat = 3.3584196 * 0.001 * Math.Sin(2 * latitude) - 5.635 * 0.000001 * Math.Sin(4 * latitude) + 1.7 * Math.Pow(10, -8) * Math.Sin(8 * latitude);

        //地心直交座標を計算
        double sinlat = Math.Sin(latitude);
        double N      = 1 / Math.Sqrt(1 - Constants.e2 * sinlat * sinlat);

        double u = (N + altitude) * Math.Cos(latitude) * Math.Cos(longitude);
        double v = (N + altitude) * Math.Cos(latitude) * Math.Sin(longitude);
        double w = (N * (1.0 - Constants.e2) + altitude) * Math.Sin(latitude);

        //基準座標
        double myu = ve.getMyu();
        double d   = ve.getDeclination();

        double x = u * Math.Sin(myu) + v * Math.Cos(myu);
        double y = -u *Math.Cos(myu) * Math.Sin(d) + v * Math.Sin(myu) * Math.Sin(d) + w * Math.Cos(d);

        double z = u * Math.Cos(myu) * Math.Cos(d) - v * Math.Sin(myu) * Math.Cos(d) + w * Math.Sin(d);

        //r,deltaを計算する
        double r     = Math.Sqrt(x * x + y * y + z * z);
        double xdiff = x - ve.getX0();
        double ydiff = y - ve.getY0();
        double delta = Math.Sqrt(xdiff * xdiff + ydiff * ydiff);

        //cosQ, sinQを計算する
        double cosQ = xdiff / delta;
        double sinQ = ydiff / delta;

        //月の北極方向角を計算する
        double tanphai = (xdiff / ydiff) + 0.0000426 * xdiff * Math.Tan(d) / (sinQ * sinQ);
        double moon_angle_to_northpole = Math.Atan(tanphai) / Math.PI * 180;

        if (moon_angle_to_northpole < 0)
        {
            moon_angle_to_northpole += 360;
        }
        else if (moon_angle_to_northpole > 360)
        {
            moon_angle_to_northpole -= 360;
        }
        if (ydiff > 0)
        {
            if (moon_angle_to_northpole > 270 | moon_angle_to_northpole < 90)
            {
                moon_angle_to_northpole += 180;
            }
        }
        else if (ydiff < 0)
        {
            if (moon_angle_to_northpole > 90 & moon_angle_to_northpole < 270)
            {
                moon_angle_to_northpole += 180;
            }
        }
        if (moon_angle_to_northpole > 360)
        {
            moon_angle_to_northpole -= 360;
        }

        //天頂の北極方位角を計算する
        double tannyu = x / y - delta * latitude * r * x * Math.Cos(d) / (y * y * Math.Cos(latitude));
        double zenith_angle_to_northpole = Math.Atan(tannyu) / Math.PI * 180;

        if (zenith_angle_to_northpole < 0)
        {
            zenith_angle_to_northpole += 360;
        }
        else if (zenith_angle_to_northpole > 360)
        {
            zenith_angle_to_northpole -= 360;
        }

        if (y < 0)
        {
            if (zenith_angle_to_northpole > 270 | zenith_angle_to_northpole < 90)
            {
                zenith_angle_to_northpole += 180;
            }
        }
        else if (y > 0)
        {
            if (zenith_angle_to_northpole > 90 & zenith_angle_to_northpole < 270)
            {
                zenith_angle_to_northpole += 180;
            }
        }
        if (zenith_angle_to_northpole > 360)
        {
            zenith_angle_to_northpole -= 360;
        }

        double omega = moon_angle_to_northpole - zenith_angle_to_northpole;

        if (Math.Abs(omega) > 180)
        {
            if (omega < 0)
            {
                omega += 360;
            }
            else if (omega > 0)
            {
                omega -= 360;
            }
        }
        //omega = omega / Math.PI * 180.0;
        // Debug.Log("omega= " + omega);
        //食分を求める
        double D = (ve.getL1() - z * ve.getTanf1() - delta) / (ve.getL1() + ve.getL2() - z * (ve.getTanf1() + ve.getTanf2()));
        //debug

/*
 * Debug.Log("deltalat = " + deltalat);
 * Debug.Log("x0 = "+ ve.getX0());
 * Debug.Log("y0 = " + ve.getY0());
 * Debug.Log("d = " + (ve.getDeclination() / Math.PI * 180.0));
 * Debug.Log("l1 = " + ve.getL1());
 * Debug.Log("l2 = " + ve.getL2());
 * Debug.Log("tanf1 = " + ve.getTanf1());
 * Debug.Log("tanf2 = " + ve.getTanf2());
 * Debug.Log("myu = " + myu);
 * Debug.Log("x = " + x);
 * Debug.Log("y = " + y);
 * Debug.Log("z = " + z);
 * Debug.Log("r = " + r);
 * Debug.Log("delta = " + delta);
 * Debug.Log("sinQ = " + sinQ);
 * Debug.Log("(x - x0)/ (y - y0) = " + (xdiff / ydiff));
 * Debug.Log("pais(x-x0)tan(d) / sin2 Q  = " + (0.0000426 * xdiff * Math.Tan(d) / (sinQ * sinQ)));
 * Debug.Log("Tan(phai) = " + tanphai);
 * Debug.Log("phai = " + moon_angle_to_northpole);
 * Debug.Log("x / y = " + (x / y));
 * Debug.Log("delta phai = " + (delta * latitude * r * x * Math.Cos(d) / (y * y * Math.Cos(latitude))));
 * Debug.Log("tan(nyu) = " + tannyu);
 * Debug.Log("nyu = " + zenith_angle_to_northpole);
 * Debug.Log("omega = " + omega);
 * Debug.Log("D=" + D);
 */
//debug終わり
    }
예제 #7
0
    //画面を更新する(球体地図)
    public void updateScreen2()
    {
        double hinode_keido, hinoiri_keido, asayake, higure;
        int    hinoiriX = 0, hinodeX = 0;
        int    asayakeX = 0, higureX = 0;
        double x, y;
        double halfPI = Math.PI / 2.0;

        //double scrDist = (scrWidth / 2.0) / Math.Tan(scrAngle / 180.0 * Math.PI);

        //if (screen == null | screen2 == null) return;

        //イメージを初期化

        Color opaque = new Color(0, 0, 0, 0);

        for (int i = 0; i < shadow.width; i++)
        {
            for (int j = 0; j < shadow.height; j++)
            {
                shadow.SetPixel(i, j, opaque);
            }
        }

        EquatorialCoordinate sun  = new EquatorialCoordinate();
        EquatorialCoordinate moon = new EquatorialCoordinate();

        double[] result   = new double[3];
        double[] result2  = new double[3];
        double[] location = new double[2];
        double   asc      = 0.0;
        double   dec      = 0.0;
        double   moonasc  = 0.0;
        double   moondec  = 0.0;

        try
        {
            SunAndMoon.getSunRightAscension(utc, result);
            sun.setRightAscension(result[0]);
            sun.setCelestialDeclination(result[1]);
            sun.setDistance(result[2]);
            asc = result[0]; //赤経
            dec = result[1]; //赤緯

            SunAndMoon.getMoonRightAscension(utc, result);
            moon.setRightAscension(result[0]);
            moon.setCelestialDeclination(result[1]);
            moon.setDistance(result[2]);
            moonasc = result[0];
            moondec = result[1];
        }
        catch (Exception) { Debug.Log("Exception1 ");  return; }

        double phai0 = Almanac.getGreenidgeSiderealTime(utc);//グリニッジ恒星時
        //恒星時をもとに、背景の回転を行う(恒星時は春分点の時角)
        Material skybox = RenderSettings.skybox;

        skybox.SetFloat("_Rotation", (float)-phai0);//時角のマイナス方向に回転。skyboxのマテリアルは左右が逆

        //太陽位置計算(orbiterと同じコード)
        {
            double Theta = phai0 - asc;
            if (Theta < 0)
            {
                Theta += 360.0;
            }
            double DegToRad    = Math.PI / 180;
            double denominator = (Math.Sin(dec * DegToRad) * Math.Cos(90.0 * DegToRad) - Math.Cos(dec * DegToRad) * Math.Sin(90.0 * DegToRad) * Math.Cos(Theta * DegToRad));
            double A           = Math.Atan((-Math.Cos(dec * DegToRad) * Math.Sin(Theta * DegToRad)) / denominator);
            double h           = Math.Asin(Math.Sin(dec * DegToRad) * Math.Sin(90.0 * DegToRad) + Math.Cos(dec * DegToRad) * Math.Cos(90.0 * DegToRad) * Math.Cos(Theta * DegToRad));
            A = A / DegToRad;
            h = h / DegToRad;
            //Arctanの象限を検討せよ
            if (denominator > 0)
            {
                //何故か解説書とは逆だが、分母が正の時に180度加算して象限を変える必要がある
                A += 180.0;
            }
            Vector3 sunvector = new Vector3(1.0f, 0.0f, 0.0f);
            sunvector = Quaternion.Euler(0.0f, 0.0f, (float)h) * sunvector;
            sunvector = Quaternion.Euler(0.0f, (float)A, 0.0f) * sunvector;


            float ratio = 1500.0f / sunvector.magnitude;
            sunvector *= ratio;

            GameObject game = GameObject.Find("Directional Light");
            if (game != null)
            {
                game.transform.position = sunvector;
                Vector3 forward = sunvector;
                forward.Normalize();
                game.transform.forward = -forward;
            }
        }
        //日の出・日の入りの同時線を描く

        double dist                 = sun.getDistance();
        double parallax             = SunAndMoon.getSunParallax(dist);//太陽視差
        double k                    = SunAndMoon.getSunriseAltitude(SunAndMoon.getSunDiameter(dist), 0.0, SunAndMoon.refraction, parallax);
        double celestialdeclination = sun.getCelestialDeclination();

        for (int i = -90; i < 90; i++)
        {
            //緯度を取得
            double latitude = i;//getLatitudeFromY(Yequator - i);

            //緯度を元に時角を計算する
            double jikaku = SunAndMoon.getTimeAngle(k, celestialdeclination, latitude);

            if (!Double.IsNaN(jikaku))//時角がNaNでない
            {
                hinode_keido  = SunAndMoon.reviseAngle(-jikaku + sun.getRightAscension() - phai0);
                hinoiri_keido = SunAndMoon.reviseAngle(jikaku + sun.getRightAscension() - phai0);
                //   hinodeX =(int)getXfromLongitude(hinode_keido);
                //   hinoiriX = (int)getXfromLongitude(hinoiri_keido);//昼側か調べる
                drawShadowTexture(hinode_keido, latitude, Color.white);
                drawShadowTexture(hinoiri_keido, latitude, Color.white);
            }
        }

        //輪郭の描画
        VesselElements ve = new VesselElements(sun, moon, utc);

        SolarEclipse.getCrossPoint(ve, result, result2);
        double maxQ = SolarEclipse.getPenumbralQ(ve, result);
        double minQ = SolarEclipse.getPenumbralQ(ve, result2);

        //Debug.Log("MaxQ = " + maxQ + " minQ = " + minQ);

        //月位置計算(orbiterと同じコード)
        {
            double Theta = phai0 - moonasc;
            if (Theta < 0)
            {
                Theta += 360.0;
            }
            double DegToRad    = Math.PI / 180;
            double denominator = (Math.Sin(moondec * DegToRad) * Math.Cos(90.0 * DegToRad) - Math.Cos(moondec * DegToRad) * Math.Sin(90.0 * DegToRad) * Math.Cos(Theta * DegToRad));
            double A           = Math.Atan((-Math.Cos(moondec * DegToRad) * Math.Sin(Theta * DegToRad)) / denominator);
            double h           = Math.Asin(Math.Sin(moondec * DegToRad) * Math.Sin(90.0 * DegToRad) + Math.Cos(moondec * DegToRad) * Math.Cos(90.0 * DegToRad) * Math.Cos(Theta * DegToRad));
            A = A / DegToRad;
            h = h / DegToRad;
            //Arctanの象限を検討せよ
            if (denominator > 0)
            {
                //何故か解説書とは逆だが、分母が正の時に180度加算して象限を変える必要がある
                A += 180.0;
            }
            Vector3 sunvector = new Vector3(1.0f, 0.0f, 0.0f);
            sunvector = Quaternion.Euler(0.0f, 0.0f, (float)h) * sunvector;
            sunvector = Quaternion.Euler(0.0f, (float)A, 0.0f) * sunvector;
            float ratio = (float)(moon.getDistance() * Constants.AUde * 3.16f) / sunvector.magnitude;
            sunvector *= ratio;

            //

            //      Debug.Log("moondist = " + moon.getDistance());
            GameObject game = GameObject.Find("Moon");
            if (game != null)
            {
                game.transform.position = sunvector;
            }
        }

        /*  Vector3 moonPos = new Vector3((float)ve.getX0(), (float)ve.getY0(), (float)ve.getZ0());
         *  moonPos.Normalize();
         *  moonPos *= 20;
         *  GameObject moonobj = GameObject.Find("Moon");
         *
         *  if (moonobj!= null)
         *   {
         *    moonobj.transform.position = moonPos;
         *   }
         */
        //半影の描画
        if (Double.IsNaN(maxQ) && Double.IsNaN(minQ))
        {
            double first_longitude = Double.NaN;
            double first_latitude  = Double.NaN;
            double last_longitude  = Double.NaN;
            double last_latitude   = Double.NaN;

            for (double i = 0.0; i <= 360.0; i += 0.2)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result);
                if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
                {
                    continue;                                                                     //NaNが含まれていたらスキップする
                }
                if (first_longitude == double.NaN | first_latitude == double.NaN)
                {
                    first_longitude = result[0];
                    first_latitude  = result[1];
                }
                last_longitude = result[0];
                last_latitude  = result[1];

                Coordinate.transformICRStoGCS(ve, result, location);
                drawShadowTexture(location[0], location[1], Color.red);
            }
            //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude);
        }
        else if (!Double.IsNaN(maxQ) && !Double.IsNaN(minQ))
        {
            double first_x = double.NaN;
            double first_y = double.NaN;
            double first_z = double.NaN;
            double last_x  = double.NaN;
            double last_y  = double.NaN;
            double last_z  = double.NaN;

            if ((maxQ - minQ) >= 0.0)
            {
                maxQ -= 360.0;
            }
            SolarEclipse.getPenumbralOutline(ve, maxQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            //Debug.Log("MaxQ :" + location[0] + ":" + location[1]+ ":" + maxQ);
            SolarEclipse.getPenumbralOutline(ve, minQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            //Debug.Log("MinQ :" + location[0] + ":" + location[1] + ":" + minQ);

            /*
             *    //maxQが通常の計算でNaNとなる場合に備えて、強制的に描画する。
             *    SolarEclipse.getPenumbralOutline(ve, maxQ, result);
             *    result[2] = -0.01;//強制的に基準面に設定する
             *    Coordinate.transformICRStoGCS(ve, result, location);
             *    drawShadowTexture(location[0], location[1], Color.black);
             */
            for (double i = maxQ /*Math.Ceiling(maxQ)*/; i < minQ; i += 0.2)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result);
                if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
                {
                    continue;                                                                     //NaNが含まれていたらスキップする
                }
                if (Double.IsNaN(first_x) | Double.IsNaN(first_y) | Double.IsNaN(first_z))
                {
                    first_x = result[0];
                    first_y = result[1];
                    first_z = result[2];
                }
                last_x = result[0];
                last_y = result[1];
                last_z = result[2];

                Coordinate.transformICRStoGCS(ve, result, location);

                drawShadowTexture(location[0], location[1], Color.red);
            }
            {
                SolarEclipse.getPenumbralOutline(ve, minQ, result);
                if (!Double.IsNaN(result[0]) & !Double.IsNaN(result[1]) & !Double.IsNaN(result[2]))
                {
                    Coordinate.transformICRStoGCS(ve, result, location);
                    last_x = result[0];
                    last_y = result[2];
                    last_z = result[1];
                    drawShadowTexture(location[0], location[1], Color.red);
                }
            }
            //drawClosingLine2(ve, first_x, first_y, first_z, last_x, last_y, last_z);
            //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude);

            /*
             *    //minQが通常の計算でNaNとなる場合に備えて、強制的に描画する。
             *    SolarEclipse.getPenumbralOutline(ve, minQ, result);
             *    result[2] = -0.01;//強制的に基準面に設定する
             *    Coordinate.transformICRStoGCS(ve, result, location);
             *    drawShadowTexture(location[0], location[1], Color.red);
             */
        }

        //本影の描画
        for (int i = 0; i <= 360; i += 5)
        {
            SolarEclipse.getUmbralOutline(ve, (double)i, result);
            if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
            {
                continue;                                                                       //NaNが含まれていたらスキップする
            }
            Coordinate.transformICRStoGCS(ve, result, location);
            drawShadowTexture(location[0], location[1], Color.black);
        }
        GameObject earthobj = GameObject.Find("perfectsphere");

        Material[] mats = earthobj.GetComponent <Renderer>().materials;
        Debug.Log("elements =" + mats.Length);
        mats[0].SetTexture("_MainTex", (Texture)shadow);
        //mats[1].SetTexture("_EmissionMap", shadow);
        //repaint();
    }
예제 #8
0
    public void drawLines()
    {
        //テクスチャ初期化
        Color opaque = new Color(0, 0, 0, 0);

        for (int i = 0; i < shadow.width; i++)
        {
            for (int j = 0; j < shadow.height; j++)
            {
                shadow.SetPixel(i, j, opaque);
            }
        }

        EquatorialCoordinate sun  = new EquatorialCoordinate();
        EquatorialCoordinate moon = new EquatorialCoordinate();

        double[] result   = new double[3];
        double[] result2  = new double[3];
        double[] location = new double[2];
        double   asc      = 0.0;
        double   dec      = 0.0;
        double   moonasc  = 0.0;
        double   moondec  = 0.0;

        try
        {
            SunAndMoon.getSunRightAscension(utc, result);
            sun.setRightAscension(result[0]);
            sun.setCelestialDeclination(result[1]);
            sun.setDistance(result[2]);
            asc = result[0]; //赤経
            dec = result[1]; //赤緯

            SunAndMoon.getMoonRightAscension(utc, result);
            moon.setRightAscension(result[0]);
            moon.setCelestialDeclination(result[1]);
            moon.setDistance(result[2]);
            moonasc = result[0];
            moondec = result[1];
        }
        catch (Exception) { Debug.Log("Exception1 "); return; }

        double phai0 = Almanac.getGreenidgeSiderealTime(utc);//グリニッジ恒星時

        //太陽位置を計算してライトの位置と向きを変更する
        {
            //恒星時をもとに、背景の回転を行う(恒星時は春分点の時角)
            Material skybox = RenderSettings.skybox;
            skybox.SetFloat("_Rotation", (float)-phai0);//時角のマイナス方向に回転。skyboxのマテリアルは左右が逆

            //赤緯・赤経は北極から見て時計回り。自覚、恒星時は反時計回り。時角に合わせて計算する
            //float ramda = -(float)((-asc + phai0) * DegToRad);これを書き換えて下の式になる
            float ramda       = (float)((asc - phai0) * DegToRad);
            float psy         = (float)(dec * DegToRad);
            float sundistance = 400;
            float x           = Mathf.Cos(psy) * Mathf.Cos(ramda) * sundistance;
            float y           = Mathf.Cos(psy) * Mathf.Sin(ramda) * sundistance;
            float z           = Mathf.Sin(psy) * sundistance;

            GameObject light  = GameObject.Find("Directional Light");
            Vector3    sunpos = light.transform.position;
            sunpos.Set(x, z, y);
            light.transform.position = sunpos;
            sunpos.Normalize();
            sunpos *= -1;
            light.transform.forward = sunpos;
        }

        /*
         *  //日の出・日の入りの同時線を描く
         *   {
         *    double dist = sun.getDistance();
         *    double parallax = SunAndMoon.getSunParallax(dist);//太陽視差
         *    double k = SunAndMoon.getSunriseAltitude(SunAndMoon.getSunDiameter(dist), 0.0, SunAndMoon.refraction, parallax);
         *    double celestialdeclination = sun.getCelestialDeclination();
         *
         *    for (int i = -90; i < 90; i++)
         *     {
         *      //緯度を取得
         *      double latitude = i;//getLatitudeFromY(Yequator - i);
         *
         *      //緯度を元に時角を計算する
         *      double jikaku = SunAndMoon.getTimeAngle(k, celestialdeclination, latitude);
         *
         *      if (!Double.IsNaN(jikaku))//時角がNaNでない
         *       {
         *        double hinode_keido = SunAndMoon.reviseAngle(-jikaku + sun.getRightAscension() - phai0);
         *        double hinoiri_keido = SunAndMoon.reviseAngle(jikaku + sun.getRightAscension() - phai0);
         *        //   hinodeX =(int)getXfromLongitude(hinode_keido);
         *        //   hinoiriX = (int)getXfromLongitude(hinoiri_keido);//昼側か調べる
         *        drawShadowTexture(hinode_keido, latitude, Color.white);
         *        drawShadowTexture(hinoiri_keido, latitude, Color.white);
         *       }
         *     }
         *   }
         */
        //輪郭の描画
        //ベッセル数
        VesselElements ve = new VesselElements(sun, moon, utc);

        SolarEclipse.getCrossPoint(ve, result, result2);
        //月影と地球外円との交点を調べる
        double maxQ = SolarEclipse.getPenumbralQ(ve, result);
        double minQ = SolarEclipse.getPenumbralQ(ve, result2);

        //Debug.Log("MaxQ = " + maxQ + " minQ = " + minQ);

        //半影の描画
        if (Double.IsNaN(maxQ) && Double.IsNaN(minQ))
        {
            //交点が存在しない場合。月影がすべて地球上に投射されている。

            double first_longitude = Double.NaN;
            double first_latitude  = Double.NaN;
            double last_longitude;
            double last_latitude;
            Color  gray = new Color(0, 0, 0, 0.4f);

            //初期の点
            SolarEclipse.getPenumbralOutline(ve, 0.0, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            last_longitude = location[0];
            last_latitude  = location[1];
            bool fill = true;
            for (double i = 1.0; i <= 360.0; i += 1.0)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result2);
                if (Double.IsNaN(result2[0]) | Double.IsNaN(result2[1]) | Double.IsNaN(result2[2]))
                {
                    fill = false;
                    continue;//NaNが含まれていたらスキップする
                }
                Coordinate.transformICRStoGCS(ve, result2, location);
//         drawShadowTexture(location[0], location[1], gray);
                //Debug.Log("i=" + i + ":" +location[0] + ":" + location[1]);
                drawOutline(last_longitude, last_latitude, location[0], location[1], Color.red);
                last_longitude = location[0];
                last_latitude  = location[1];
            }

            if (fill)
            {
                fillShadow(last_longitude - 2, last_latitude, shadow, gray);
            }

            /*
             *   byte[] pngData = shadow.EncodeToPNG();   // pngのバイト情報を取得.
             *
             *   // ファイルダイアログの表示.
             *   string filePath = EditorUtility.SaveFilePanel("Save Texture", "", shadow.name + ".png", "png");
             *
             *   if (filePath.Length > 0)
             *    {
             *     // pngファイル保存.
             *     File.WriteAllBytes(filePath, pngData);
             *     }
             */
            //Debug.Log(first_longitude + ":" + first_latitude + "::" + last_longitude + ":" + last_latitude);
        }
        else if (!Double.IsNaN(maxQ) && !Double.IsNaN(minQ))//交点が存在する
        {
            double first_x = double.NaN;
            double first_y = double.NaN;
            double first_z = double.NaN;
            double last_x  = double.NaN;
            double last_y  = double.NaN;
            double last_z  = double.NaN;
            Color  gray    = new Color(0, 0, 0, 0.4f);
            if ((maxQ - minQ) >= 0.0)
            {
                maxQ -= 360.0;
            }
            SolarEclipse.getPenumbralOutline(ve, maxQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            //Debug.Log("MaxQ :" + location[0] + ":" + location[1]+ ":" + maxQ);
            SolarEclipse.getPenumbralOutline(ve, minQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            //Debug.Log("MinQ :" + location[0] + ":" + location[1] + ":" + minQ);

            /*
             *    //maxQが通常の計算でNaNとなる場合に備えて、強制的に描画する。
             *    SolarEclipse.getPenumbralOutline(ve, maxQ, result);
             *    result[2] = -0.01;//強制的に基準面に設定する
             *    Coordinate.transformICRStoGCS(ve, result, location);
             *    drawShadowTexture(location[0], location[1], Color.black);
             */
            for (double i = maxQ /*Math.Ceiling(maxQ)*/; i < minQ; i += 0.2)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result);
                if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
                {
                    continue;                                                                     //NaNが含まれていたらスキップする
                }
                if (Double.IsNaN(first_x) | Double.IsNaN(first_y) | Double.IsNaN(first_z))
                {
                    first_x = result[0];
                    first_y = result[1];
                    first_z = result[2];
                }
                last_x = result[0];
                last_y = result[1];
                last_z = result[2];

                Coordinate.transformICRStoGCS(ve, result, location);
                drawShadowTexture(location[0], location[1], gray);
            }

            {
                SolarEclipse.getPenumbralOutline(ve, minQ, result);
                if (!Double.IsNaN(result[0]) & !Double.IsNaN(result[1]) & !Double.IsNaN(result[2]))
                {
                    Coordinate.transformICRStoGCS(ve, result, location);
                    last_x = result[0];
                    last_y = result[2];
                    last_z = result[1];

                    drawShadowTexture(location[0], location[1], gray);
                }
            }
        }

        //本影の描画
        for (int i = 0; i <= 360; i += 5)
        {
            SolarEclipse.getUmbralOutline(ve, (double)i, result);
            if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
            {
                continue;                                                                       //NaNが含まれていたらスキップする
            }
            Coordinate.transformICRStoGCS(ve, result, location);
            drawShadowTexture(location[0], location[1], Color.black);
        }
        //
        shadow.Apply();
    }
예제 #9
0
    public static void transformICRStoGCS(VesselElements ve, double[] point, double[] result)
    {
        if (result.Length != 2)
        {
            return;
        }
        double d = ve.getDeclination();//ラジアン

        //変換行列を生成(縦配置)
        double[][] transmatrix = new double[][] { new double[3], new double[3], new double[3] };

        double[] coordinate1 = new double[] { point[0], point[1], point[2] };
        double[] coordinate2 = new double[3];

        double angle = d - (Math.PI / 2.0);

        transmatrix[0][0] = 1.0;
        transmatrix[0][1] = 0.0;
        transmatrix[0][2] = 0.0;
        transmatrix[1][0] = 0.0;
        transmatrix[1][1] = Math.Cos(angle);
        transmatrix[1][2] = -Math.Sin(angle);
        transmatrix[2][0] = 0.0;
        transmatrix[2][1] = Math.Sin(angle);
        transmatrix[2][2] = Math.Cos(angle);
        Matrix.multiplication31type2(transmatrix, coordinate1, coordinate2);

        angle             = (ve.getGreenidgeSiderealTime() / 180.0 * Math.PI) - ve.getAscension() - (Math.PI / 2.0);
        transmatrix[0][0] = Math.Cos(angle);
        transmatrix[0][1] = -Math.Sin(angle);
        transmatrix[0][2] = 0.0;
        transmatrix[1][0] = Math.Sin(angle);
        transmatrix[1][1] = Math.Cos(angle);
        transmatrix[1][2] = 0.0;
        transmatrix[2][0] = 0.0;
        transmatrix[2][1] = 0.0;
        transmatrix[2][2] = 1.0;
        Matrix.multiplication31type2(transmatrix, coordinate2, coordinate1);

        result[0] = Math.Atan2(coordinate1[1], coordinate1[0]) / Math.PI * 180.0; //経度

        //緯度を求める
        double denominator  = Math.Sqrt(coordinate1[0] * coordinate1[0] + coordinate1[1] * coordinate1[1]); //root(u* u + v* v);
        double coequation1  = coordinate1[2] / denominator;
        double coequation2  = Constants.e2 / denominator;
        double tan_phai     = coequation1;
        double lasttan_phai = -tan_phai;//tan_phaiと一致させないための工夫。
        int    count        = 0;

        while (Math.Abs(tan_phai - lasttan_phai) > 10e-7)
        {
            lasttan_phai = tan_phai;
            tan_phai     = coequation1 + coequation2 * (lasttan_phai / Math.Sqrt(1.0 + (1.0 - Constants.e2) * lasttan_phai * lasttan_phai));

            if (count++ > 10)
            {
                break;
            }
        }
        result[1] = Math.Atan(tan_phai) / Math.PI * 180.0; //緯度
    }
예제 #10
0
    //地球に写る月の影の輪郭を描く
    public void drawLines(DateTime utc)
    {
        EquatorialCoordinate sun  = new EquatorialCoordinate();
        EquatorialCoordinate moon = new EquatorialCoordinate();

        double[] result   = new double[3];
        double[] result2  = new double[3];
        double[] dataset  = new double[7];
        double[] location = new double[2];
        double   asc      = 0.0;
        double   dec      = 0.0;
        double   moonasc  = 0.0;
        double   moondec  = 0.0;
        double   phai0;

        if (mode == PLAYMODE)
        {
            dataholder.getPositions(utc, dataset);
            asc = dataset[0];
            dec = dataset[1];
            sun.setRightAscension(dataset[0]);
            sun.setCelestialDeclination(dataset[1]);
            sun.setDistance(dataset[2]);

            moon.setRightAscension(dataset[3]);
            moon.setCelestialDeclination(dataset[4]);
            moon.setDistance(dataset[5]);
            moonasc = dataset[3];
            moondec = dataset[4];
            phai0   = dataset[6];
        }
        else if (mode == RECORDMODE)
        {
            try
            {
                SunAndMoon.getSunRightAscension(utc, result);
                asc = result[0];
                dec = result[1];
                sun.setRightAscension(result[0]);
                sun.setCelestialDeclination(result[1]);
                sun.setDistance(result[2]);

                SunAndMoon.getMoonRightAscension(utc, result);
                moon.setRightAscension(result[0]);
                moon.setCelestialDeclination(result[1]);
                moon.setDistance(result[2]);
                moonasc = result[0];
                moondec = result[1];
            }
            catch (Exception) { /* Debug.Log("Exception1 ");*/ return; }
            phai0 = Almanac.getGreenidgeSiderealTime(utc);//グリニッジ恒星時
            //記録する
            dataholder.setPositions(asc, dec, sun.getDistance(), moonasc, moondec, moon.getDistance(), phai0, utc);
        }
        else
        {
            return;
        }

        //輪郭の描画
        //ベッセル数
        VesselElements ve = new VesselElements(sun, moon, utc);

        // SolarEclipse.getD(ve, 143.009267, 42.7396185, 0);
        SolarEclipse.getCrossPoint(ve, result, result2);
        //月影と地球外円との交点を調べる
        double maxQ = SolarEclipse.getPenumbralQ(ve, result);
        double minQ = SolarEclipse.getPenumbralQ(ve, result2);

        //Debug.Log("MaxQ = " + maxQ + " minQ = " + minQ);

        //半影の描画
        if (Double.IsNaN(maxQ) && Double.IsNaN(minQ))
        {
            clearTexture();
            //交点が存在しない場合。月影がすべて地球上に投射されている。
            double last_longitude;
            double last_latitude;
            Color  gray = new Color(0, 0, 0, 0.4f);

            //初期の点
            SolarEclipse.getPenumbralOutline(ve, 0.0, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            last_longitude = location[0];
            last_latitude  = location[1];
            double max_lat = -90, min_lat = 90;
            double east_lon = location[0];
            double west_lon = double.NaN;

            //bool
            for (double i = 1.0; i <= 360.0; i += 1.0)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result2);
                if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
                {
                    continue;//NaNが含まれていたらスキップする
                }
                Coordinate.transformICRStoGCS(ve, result2, location);

                if (double.IsNaN(location[0]) | double.IsNaN(location[1]))
                {
                    continue;
                }
                //値の取得で例外が発生したら、処理をスキップする
                try
                {
                    drawOutline(last_longitude, last_latitude, location[0], location[1], shadow, sunoutline);
                }
                catch (Exception ex) { continue; }

                last_longitude = location[0];
                last_latitude  = location[1];
                if (i == 180.0)
                {
                    west_lon = location[0];
                }
                if (max_lat < last_latitude)
                {
                    max_lat = last_latitude;
                }
                if (min_lat > last_latitude)
                {
                    min_lat = last_latitude;
                }
            }

            if (!double.IsNaN(west_lon) & !double.IsNaN(east_lon))
            {
                if (west_lon > east_lon)
                {
                    east_lon += 360.0;
                }

                Point paintpoint = getScreenPoint((east_lon + west_lon) / 2, (max_lat + min_lat) / 2);
                fillShadowEx(paintpoint.x, paintpoint.y, shadow, shadowcolor);
                // Debug.Log("west= " + west_lon + " east=" +east_lon) ;
            }
        }
        else if (!Double.IsNaN(maxQ) && !Double.IsNaN(minQ))//交点が存在する
        {
            double first_longitude;
            double first_latitude;
            double last_longitude;
            double last_latitude;

            clearTexture();
            Color gray = new Color(0, 0, 0, 0.4f);
            if ((maxQ - minQ) >= 0.0)
            {
                maxQ -= 360.0;
            }
            SolarEclipse.getPenumbralOutline(ve, maxQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);
            //Debug.Log("MaxQ :" + location[0] + ":" + location[1]+ ":" + maxQ);
            SolarEclipse.getPenumbralOutline(ve, minQ, result);
            Coordinate.transformICRStoGCS(ve, result, location);

            //初期の点
            double delta = 0.0;
            while (true)
            {
                SolarEclipse.getPenumbralOutline(ve, maxQ + delta, result);
                if (Double.IsNaN(result[0]) | Double.IsNaN(result[1]) | Double.IsNaN(result[2]))
                {
                    delta += 0.1;
                }
                else
                {
                    break;
                }
                if (delta > 5.0)
                {
                    break;
                }
            }

            Coordinate.transformICRStoGCS(ve, result, location);
            first_longitude = last_longitude = location[0];
            first_latitude  = last_latitude = location[1];
            // double max_lon = 0, max_lat = -90, min_lon = 360, min_lat = 90;

            for (double i = maxQ + delta + 0.5; i < minQ; i += 0.5)
            {
                SolarEclipse.getPenumbralOutline(ve, i, result2);
                if (Double.IsNaN(result2[0]) | Double.IsNaN(result2[1]) | Double.IsNaN(result2[2]))
                {
                    continue;//NaNが含まれていたらスキップする
                }
                Coordinate.transformICRStoGCS(ve, result2, location);

                //値の取得で例外が発生したら、処理をスキップする
                if (double.IsNaN(location[0]) | double.IsNaN(location[1]))
                {
                    continue;
                }
                try
                {
                    drawOutline(last_longitude, last_latitude, location[0], location[1], shadow, sunoutline);
                }
                catch (Exception e) { continue; }

                last_longitude = location[0];
                last_latitude  = location[1];
            }

            SolarEclipse.getPenumbralOutline(ve, minQ, result);
            if (!Double.IsNaN(result[0]) & !Double.IsNaN(result[1]) & !Double.IsNaN(result[2]))
            {
                Coordinate.transformICRStoGCS(ve, result, location);
                if (!double.IsNaN(location[0]) & !double.IsNaN(location[1]))
                {
                    drawOutline(last_longitude, last_latitude, location[0], location[1], shadow, sunoutline);
                    last_longitude = location[0];
                    last_latitude  = location[1];
                }
            }

            //同時線を描く
            {
                //日の出・日の入りの同時線を描く
                int alllength = getSunLine(sun, phai0);

                //終点から同時線までの最短の線を描く
                Point  pnt           = getScreenPoint(last_longitude, last_latitude);
                double leastdistance = double.MaxValue;
                int    finishindex   = -1; //終点と最も近い点のインデックス
                if (pnt.x < 0)
                {
                    pnt.x += shadow.width;
                }
                else if (pnt.x >= shadow.width)
                {
                    pnt.x -= shadow.width;
                }
                if (pnt.y < 0)
                {
                    pnt.y = 0;
                }
                else if (pnt.y >= shadow.width)
                {
                    pnt.y = shadow.width;
                }

                for (int i = 0; i < alllength; i++)
                {
                    double xdiff = Math.Abs(pnt.x - sunline[i * 2]);
                    if (xdiff > shadow.width / 2)
                    {
                        xdiff = shadow.width - xdiff;
                    }
                    double ydiff  = pnt.y - sunline[i * 2 + 1];
                    double length = Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
                    if (length < leastdistance)
                    {
                        leastdistance = length; finishindex = i;
                    }
                }
                if (finishindex != -1 & leastdistance != double.MaxValue)
                {
                    if (!double.IsNaN(last_longitude) & !double.IsNaN(last_latitude))
                    {
                        drawScreenOutline(pnt.x, pnt.y, sunline[finishindex * 2], sunline[finishindex * 2 + 1], sunoutline);
                    }
                }

                //開始点から同時線までの最短の線を描く
                pnt           = getScreenPoint(first_longitude, first_latitude);
                leastdistance = double.MaxValue;
                int startindex = -1; //始点と最も近い点のインデックス
                if (pnt.x < 0)
                {
                    pnt.x += shadow.width;
                }
                else if (pnt.x >= shadow.width)
                {
                    pnt.x -= shadow.width;
                }
                if (pnt.y < 0)
                {
                    pnt.y = 0;
                }
                else if (pnt.y >= shadow.width)
                {
                    pnt.y = shadow.width;
                }

                for (int i = 0; i < alllength; i++)
                {
                    double xdiff = Math.Abs(pnt.x - sunline[i * 2]);
                    if (xdiff > shadow.width / 2)
                    {
                        xdiff = shadow.width - xdiff;
                    }
                    double ydiff  = pnt.y - sunline[i * 2 + 1];
                    double length = Math.Sqrt(xdiff * xdiff + ydiff * ydiff);
                    if (length < leastdistance)
                    {
                        leastdistance = length; startindex = i;
                    }
                }
                if (startindex != -1 & leastdistance != double.MaxValue)
                {
                    if (!double.IsNaN(last_longitude) & !double.IsNaN(last_latitude))
                    {
                        drawScreenOutline(pnt.x, pnt.y, sunline[startindex * 2], sunline[startindex * 2 + 1], sunoutline);
                    }
                }
                //判定を正確にするため、同時線は最後に描く。alllengthは要素数だから、マイナスしない
                for (int i = 0; i < alllength; i++)
                {
                    drawScreenPixel(sunline[i * 2], sunline[i * 2 + 1], boundscolor);
                }

                //影の中を塗る
                int middlepoint = -1;
                if (Math.Abs(finishindex - startindex) > (alllength / 2))
                {
                    middlepoint = (finishindex + startindex + alllength) / 2;
                    if (middlepoint >= alllength)
                    {
                        middlepoint -= alllength;
                    }
                    else if (middlepoint < 0)
                    {
                        middlepoint += alllength;
                    }
                }
                else
                {
                    middlepoint = (finishindex + startindex) / 2;
                }
                getInnerPoint(sunline[middlepoint * 2], sunline[middlepoint * 2 + 1], shadow);//塗の指示
            }//同時線の描画の終わり
        } //半影の描画の終わり
        else if (!Double.IsNaN(maxQ) | !Double.IsNaN(minQ)) /*Debug.Log("minQ or maxQ is NaN");*/ } {