Exemplo n.º 1
0
        public void SolarEclipses()
        {
            IFormatter formatter = new BinaryFormatter();

            //Deserialize
            using (StreamReader streamReader = new StreamReader("CelestialData\\SolarEclipse.txt"))
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                SolarEclipse    ev = (SolarEclipse)binaryFormatter.Deserialize(streamReader.BaseStream);

                SolarEclipseDetails lE1 = ev.LastEclipse;
                SolarEclipseDetails nE1 = ev.NextEclipse;
                SolarEclipseDetails lE2 = data.SolarEclispe.LastEclipse;
                SolarEclipseDetails nE2 = data.SolarEclispe.NextEclipse;

                PropertyInfo[] properties = typeof(SolarEclipseDetails).GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    var l1 = property.GetValue(lE1);
                    var l2 = property.GetValue(lE2);
                    var n1 = property.GetValue(nE1);
                    var n2 = property.GetValue(nE2);

                    Assert.AreEqual(l1.ToString(), l2.ToString(), "Last Eclipse data does not match.");
                    Assert.AreEqual(n1.ToString(), n2.ToString(), "Next Eclipse data does not match.");
                }
            }
        }
Exemplo n.º 2
0
        private ICollection <AstroEvent> FindSolarEclipses(AstroEventsContext context)
        {
            List <AstroEvent> events = new List <AstroEvent>();

            int ln = LunarEphem.Lunation(context.From, LunationSystem.Meeus);

            do
            {
                SolarEclipse eclipse = GetNearestSolarEclipse(ln, next: true, saros: false);
                double       jd      = eclipse.JulianDayMaximum;
                if (jd <= context.To)
                {
                    var pbe       = GetBesselianElements(jd);
                    var localCirc = SolarEclipses.LocalCircumstances(pbe, context.GeoLocation);

                    string type            = Text.Get($"SolarEclipse.Type.{eclipse.EclipseType}");
                    string subtype         = eclipse.IsNonCentral ? $" {Text.Get("SolarEclipse.Type.NoCentral")}" : "";
                    string phase           = eclipse.EclipseType == SolarEclipseType.Partial ? $" ({Text.Get("SolarEclipse.MaxPhase")} {Formatters.Phase.Format(eclipse.Magnitude)})" : "";
                    double jdMax           = localCirc.MaxMagnitude > 0 ? localCirc.Maximum.JulianDay : jd;
                    string localVisibility = GetLocalVisibilityString(eclipse, localCirc);

                    events.Add(new AstroEvent(jdMax, Text.Get("SolarEclipse.Event", ("type", type), ("subtype", subtype), ("phase", phase), ("localVisibility", localVisibility)), sun, moon));
                    ln = eclipse.MeeusLunationNumber + 1;
                }
                else
                {
                    break;
                }
            }while (true);
            return(events);
        }
Exemplo n.º 3
0
        public void FindNearestSolarEclipse()
        {
            double       jd      = new Date(1993, 5, 21).ToJulianDay();
            SolarEclipse eclipse = SolarEclipses.NearestEclipse(jd, true);

            Assert.AreEqual(2449129.0979, eclipse.JulianDayMaximum, TimeSpan.FromMinutes(0.36).TotalDays);
            Assert.AreEqual(SolarEclipseType.Partial, eclipse.EclipseType);
            Assert.AreEqual(0.740, eclipse.Magnitude, 1e-3);
        }
Exemplo n.º 4
0
        private static void eclipseTest2()
        {
            int                 year   = 1907;
            DateTimeOffset      start  = new DateTimeOffset(year, 1, 1, 0, 0, 0, TimeSpan.Zero);
            DateTimeOffset      end    = new DateTimeOffset(year, 1, 31, 0, 0, 0, TimeSpan.Zero);
            List <IPlanetEvent> events = Ephemeris.Geocentric[start, end, PlanetEventFlag.EclipseOccultationCategory];

            SolarEclipse eclipse = events[1] as SolarEclipse;

            Console.WriteLine("{0} happened on {1}, Sun @ {2}", eclipse.ShortDescription, eclipse.When, eclipse.Where);

            Position venusPos = Ephemeris.Geocentric[eclipse.When, PlanetId.SE_VENUS];

            List <IPlanetEvent> transcents = Ephemeris.Geocentric.TranscensionEventOf(PlanetId.SE_VENUS, venusPos.Longitude,
                                                                                      eclipse.When.AddDays(1), start.AddYears(1));

            Console.WriteLine("Venus @ {0}, and transcension afterwards are:\r\n", venusPos.Longitude);

            foreach (IPlanetEvent evt in transcents)
            {
                Console.WriteLine(evt.ToString());
            }

            transcents = Ephemeris.Geocentric.TranscensionEventOf(PlanetId.SE_VENUS, eclipse.Where.Longitude,
                                                                  eclipse.When.AddDays(1), start.AddYears(1));

            Console.WriteLine("Venus transcend Sun position of {0} are:\r\n", eclipse.Where.Longitude);

            foreach (IPlanetEvent evt in transcents)
            {
                Console.WriteLine(evt.ToString());
            }

            LunarEclipse lun = events[3] as LunarEclipse;

            Console.WriteLine("{0} happened on {1}, Sun @ {2}", lun.ShortDescription, lun.When, lun.Where);

            venusPos = Ephemeris.Geocentric[lun.When, PlanetId.SE_VENUS];

            transcents = Ephemeris.Geocentric.TranscensionEventOf(PlanetId.SE_VENUS, lun.Where.Longitude,
                                                                  eclipse.When.AddDays(1), start.AddYears(1));

            foreach (IPlanetEvent evt in transcents)
            {
                Console.WriteLine(evt.ToString());
            }

            Console.ReadKey();
        }
