Пример #1
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();
    }
Пример #2
0
    private double siderealtime; //グリニッジ恒星時。角度。

    public VesselElements(EquatorialCoordinate possun, EquatorialCoordinate posmoon, DateTime cal)
    {
        //赤経をラジアン角に変換
        double alphasun  = possun.getRightAscension() / 180.0 * Math.PI;
        double alphamoon = posmoon.getRightAscension() / 180.0 * Math.PI;

        //赤緯をラジアン角に変換
        double gammasun  = possun.getCelestialDeclination() / 180.0 * Math.PI;
        double gammamoon = posmoon.getCelestialDeclination() / 180.0 * Math.PI;
        //Debug.Log("asc= " + alphasun + " dec =" + gammasun + " dist = " + possun.getDistance());

        //地心赤道座標を計算する
        double Xs = possun.getDistance() * Math.Cos(alphasun) * Math.Cos(gammasun);
        double Ys = possun.getDistance() * Math.Sin(alphasun) * Math.Cos(gammasun);
        double Zs = possun.getDistance() * Math.Sin(gammasun);

        double Xm = posmoon.getDistance() * Math.Cos(alphamoon) * Math.Cos(gammamoon);
        double Ym = posmoon.getDistance() * Math.Sin(alphamoon) * Math.Cos(gammamoon);
        double Zm = posmoon.getDistance() * Math.Sin(gammamoon);

        //月から見た太陽の赤道直交座標
        double Gx = Xs - Xm;
        double Gy = Ys - Ym;
        double Gz = Zs - Zm;

        double tana = Gy / Gx;
        double tand = Gz / Math.Sqrt(Gx * Gx + Gy * Gy);

        //月影軸方向の赤経・赤緯
        ascension   = Math.Atan2(Gy, Gx);
        declination = Math.Atan2(Gz, Math.Sqrt(Gx * Gx + Gy * Gy));
        g           = Math.Sqrt(Gx * Gx + Gy * Gy + Gz * Gz) * Constants.AUde;

        //地球半径単位への変換
        Xm *= Constants.AUde;
        Ym *= Constants.AUde;
        Zm *= Constants.AUde;

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

        double[] coordinate1 = new double[] { Xm, Ym, Zm };
        double[] coordinate2 = new double[3];

        double angle = ascension + (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, coordinate1, coordinate2);

        angle             = (Math.PI / 2.0) - declination;
        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, coordinate2, coordinate1);

        x0 = coordinate1[0];
        y0 = coordinate1[1];
        z0 = coordinate1[2];

        double d = Constants.Dsun + Constants.Dmoon;

        tanf1 = d / Math.Sqrt(g * g - d * d);
        c1    = z0 + (g * Constants.Dmoon) / d;

        d     = Constants.Dsun - Constants.Dmoon;
        tanf2 = d / Math.Sqrt(g * g - d * d);
        c2    = z0 - (g * Constants.Dmoon) / d;

        l1 = c1 * tanf1;
        l2 = c2 * tanf2;

        //グリニッジ恒星時を計算する
        siderealtime = Almanac.getGreenidgeSiderealTime(cal);
    }