protected virtual void DrawEquatorialGrid(Graphics g) { // We want at least 5 but no more than 10 RA and DE lines to fit the diagonal double diagonalInArcSec = m_SolvedPlate.GetDistanceInArcSec(0, 0, m_Image.ImageWidth, m_Image.ImageHeight); double ra0, de0; m_SolvedPlate.GetRADEFromImageCoords(m_Image.CenterXImage, m_Image.CenterYImage, out ra0, out de0); Debug.Assert(Math.Abs(m_SolvedPlate.RA0Deg - ra0) < 1 / 3600.0); Debug.Assert(Math.Abs(m_SolvedPlate.DE0Deg - de0) < 1 / 3600.0); // We are not drawing lines when too close to the poles if (de0 + 2 * diagonalInArcSec / 3600.0 > 90) { return; } if (de0 - 2 * diagonalInArcSec / 3600.0 < -90) { return; } int MAX_GRID_LINES = 10; int MIN_GRID_LINES = 5; int[] intervals = new int[] { 1, 5, 10, 30, 60, 60 * 5, 60 * 10, 60 * 30, 60 * 60 }; double deFrom, deTo; #region Calculating the interval in declination double maxArcSec = diagonalInArcSec / MIN_GRID_LINES; double minArcSec = diagonalInArcSec / MAX_GRID_LINES; int deInterval = -1; for (int i = 0; i < intervals.Length; i++) { if (intervals[i] >= minArcSec && intervals[i] <= maxArcSec) { deInterval = intervals[i]; break; } else if (intervals[i] < minArcSec) { deInterval = intervals[i]; } } #endregion double raFrom, raTo; #region Calculating the interval in right accension double[] raArr = new double[4]; double[] deArr = new double[4]; m_SolvedPlate.GetRADEFromImageCoords(0, 0, out raArr[0], out deArr[0]); m_SolvedPlate.GetRADEFromImageCoords(0, m_Image.ImageHeight, out raArr[1], out deArr[1]); m_SolvedPlate.GetRADEFromImageCoords(m_Image.ImageWidth, 0, out raArr[2], out deArr[2]); m_SolvedPlate.GetRADEFromImageCoords(m_Image.ImageWidth, m_Image.ImageHeight, out raArr[3], out deArr[3]); // From the RA of the 4 corners we need to find the fromRA and toRA double raMin = double.MaxValue, raMax = double.MinValue; int minIdx = 0, maxIdx = 0; for (int i = 0; i < 4; i++) { if (raArr[i] > raMax) { raMax = raArr[i]; maxIdx = i; } if (raArr[i] < raMin) { raMin = raArr[i]; minIdx = i; } } double shortestDistance = AngleUtility.Elongation(raArr[minIdx], 0, raArr[maxIdx], 0); if (shortestDistance < (raArr[maxIdx] - raArr[minIdx]) - 10 / 3600.0 /* tolerance 10" */) { // We are going accross the 0 point Debug.Assert(false, "This is not implemented yet"); return; //raFrom = 0; //raTo = 0; //for (int i = 0; i < 4; i++) //{ // if (i == minIdx) continue; // if (i == maxIdx) continue; // if (raArr[0] > raMax) // { // raMax = raArr[0]; // maxIdx = 1; // } // if (raArr[0] < raMin) // { // raMin = raArr[0]; // minIdx = i; // } //} //raTo = raArr[maxIdx]; } else { raFrom = raArr[minIdx]; raTo = raArr[maxIdx]; } minArcSec = 3600.0 * (raTo - raFrom) / (15 * MAX_GRID_LINES); maxArcSec = 3600.0 * (raTo - raFrom) / (15 * MIN_GRID_LINES); int raInterval = -1; for (int i = 0; i < intervals.Length; i++) { if (intervals[i] >= minArcSec && intervals[i] <= maxArcSec) { raInterval = intervals[i]; break; } else if (intervals[i] < minArcSec) { raInterval = intervals[i]; } } #endregion #if DEBUG if (raInterval == -1 || deInterval == -1) { Debug.Assert(false, "Problem with raInterval or deInterval"); return; } #endif raFrom = (Math.Floor((raFrom * 3600.0) / (15 * raInterval)) - 1) * 15 * raInterval / 3600.0; raTo = (Math.Ceiling((raTo * 3600.0) / (15 * raInterval)) + 1) * 15 * raInterval / 3600.0; deFrom = (Math.Floor((de0 * 3600.0 - (diagonalInArcSec / 2)) / (deInterval)) - 1) * deInterval / 3600.0; deTo = (Math.Ceiling((de0 * 3600.0 + (diagonalInArcSec / 2)) / (deInterval)) + 1) * deInterval / 3600.0; //Debug.WriteLine(string.Format("Draw Grid -> C: ({0}, {1}) F:({2}, {3}) T:({4}, {5})", // AstroConvert.ToStringValue(ra0, "HH MM SS.T"), AstroConvert.ToStringValue(de0, "+DD MM SS.T"), // AstroConvert.ToStringValue(raFrom, "HH MM SS.T"), AstroConvert.ToStringValue(raTo, "HH MM SS.T"), // AstroConvert.ToStringValue(deFrom, "+DD MM SS.T"), AstroConvert.ToStringValue(deTo, "+DD MM SS.T"))); double x1, y1, x2, y2; double stepRA = (15 * raInterval) / 3600.0; double stepDE = deInterval / 3600.0; for (double ra = raFrom; ra <= raTo; ra += stepRA) { x1 = double.NaN; y1 = double.NaN; for (double de = deFrom; de < deTo; de += stepDE / 10.0) { m_SolvedPlate.GetImageCoordsFromRADE(ra, de, out x2, out y2); if (x2 >= 0 && x2 <= m_Image.ImageWidth && y2 >= 0 && y2 <= m_Image.ImageHeight) { if (!double.IsNaN(x1)) { g.DrawLine(Pens.Purple, (float)x1, (float)y1, (float)x2, (float)y2); } x1 = x2; y1 = y2; } } } for (double de = deFrom; de <= deTo; de += stepDE) { x1 = double.NaN; y1 = double.NaN; for (double ra = raFrom; ra < raTo; ra += stepRA / 10.0) { m_SolvedPlate.GetImageCoordsFromRADE(ra, de, out x2, out y2); if (x2 >= 0 && x2 <= m_Image.ImageWidth && y2 >= 0 && y2 <= m_Image.ImageHeight) { if (!double.IsNaN(x1)) { g.DrawLine(Pens.Purple, (float)x1, (float)y1, (float)x2, (float)y2); } x1 = x2; y1 = y2; } } } }
public LeastSquareFittedAstrometry SolvePlateConstantsPhase4(double pyramidLimitMag) { double ra0deg, de0Deg; m_SolvedPlate.GetRADEFromImageCoords(m_SolvedPlate.Image.CenterXImage, m_SolvedPlate.Image.CenterYImage, out ra0deg, out de0Deg); FocalLengthFit distFit = m_ConstantsSolver.ComputeFocalLengthFit(); m_Context.PlateConfig.EffectiveFocalLength = m_Context.FieldSolveContext.FocalLength; distFit.GetFocalParameters(m_Context.PlateConfig.EffectiveFocalLength, out m_Context.PlateConfig.EffectivePixelWidth, out m_Context.PlateConfig.EffectivePixelHeight); DistanceBasedAstrometrySolver distMatch = new DistanceBasedAstrometrySolver( m_AstrometryController, m_Context.PlateConfig, m_AstrometrySettings, m_Context.FieldSolveContext.CatalogueStars, m_Context.FieldSolveContext.RADeg, m_Context.FieldSolveContext.DEDeg, m_Context.FieldSolveContext.DetermineAutoLimitMagnitude); distMatch.SetMinMaxMagOfStarsForAstrometry(CorePyramidConfig.Default.DefaultMinAstrometryMagnitude, 18); distMatch.SetMinMaxMagOfStarsForPyramidAlignment(CorePyramidConfig.Default.DefaultMinPyramidMagnitude, pyramidLimitMag); Trace.WriteLine(string.Format("Stars for alignment in range: {0:0.0} - {1:0.0} mag", CorePyramidConfig.Default.DefaultMinPyramidMagnitude, pyramidLimitMag)); Dictionary <PSFFit, IStar> manualStars = null; var threeStarFit = m_Context.PreliminaryFit as ThreeStarAstrometry; if (threeStarFit != null) { manualStars = new Dictionary <PSFFit, IStar>(); foreach (var kvp in threeStarFit.UserStars) { PSFFit psfFit; m_Context.StarMap.GetPSFFit(kvp.Key.X, kvp.Key.Y, PSFFittingMethod.NonLinearFit, out psfFit); if (psfFit != null && psfFit.IsSolved) { manualStars.Add(psfFit, kvp.Value); } } } distMatch.InitNewMatch(m_Context.StarMap, PyramidMatchType.PlateSolve, manualStars); #if ASTROMETRY_DEBUG Dictionary <int, ulong> debugInfo = new Dictionary <int, ulong>(); var starList = m_Context.SecondAstrometricFit.FitInfo.AllStarPairs .Where(p => !p.FitInfo.ExcludedForHighResidual); foreach (var x in starList) { if (!debugInfo.ContainsKey(x.FeatureId)) { debugInfo.Add(x.FeatureId, x.StarNo); } } foreach (var f in m_Context.StarMap.Features) { Trace.WriteLine(string.Format("{0} - {1}", f.FeatureId, debugInfo.ContainsKey(f.FeatureId) ? "INCLUDED" : "MISSING")); } distMatch.SetDebugData(new DistanceBasedAstrometrySolver.PyramidDebugContext() { ResolvedStars = debugInfo, ResolvedFocalLength = m_Context.SecondAstrometricFit.FitInfo.FittedFocalLength }); #endif LeastSquareFittedAstrometry fit = null; LeastSquareFittedAstrometry improvedFit = null; PlateConstantsSolver solver; distMatch.PerformMatch(out fit, out improvedFit, out solver); m_Context.DistanceBasedFit = fit; m_Context.ImprovedDistanceBasedFit = improvedFit; if (fit != null) { m_Context.PlateConstants = new TangraConfig.PersistedPlateConstants { EffectiveFocalLength = m_Context.PlateConfig.EffectiveFocalLength, EffectivePixelWidth = m_Context.PlateConfig.EffectivePixelWidth, EffectivePixelHeight = m_Context.PlateConfig.EffectivePixelHeight }; m_Context.ConstantsSolver = solver; if (improvedFit != null) { foreach (var pair in improvedFit.FitInfo.AllStarPairs) { if (pair.FitInfo.ExcludedForHighResidual) { continue; } Trace.WriteLine(string.Format("{6}; {0}; {1}; {2}; {3}; ({4}\", {5}\")", pair.RADeg, pair.DEDeg, pair.x.ToString("0.00"), pair.y.ToString("0.00"), pair.FitInfo.ResidualRAArcSec.ToString("0.00"), pair.FitInfo.ResidualDEArcSec.ToString("0.00"), pair.StarNo)); double x, y; improvedFit.GetImageCoordsFromRADE(pair.RADeg, pair.DEDeg, out x, out y); double dist = improvedFit.GetDistanceInArcSec(x, y, pair.x, pair.y); } } } else { m_Context.PlateConstants = null; } return(fit); }