Exemplo n.º 5
0
        /// <inheritdoc />
        public string GetLocalVisibilityString(SolarEclipse eclipse, SolarEclipseLocalCircumstances localCirc)
        {
            string localVisibility = Text.Get("SolarEclipse.LocalVisibility.Invisible");

            if (localCirc.MaxMagnitude > 0)
            {
                string localMag  = Formatters.Phase.Format(localCirc.MaxMagnitude);
                string asPartial = eclipse.EclipseType != SolarEclipseType.Partial ? $" {Text.Get("SolarEclipse.LocalVisibility.AsPartial")}" : "";

                // max instant not visible
                if (localCirc.Maximum.SolarAltitude <= 0)
                {
                    if ((localCirc.TotalEnd != null && localCirc.TotalEnd.SolarAltitude < 0) || localCirc.PartialEnd.SolarAltitude < 0)
                    {
                        localVisibility = Text.Get("SolarEclipse.LocalVisibility.VisibleOnSunset", ("asPartial", asPartial), ("localMag", localMag));
                    }
                    else if (localCirc.PartialBegin.SolarAltitude < 0 || (localCirc.TotalBegin != null && localCirc.TotalBegin.SolarAltitude < 0))
                    {
                        localVisibility = Text.Get("SolarEclipse.LocalVisibility.VisibleOnSunrise", ("asPartial", asPartial), ("localMag", localMag));
                    }
                }
                // max instant visible
                else
                {
                    if (localCirc.TotalDuration > 0)
                    {
                        localVisibility = Text.Get("SolarEclipse.LocalVisibility.VisibleTotally");
                    }
                    else
                    {
                        localVisibility = Text.Get("SolarEclipse.LocalVisibility.Visible", ("asPartial", asPartial), ("localMag", localMag));
                    }
                }
            }

            return(localVisibility);
        }
Exemplo n.º 6
0
        public bool Check_Solar_Eclipse()
        {
            IFormatter formatter = new BinaryFormatter();

            //Deserialize
            using (StreamReader streamReader = new StreamReader("CelestialData\\SolarEclipse.txt"))
            {
                BinaryFormatter binaryFormatter = new BinaryFormatter();
                SolarEclipse    ev = (SolarEclipse)binaryFormatter.Deserialize(streamReader.BaseStream);

                SolarEclipseDetails lE1 = ev.LastEclipse;
                SolarEclipseDetails nE1 = ev.NextEclipse;
                SolarEclipseDetails lE2 = this.SolarEclispe.LastEclipse;
                SolarEclipseDetails nE2 = this.SolarEclispe.NextEclipse;

                PropertyInfo[] properties = typeof(SolarEclipseDetails).GetProperties();
                foreach (PropertyInfo property in properties)
                {
                    var l1 = property.GetValue(lE1);
                    var l2 = property.GetValue(lE2);
                    var n1 = property.GetValue(nE1);
                    var n2 = property.GetValue(nE2);

                    if (l1.ToString() != l2.ToString())
                    {
                        return(false);
                    }

                    if (n1.ToString() != n2.ToString())
                    {
                        return(false);
                    }
                }
            }
            return(true);
        }
Exemplo n.º 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();
    }
Exemplo n.º 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();
    }
Exemplo n.º 9
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");*/ } {
Exemplo n.º 10
0
        private void buttonSolarEclipse_Click(object sender, EventArgs e)
        {
            SolarEclipse solEclipse = Utilities.SolarEclipseAround(start, isBackward);

            MessageBox.Show(solEclipse.ToString());
        }