//地球に写る月の影の輪郭を描く 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");*/ } {