示例#1
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");*/ } {