internal frmIdentifyObjects(IAstrometricFit fit, VideoController videoController, double fovArcMin, DateTime utcTime, double magLimit, string obsCode) : this() { m_Fit = fit; m_FovArcMin = fovArcMin; m_UtcTime = utcTime; m_MagLimit = magLimit; m_ObsCode = obsCode; pnlProgress.Visible = false; pnlEnterTime.Visible = true; if (m_UtcTime != DateTime.MinValue && m_UtcTime.Year != 1) { dtTime.Value = m_UtcTime; dtDate.Value = m_UtcTime; } else { DateTime? timeStamp = videoController.GetCurrentFrameTime(); if (timeStamp != null && timeStamp != DateTime.MinValue && timeStamp.Value.Year != 1 /* Has a day component */) { dtTime.Value = timeStamp.Value; dtDate.Value = timeStamp.Value; } else { DateTime dt = TangraConfig.Settings.LastUsed.LastIdentifyObjectsDate; if (dt == DateTime.MinValue) dt = DateTime.Now.ToUniversalTime(); dtTime.Value = dt; dtDate.Value = dt; } } }
/// <summary> /// Does the second step of the plate calibration: Least Square with the mapped celestrial stars (from step 1) /// </summary> /// <param name="fitOrder"></param> /// <returns></returns> public bool SolvePlateConstantsPhase2(FitOrder fitOrder, bool fineFit) { LeastSquareFittedAstrometry firstSolution; m_SolvedPlate = m_ConstantsSolver.SolveWithLinearRegression(m_AstrometrySettings, out firstSolution); if (firstSolution != null) { if (fineFit) { m_Context.InitialSecondAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialSecondAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } else { m_Context.InitialFirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialFirstAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } } if (m_SolvedPlate != null) { // TODO: Make this configurable if (m_ConstantsSolver.ExcludedForBadResidualsCount < 2 * m_ConstantsSolver.IncludedInSolutionCount) { LeastSquareFittedAstrometry lsfa = m_SolvedPlate as LeastSquareFittedAstrometry; // At least 33% of the stars should be included in the solution if (fineFit) { m_Context.SecondAstrometricFit = lsfa; } else { m_Context.FirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(lsfa); m_Context.FirstAstrometricFit.FitInfo.AllStarPairs.AddRange(lsfa.FitInfo.AllStarPairs); } #if ASTROMETRY_DEBUG //foreach (PlateConstStarPair pair in lsfa.FitInfo.AllStarPairs) //{ // double x, y; // lsfa.GetImageCoordsFromRADE(pair.RADeg, pair.DEDeg, out x, out y); // double dist = lsfa.GetDistanceInArcSec(x, y, pair.x, pair.y); // Trace.Assert(Math.Abs(dist) < pair.FitInfo.ResidualArcSec*1.1); //} #endif return(true); } } return(false); }
protected virtual void ReinitializePlateConstants() { m_Image = m_AstrometryController.GetCurrentAstroPlate(); m_Image.EffectiveFocalLength = m_FLength; if (m_SolvedPlate is LeastSquareFittedAstrometry) { m_SolvedPlate = new LeastSquareFittedAstrometry(m_Image, m_RADegCenter, m_DEDegCenter, null /*m_SolvePlateConts*/); } else if (m_SolvedPlate is TangentalTransRotAstrometry) { m_SolvedPlate = new TangentalTransRotAstrometry(m_SolvedPlate as TangentalTransRotAstrometry, m_Image, m_RADegCenter, m_DEDegCenter, m_Eta); } else { m_SolvedPlate = new DirectTransRotAstrometry(m_Image, m_RADegCenter, m_DEDegCenter, m_Eta, m_Aspect); } }
internal frmIdentifyObjects(IAstrometricFit fit, VideoController videoController, double fovArcMin, DateTime utcTime, double magLimit, string obsCode) : this() { m_Fit = fit; m_FovArcMin = fovArcMin; m_UtcTime = utcTime; m_MagLimit = magLimit; m_ObsCode = obsCode; pnlProgress.Visible = false; pnlEnterTime.Visible = true; if (m_UtcTime != DateTime.MinValue && m_UtcTime.Year != 1) { dtTime.Value = m_UtcTime; dtDate.Value = m_UtcTime; } else { DateTime?timeStamp = videoController.GetCurrentFrameTime(); if (timeStamp != null && timeStamp != DateTime.MinValue && timeStamp.Value.Year != 1 /* Has a day component */) { dtTime.Value = timeStamp.Value; dtDate.Value = timeStamp.Value; } else { DateTime dt = TangraConfig.Settings.LastUsed.LastIdentifyObjectsDate; if (dt == DateTime.MinValue) { dt = DateTime.Now.ToUniversalTime(); } dtTime.Value = dt; dtDate.Value = dt; } } }
/// <summary> /// Does the second step of the plate calibration: Least Square with the mapped celestrial stars (from step 1) /// </summary> /// <param name="fitOrder"></param> /// <returns></returns> public bool SolvePlateConstantsPhase2(FitOrder fitOrder, bool fineFit) { LeastSquareFittedAstrometry firstSolution; m_SolvedPlate = m_ConstantsSolver.SolveWithLinearRegression(m_AstrometrySettings, out firstSolution); if (firstSolution != null) { if (fineFit) { m_Context.InitialSecondAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialSecondAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } else { m_Context.InitialFirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(firstSolution); m_Context.InitialFirstAstrometricFit.FitInfo.AllStarPairs.AddRange(firstSolution.FitInfo.AllStarPairs); } } if (m_SolvedPlate != null) { // TODO: Make this configurable if (m_ConstantsSolver.ExcludedForBadResidualsCount < 2 * m_ConstantsSolver.IncludedInSolutionCount) { LeastSquareFittedAstrometry lsfa = m_SolvedPlate as LeastSquareFittedAstrometry; // At least 33% of the stars should be included in the solution if (fineFit) m_Context.SecondAstrometricFit = lsfa; else { m_Context.FirstAstrometricFit = LeastSquareFittedAstrometry.FromReflectedObject(lsfa); m_Context.FirstAstrometricFit.FitInfo.AllStarPairs.AddRange(lsfa.FitInfo.AllStarPairs); } #if ASTROMETRY_DEBUG //foreach (PlateConstStarPair pair in lsfa.FitInfo.AllStarPairs) //{ // double x, y; // lsfa.GetImageCoordsFromRADE(pair.RADeg, pair.DEDeg, out x, out y); // double dist = lsfa.GetDistanceInArcSec(x, y, pair.x, pair.y); // Trace.Assert(Math.Abs(dist) < pair.FitInfo.ResidualArcSec*1.1); //} #endif return true; } } return false; }
private bool CheckTriangle(int i, int j, int k, double dij, double dik, double djk, double toleranceInArcSec) { // Candidates for the matches int idxIJLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dij - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIJUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dij + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dik - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dik + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxJKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(djk - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxJKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(djk + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; DistanceEntry ijEntry = null; DistanceEntry ikEntry = null; DistanceEntry jkEntry = null; for (int ij = idxIJLower; ij <= idxIJUpper; ij++) { ijEntry = m_Entries[ij]; if (ijEntry.DistanceArcSec + toleranceInArcSec < dij) continue; if (ijEntry.DistanceArcSec - toleranceInArcSec > dij) continue; for (int ik = idxIKLower; ik <= idxIKUpper; ik++) { ikEntry = m_Entries[ik]; if (ikEntry.DistanceArcSec + toleranceInArcSec < dik) continue; if (ikEntry.DistanceArcSec - toleranceInArcSec > dik) continue; ulong foundIdx0 = uint.MaxValue; ulong needIdx1 = uint.MaxValue; ulong needIdx2 = uint.MaxValue; if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo) { // ik_1 = ij_1 = (i) foundIdx0 = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; needIdx2 = ijEntry.Star2.StarNo; } else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo) { // ik_1 = ij_2 = (i) foundIdx0 = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo) { // ik_2 = ij_1 = (i) foundIdx0 = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star2.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo) { // ik_2 = ij_2 = (i) foundIdx0 = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else continue; if (needIdx1 == needIdx2) continue; #if DEBUG int bestKId = -1; double bestDiff = double.MaxValue; #endif for (int jk = idxJKLower; jk <= idxJKUpper; jk++) { jkEntry = m_Entries[jk]; #if DEBUG double diff = Math.Abs(jkEntry.DistanceArcSec - djk); if (diff < bestDiff) { bestDiff = diff; bestKId = jk; } #endif if (jkEntry.DistanceArcSec + toleranceInArcSec < djk) continue; if (jkEntry.DistanceArcSec - toleranceInArcSec > djk) continue; if (jkEntry.Star1.StarNo == needIdx1 && jkEntry.Star2.StarNo == needIdx2) { #if PYRAMID_DEBUG Trace.WriteLine( string.Format("Match: {0} - {1} - {2} ({3}-{4}-{5}) {6}\" {7}\" {8}\"", foundIdx0, needIdx1, needIdx2, i, j, k, dij.ToString("0.0"), dik.ToString("0.0"), djk.ToString("0.0"))); #endif m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, foundIdx0, needIdx1, needIdx2, toleranceInArcSec); if (m_Solution != null) return true; } if (jkEntry.Star1.StarNo == needIdx2 && jkEntry.Star2.StarNo == needIdx1) { #if PYRAMID_DEBUG Trace.WriteLine( string.Format("Match: {0} - {1} - {2} ({3}-{4}-{5}) {6}\" {7}\" {8}\"", foundIdx0, needIdx1, needIdx2, i, j, k, dij.ToString("0.0"), dik.ToString("0.0"), djk.ToString("0.0"))); #endif m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, foundIdx0, needIdx1, needIdx2, toleranceInArcSec); if (m_Solution != null) return true; } } #if DEBUG jkEntry = m_Entries[bestKId]; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Debug.WriteLine( string.Format("3-rd star match failed by {0}\" ({1}, {2}, {3}) -> ({4}: {5}, {6}); [{7},{8}]", bestDiff, i, j, k, foundIdx0, needIdx1, needIdx2, jkEntry.Star1.StarNo, jkEntry.Star2.StarNo)); #endif } } return false; }
private bool CheckTriangleWithRatios(int i, int j, int k, ImagePixel iCenter, ImagePixel jCenter, ImagePixel kCenter, double toleranceInArcSec) { double dijMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dijMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dikMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dikMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double djkMax = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double djkMin = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); // Candidates for the matches int idxIJLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dijMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIJUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dijMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(dikMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxIKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(dikMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxJKLower = m_IndexLower[Math.Min(Math.Max((int)Math.Round(djkMin - toleranceInArcSec) - 1, 0), m_IndexUpper.Keys.Count - 1)]; int idxJKUpper = m_IndexUpper[Math.Min(Math.Max((int)Math.Round(djkMax + toleranceInArcSec) + 1, 0), m_IndexUpper.Keys.Count - 1)]; ulong iDebugStarNo = 0, jDebugStarNo = 0, kDebugStarNo = 0; bool debugStarMatch = false; if (DebugResolvedStars != null) { if (DebugResolvedStars.TryGetValue(i, out iDebugStarNo) && DebugResolvedStars.TryGetValue(j, out jDebugStarNo) && DebugResolvedStars.TryGetValue(k, out kDebugStarNo)) { IStar iStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == iDebugStarNo); IStar jStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == jDebugStarNo); IStar kStarAllDbg = m_CelestialAllStars.FirstOrDefault(s => s.StarNo == kDebugStarNo); #if ASTROMETRY_DEBUG Trace.Assert(iStarAllDbg != null); Trace.Assert(jStarAllDbg != null); Trace.Assert(kStarAllDbg != null); #endif IStar iStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == iDebugStarNo); IStar jStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == jDebugStarNo); IStar kStarDbg = m_CelestialPyramidStars.FirstOrDefault(s => s.StarNo == kDebugStarNo); if (iStarDbg != null && jStarDbg != null && kStarDbg != null) { debugStarMatch = true; DistanceEntry deIJDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == iDebugStarNo && e.Star2.StarNo == jDebugStarNo) || (e.Star1.StarNo == jDebugStarNo && e.Star2.StarNo == iDebugStarNo)); DistanceEntry deIKDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == iDebugStarNo && e.Star2.StarNo == kDebugStarNo) || (e.Star1.StarNo == kDebugStarNo && e.Star2.StarNo == iDebugStarNo)); DistanceEntry deJKDbg = m_Entries.FirstOrDefault(e => (e.Star1.StarNo == kDebugStarNo && e.Star2.StarNo == jDebugStarNo) || (e.Star1.StarNo == jDebugStarNo && e.Star2.StarNo == kDebugStarNo)); #if ASTROMETRY_DEBUG Trace.Assert(deIJDbg != null); Trace.Assert(deIKDbg != null); Trace.Assert(deJKDbg != null); #endif double dijDbg = AngleUtility.Elongation(iStarDbg.RADeg, iStarDbg.DEDeg, jStarDbg.RADeg, jStarDbg.DEDeg) * 3600; double dikDbg = AngleUtility.Elongation(iStarDbg.RADeg, iStarDbg.DEDeg, kStarDbg.RADeg, kStarDbg.DEDeg) * 3600; double djkDbg = AngleUtility.Elongation(kStarDbg.RADeg, kStarDbg.DEDeg, jStarDbg.RADeg, jStarDbg.DEDeg) * 3600; #if ASTROMETRY_DEBUG Trace.Assert(Math.Abs(dijDbg - deIJDbg.DistanceArcSec) < 1); Trace.Assert(Math.Abs(dikDbg - deIKDbg.DistanceArcSec) < 1); Trace.Assert(Math.Abs(djkDbg - deJKDbg.DistanceArcSec) < 1); #endif //TODO: Find the real focal length, then find the difference in percentages //NOTE: Stars are not included because initial focal length is not correct !!! #if ASTROMETRY_DEBUG Trace.Assert(dijMax > dijDbg); Trace.Assert(dijMin < dijDbg); Trace.Assert(dikMax > dikDbg); Trace.Assert(dikMin < dikDbg); Trace.Assert(djkMax > djkDbg); Trace.Assert(djkMin < djkDbg); #endif } else { #if ASTROMETRY_DEBUG if (iStarDbg == null) Trace.Assert((iStarAllDbg.Mag > m_PyramidMaxMag) || (iStarAllDbg.Mag < m_PyramidMinMag)); if (jStarDbg == null) Trace.Assert((jStarAllDbg.Mag > m_PyramidMaxMag) || (jStarAllDbg.Mag < m_PyramidMinMag)); if (kStarDbg == null) Trace.Assert((kStarAllDbg.Mag > m_PyramidMaxMag) || (kStarAllDbg.Mag < m_PyramidMinMag)); #endif } } } DistanceEntry ijEntry = null; DistanceEntry ikEntry = null; DistanceEntry jkEntry = null; for (int ij = idxIJLower; ij <= idxIJUpper; ij++) { ijEntry = m_Entries[ij]; if (debugStarMatch) { if ((ijEntry.Star1.StarNo == iDebugStarNo && ijEntry.Star2.StarNo == jDebugStarNo) || (ijEntry.Star1.StarNo == jDebugStarNo && ijEntry.Star2.StarNo == iDebugStarNo)) { #if ASTROMETRY_DEBUG Trace.Assert(ijEntry.DistanceArcSec + toleranceInArcSec >= dijMin); Trace.Assert(ijEntry.DistanceArcSec - toleranceInArcSec <= dijMax); #endif } } if (ijEntry.DistanceArcSec + toleranceInArcSec < dijMin) continue; if (ijEntry.DistanceArcSec - toleranceInArcSec > dijMax) continue; for (int ik = idxIKLower; ik <= idxIKUpper; ik++) { ikEntry = m_Entries[ik]; bool debugIKPairFound = false; if (debugStarMatch) { if ((ikEntry.Star1.StarNo == iDebugStarNo && ikEntry.Star2.StarNo == kDebugStarNo) || (ikEntry.Star1.StarNo == kDebugStarNo && ikEntry.Star2.StarNo == iDebugStarNo)) { #if ASTROMETRY_DEBUG Trace.Assert(ikEntry.DistanceArcSec + toleranceInArcSec >= dikMin); Trace.Assert(ikEntry.DistanceArcSec - toleranceInArcSec <= dikMax); Trace.Assert(Math.Abs(ijEntry.DistanceArcSec - (dijMin / dikMin) * ikEntry.DistanceArcSec) < toleranceInArcSec); #endif debugIKPairFound = true; } } if (ikEntry.DistanceArcSec + toleranceInArcSec < dikMin) continue; if (ikEntry.DistanceArcSec - toleranceInArcSec > dikMax) continue; if (ikEntry.Star1.StarNo != ijEntry.Star1.StarNo && ikEntry.Star1.StarNo != ijEntry.Star2.StarNo && ikEntry.Star2.StarNo != ijEntry.Star1.StarNo && ikEntry.Star2.StarNo != ijEntry.Star2.StarNo) { // There is no possible (i, j, k) configuration that involves the same 3 stars continue; } double ratioDifference = Math.Abs(ijEntry.DistanceArcSec - (dijMin/dikMin) * ikEntry.DistanceArcSec); if (ratioDifference > toleranceInArcSec) continue; // Ratios are preserved when changing the focal length (with linear fit) so check the ratios here double fittedFocalLength = m_PlateConfig.GetFocalLengthFromMatch( ijEntry.DistanceArcSec, ikEntry.DistanceArcSec, iCenter, jCenter, kCenter, toleranceInArcSec, m_Settings.PyramidFocalLengthAllowance); if (debugIKPairFound) { #if ASTROMETRY_DEBUG Trace.Assert(!double.IsNaN(fittedFocalLength)); #endif } if (double.IsNaN(fittedFocalLength)) continue; double djk = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength); ulong iStarNo = uint.MaxValue; ulong needIdx1 = uint.MaxValue; ulong needIdx2 = uint.MaxValue; if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo) { // ik_1 = ij_1 = (i) iStarNo = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; needIdx2 = ijEntry.Star2.StarNo; } else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo) { // ik_1 = ij_2 = (i) iStarNo = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo) { // ik_2 = ij_1 = (i) iStarNo = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star2.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo) { // ik_2 = ij_2 = (i) iStarNo = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else continue; if (needIdx1 == needIdx2) continue; jkEntry = m_Entries.Where(e => (e.Star1.StarNo == needIdx1 && e.Star2.StarNo == needIdx2) || (e.Star1.StarNo == needIdx2 && e.Star2.StarNo == needIdx1)).FirstOrDefault(); if (debugIKPairFound) { #if ASTROMETRY_DEBUG Trace.Assert(jkEntry != null); #endif if (jkEntry != null) { #if ASTROMETRY_DEBUG Trace.Assert(jkEntry.DistanceArcSec + toleranceInArcSec >= djk); Trace.Assert(jkEntry.DistanceArcSec - toleranceInArcSec <= djk); Trace.Assert(jkEntry.DistanceArcSec + toleranceInArcSec >= djkMin); Trace.Assert(jkEntry.DistanceArcSec - toleranceInArcSec <= djkMax); #endif } } if (jkEntry != null) { ulong jStarNo = ulong.MinValue; ulong kStarNo = ulong.MinValue; if (jkEntry.DistanceArcSec + toleranceInArcSec < djkMin) continue; if (jkEntry.DistanceArcSec - toleranceInArcSec > djkMax) continue; if (jkEntry.DistanceArcSec + toleranceInArcSec < djk) continue; if (jkEntry.DistanceArcSec - toleranceInArcSec > djk) continue; if (jkEntry.Star1.StarNo == needIdx1 && jkEntry.Star2.StarNo == needIdx2) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec); if (m_Solution == null) continue; jStarNo = needIdx1; kStarNo = needIdx2; } if (jkEntry.Star1.StarNo == needIdx2 && jkEntry.Star2.StarNo == needIdx1) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec); if (m_Solution == null) continue; jStarNo = needIdx2; kStarNo = needIdx1; } if (m_Solution != null) { if (TangraConfig.Settings.Astrometry.PyramidNumberOfPivots == 3) // Exist the initial alignment with only 3 candidate pivots return true; for (int l = 0; l < m_StarMap.Features.Count; l++) { var piramid = m_StarMap.Features[l]; if (piramid.FeatureId == i || piramid.FeatureId == j || piramid.FeatureId == k) continue; var lCenter = piramid.GetCenter(); // NOTE: Continue until a set of distances is found in the cache for the 4-th pivot double dli = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, iCenter.XDouble, iCenter.YDouble, fittedFocalLength); double dlj = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, jCenter.XDouble, jCenter.YDouble, fittedFocalLength); double dlk = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength); List<DistanceEntry> ilCandidates = m_DistancesByMagnitude .Where(e => (e.Star1.StarNo == iStarNo || e.Star2.StarNo == iStarNo) && e.DistanceArcSec < dli + toleranceInArcSec && e.DistanceArcSec > dli - toleranceInArcSec) .ToList(); foreach (var cand_il in ilCandidates) { var lStar = cand_il.Star1.StarNo == iStarNo ? cand_il.Star2 : cand_il.Star1; List<DistanceEntry> jlCandidates = m_DistancesByMagnitude .Where(e => ((e.Star1.StarNo == jStarNo && e.Star2.StarNo == lStar.StarNo) || (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == jStarNo)) && e.DistanceArcSec < dlj + toleranceInArcSec && e.DistanceArcSec > dlj - toleranceInArcSec) .ToList(); List<DistanceEntry> klCandidates = m_DistancesByMagnitude .Where(e => ((e.Star1.StarNo == kStarNo && e.Star2.StarNo == lStar.StarNo) || (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == kStarNo)) && e.DistanceArcSec < dlk + toleranceInArcSec && e.DistanceArcSec > dlk - toleranceInArcSec) .ToList(); if (jlCandidates.Count > 0 && klCandidates.Count > 0) { if (klCandidates.Count > 0) return true; } } } } } //#if DEBUG // int bestKId = -1; // double bestDiff = double.MaxValue; //#endif // for (int jk = idxJKLower; jk <= idxJKUpper; jk++) // { // jkEntry = m_Entries[jk]; //#if DEBUG // double diff = Math.Abs(jkEntry.DistanceArcSec - djk); // if (diff < bestDiff) // { // bestDiff = diff; // bestKId = jk; // } //#endif // } //#if DEBUG // jkEntry = m_Entries[bestKId]; // Debug.WriteLine( // string.Format("3-rd star match failed by {0}\" ({1}, {2}, {3}) -> ({4}: {5}, {6}); [{7},{8}]", // bestDiff, i, j, k, // foundIdx0, needIdx1, needIdx2, // jkEntry.Star1.StarNo, jkEntry.Star2.StarNo)); //#endif } } return false; }
private bool TryMatchingPairsFromPreviousFit(IStarMap starMap) { ThreeStarFit.StarPair[] pairs = new ThreeStarFit.StarPair[3]; Dictionary<ImagePixel, IStar> matchedPairs = new Dictionary<ImagePixel, IStar>(); Dictionary<int, ulong> matchedFeatureIdToStarIdIndexes = new Dictionary<int, ulong>(); int idx = 0; foreach (PlateConstStarPair pair in m_PreviousFit.AllStarPairs) { if (pair.FitInfo.ExcludedForHighResidual) continue; StarMapFeature ftr = starMap.GetFeatureInRadius((int)pair.x, (int)pair.y, (int)CoreAstrometrySettings.Default.SearchArea); if (ftr != null) { ImagePixel center = starMap.GetCentroid( (int)pair.x, (int)pair.y, (int)CoreAstrometrySettings.Default.SearchArea); IStar star = null; foreach (IStar s in m_CelestialPyramidStars) { if (s.StarNo == pair.StarNo) { star = s; break; } } if (star != null && center != null && !matchedFeatureIdToStarIdIndexes.ContainsKey(ftr.FeatureId)) { if (idx < 3) { pairs[idx] = new ThreeStarFit.StarPair(center.X, center.Y); pairs[idx].RADeg = star.RADeg; pairs[idx].DEDeg = star.DEDeg; pairs[idx].Star = star; idx++; } matchedPairs.Add(center, star); matchedFeatureIdToStarIdIndexes.Add(ftr.FeatureId, star.StarNo); } } } // Shortcurcuit to FeautreId - StarNo detection if (matchedPairs.Count >= m_Settings.MinimumNumberOfStars) { // When there was a previous fit and we have sufficient stars from the current star map // then don't require % of the bright features to approve the solution. Do it as a calibration fit (not too precise) LeastSquareFittedAstrometry fit = SolveStarPairs( starMap, matchedPairs, matchedFeatureIdToStarIdIndexes, pairs[0], pairs[1], pairs[2], m_PreviousFit.FittedFocalLength, null, TangraConfig.Settings.Astrometry.MinimumNumberOfStars); if (fit != null) { m_Solution = fit; m_MatchedPairs = matchedPairs; m_MatchedFeatureIdToStarIdIndexes = matchedFeatureIdToStarIdIndexes; return true; } } return false; }
private bool TryMatchingPairsFromManualPairs(IStarMap starMap) { ThreeStarFit.StarPair[] pairs = new ThreeStarFit.StarPair[3]; Dictionary<ImagePixel, IStar> matchedPairs = new Dictionary<ImagePixel, IStar>(); Dictionary<int, ulong> matchedFeatureIdToStarIdIndexes = new Dictionary<int, ulong>(); int idx = 0; foreach (StarMapFeature feature in m_ManualPairs.Keys) { IStar star = m_ManualPairs[feature]; ImagePixel center = feature.GetCenter(); StarMapFeature ftr = starMap.GetFeatureInRadius((int)center.X, (int)center.Y, (int)CoreAstrometrySettings.Default.SearchArea); if (ftr != null) { if (!matchedFeatureIdToStarIdIndexes.ContainsKey(ftr.FeatureId)) { if (idx < 3) { pairs[idx] = new ThreeStarFit.StarPair(center.X, center.Y); pairs[idx].RADeg = star.RADeg; pairs[idx].DEDeg = star.DEDeg; pairs[idx].Star = star; idx++; } matchedPairs.Add(center, star); matchedFeatureIdToStarIdIndexes.Add(ftr.FeatureId, star.StarNo); } } } if (matchedPairs.Count >= m_Settings.MinimumNumberOfStars) { // When there was a previous fit and we have sufficient stars from the current star map // then don't require % of the bright features to approve the solution. Do it as a calibration fit (not too precise) LeastSquareFittedAstrometry fit = SolveStarPairs( starMap, matchedPairs, matchedFeatureIdToStarIdIndexes, pairs[0], pairs[1], pairs[2], m_PlateConfig.EffectiveFocalLength, null, TangraConfig.Settings.Astrometry.MinimumNumberOfStars); if (fit != null) { m_Solution = fit; m_MatchedPairs = matchedPairs; m_MatchedFeatureIdToStarIdIndexes = matchedFeatureIdToStarIdIndexes; return true; } } return false; }
private bool CheckTrianglesWithRatiosByMagnitude(int i, int j, int k, ImagePixel iCenter, ImagePixel jCenter, ImagePixel kCenter, double toleranceInArcSec) { if (iCenter == null || jCenter == null || kCenter == null) return false; double dijMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dijMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, jCenter.XDouble, jCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dikMax = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double dikMin = m_PlateConfig.GetDistanceInArcSec(iCenter.XDouble, iCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double djkMax = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 - m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); double djkMin = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, (1 + m_Settings.PyramidFocalLengthAllowance) * m_PlateConfig.EffectiveFocalLength); List<DistanceEntry> ijCandidates = m_DistancesByMagnitude .Where(e => e.DistanceArcSec > dijMin && e.DistanceArcSec < dijMax).ToList(); if (m_ManualPairs != null && m_ManualPairs.Count <= 3) LimitIJtoManualPairs(ijCandidates); bool debugFieldIdentified = true; bool debug = false; ulong debugiStarNo = 0; ulong debugjStarNo = 0; ulong debugkStarNo = 0; if (DebugResolvedStars != null) { if (DebugResolvedStars.ContainsKey(i) && DebugResolvedStars.ContainsKey(j) && DebugResolvedStars.ContainsKey(k)) { debugiStarNo = DebugResolvedStars[i]; debugjStarNo = DebugResolvedStars[j]; debugkStarNo = DebugResolvedStars[k]; debug = true; debugFieldIdentified = false; } } try { if (debug) { // The ijCandidates must contain the IJ pair DistanceEntry rightijEntry = ijCandidates.FirstOrDefault(c => (c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugjStarNo) || (c.Star1.StarNo == debugjStarNo && c.Star2.StarNo == debugiStarNo)); if(rightijEntry == null) { DistanceEntry masterijEntry = m_DistancesByMagnitude.FirstOrDefault(c => (c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugjStarNo) || (c.Star1.StarNo == debugjStarNo && c.Star2.StarNo == debugiStarNo)); Trace.Assert(masterijEntry != null); } } foreach (DistanceEntry ijEntry in ijCandidates) { List<DistanceEntry> ikCandidates = m_DistancesByMagnitude .Where(e => (e.Star1.StarNo == ijEntry.Star1.StarNo || e.Star2.StarNo == ijEntry.Star1.StarNo || e.Star1.StarNo == ijEntry.Star2.StarNo || e.Star2.StarNo == ijEntry.Star2.StarNo) && e.DistanceArcSec > dikMin && e.DistanceArcSec < dikMax) .ToList(); if (m_ManualPairs != null && m_ManualPairs.Count == 3) LimitIKtoManualPairs(ikCandidates); if (debug && ( (debugiStarNo == ijEntry.Star1.StarNo && debugjStarNo == ijEntry.Star2.StarNo) || (debugiStarNo == ijEntry.Star2.StarNo && debugjStarNo == ijEntry.Star1.StarNo))) { // The ikCandidates must contain the IK pair DistanceEntry rightikEntry = ikCandidates.FirstOrDefault(c => (c.Star1.StarNo == debugkStarNo || c.Star2.StarNo == debugkStarNo)); if (rightikEntry == null) { rightikEntry = m_DistancesByMagnitude.FirstOrDefault(c => (c.Star1.StarNo == debugiStarNo && c.Star2.StarNo == debugkStarNo) || (c.Star1.StarNo == debugkStarNo && c.Star2.StarNo == debugiStarNo)); if (rightikEntry != null) Trace.Assert(rightikEntry.DistanceArcSec > dikMin && rightikEntry.DistanceArcSec < dikMax); else Trace.Assert(false, string.Format("Cannot find the ik pair ({0}, {1}) in the area distances.", debugiStarNo, debugkStarNo)); } } foreach (DistanceEntry ikEntry in ikCandidates) { bool debugTrippleFound = false; if (debug && ((debugiStarNo == ijEntry.Star1.StarNo && debugjStarNo == ijEntry.Star2.StarNo) || (debugiStarNo == ijEntry.Star2.StarNo && debugjStarNo == ijEntry.Star1.StarNo)) && (debugkStarNo == ikEntry.Star1.StarNo || debugkStarNo == ikEntry.Star2.StarNo)) { debugTrippleFound = true; } // Ratios are preserved when changing the focal length (with linear fit) so check the ratios here double fittedFocalLength = m_PlateConfig.GetFocalLengthFromMatch( ijEntry.DistanceArcSec, ikEntry.DistanceArcSec, iCenter, jCenter, kCenter, toleranceInArcSec, m_Settings.PyramidFocalLengthAllowance); if (double.IsNaN(fittedFocalLength)) { Trace.Assert(!debugTrippleFound); continue; } double djk = m_PlateConfig.GetDistanceInArcSec(jCenter.XDouble, jCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength); ulong iStarNo = uint.MaxValue; ulong needIdx1 = uint.MaxValue; ulong needIdx2 = uint.MaxValue; if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo) { // ik_1 = ij_1 = (i) iStarNo = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; needIdx2 = ijEntry.Star2.StarNo; } else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo) { // ik_1 = ij_2 = (i) iStarNo = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo) { // ik_2 = ij_1 = (i) iStarNo = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star2.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo) { // ik_2 = ij_2 = (i) iStarNo = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else { Trace.Assert(!debugTrippleFound); continue; } if (needIdx1 == needIdx2) { Trace.Assert(!debugTrippleFound); continue; } DistanceEntry jkEntry = m_DistancesByMagnitude.Where(e => (e.Star1.StarNo == needIdx1 && e.Star2.StarNo == needIdx2) || (e.Star1.StarNo == needIdx2 && e.Star2.StarNo == needIdx1)).FirstOrDefault(); if (jkEntry != null) { ulong jStarNo = uint.MaxValue; ulong kStarNo = uint.MaxValue; if (jkEntry.DistanceArcSec + toleranceInArcSec < djkMin) { Trace.Assert(!debugTrippleFound); continue; } if (jkEntry.DistanceArcSec - toleranceInArcSec > djkMax) { Trace.Assert(!debugTrippleFound); continue; } if (jkEntry.DistanceArcSec + toleranceInArcSec < djk) { Trace.Assert(!debugTrippleFound); continue; } if (jkEntry.DistanceArcSec - toleranceInArcSec > djk) { Trace.Assert(!debugTrippleFound); continue; } if (jkEntry.Star1.StarNo == needIdx1 && jkEntry.Star2.StarNo == needIdx2) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec); if (m_Solution != null) { jStarNo = needIdx1; kStarNo = needIdx2; debugFieldIdentified = true; } else { Trace.Assert(!debugTrippleFound); continue; } } if (jkEntry.Star1.StarNo == needIdx2 && jkEntry.Star2.StarNo == needIdx1) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, iStarNo, needIdx1, needIdx2, fittedFocalLength, true, toleranceInArcSec); if (m_Solution != null) { jStarNo = needIdx2; kStarNo = needIdx1; debugFieldIdentified = true; } else { Trace.Assert(!debugTrippleFound); continue; } } if (m_Solution != null) { if (TangraConfig.Settings.Astrometry.PyramidNumberOfPivots == 3) // Exist the initial alignment with only 3 candidate pivots return true; for (int l = 0; l < m_StarMap.Features.Count; l++) { var piramid = m_StarMap.Features[l]; if (piramid.FeatureId == i || piramid.FeatureId == j || piramid.FeatureId == k) continue; var lCenter = piramid.GetCenter(); // NOTE: Continue until a set of distances is found in the cache for the 4-th pivot double dli = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, iCenter.XDouble, iCenter.YDouble, fittedFocalLength); double dlj = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, jCenter.XDouble, jCenter.YDouble, fittedFocalLength); double dlk = m_PlateConfig.GetDistanceInArcSec(lCenter.XDouble, lCenter.YDouble, kCenter.XDouble, kCenter.YDouble, fittedFocalLength); List<DistanceEntry> ilCandidates = m_DistancesByMagnitude .Where(e => (e.Star1.StarNo == iStarNo || e.Star2.StarNo == iStarNo) && e.DistanceArcSec < dli + toleranceInArcSec && e.DistanceArcSec > dli - toleranceInArcSec) .ToList(); foreach (var cand_il in ilCandidates) { var lStar = cand_il.Star1.StarNo == iStarNo ? cand_il.Star2 : cand_il.Star1; List<DistanceEntry> jlCandidates = m_DistancesByMagnitude .Where(e => ((e.Star1.StarNo == jStarNo && e.Star2.StarNo == lStar.StarNo) || (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == jStarNo)) && e.DistanceArcSec < dlj + toleranceInArcSec && e.DistanceArcSec > dlj - toleranceInArcSec) .ToList(); List<DistanceEntry> klCandidates = m_DistancesByMagnitude .Where(e => ((e.Star1.StarNo == kStarNo && e.Star2.StarNo == lStar.StarNo) || (e.Star1.StarNo == lStar.StarNo && e.Star2.StarNo == kStarNo)) && e.DistanceArcSec < dlk + toleranceInArcSec && e.DistanceArcSec > dlk - toleranceInArcSec) .ToList(); if (jlCandidates.Count > 0 && klCandidates.Count > 0) { if (klCandidates.Count > 0) return true; } } } } } } } } finally { if (debug && !debugFieldIdentified) { DebugCheckUnidentifiedStars( dijMin, dijMax, dikMin, dikMax, djkMin, djkMax, debugiStarNo, debugjStarNo, debugkStarNo, i, j, k); } } return false; }
private bool LoopThroghFeatureTriangles( IStarMap starMap, double toleranceInArcSec, CheckTriangleCallback callback, CheckTriangleWithRatiosCallback callbackWithRatios) { if (m_PreviousFit != null) { if (TryMatchingPairsFromPreviousFit(starMap)) { // Successfull fit from star to feature matching inferred from the previous fit was successfull if (ImproveAndRetestSolution(0, 0, 0, true)) return true; else { Trace.WriteLine("Could improve solution from previous fit"); } } else { Trace.WriteLine("Could not match stars from previous fit"); } } if (m_ManualPairs != null && TryMatchingPairsFromManualPairs(starMap)) { // Successfull fit from star to feature matching inferred from the previous fit was successfull if (ImproveAndRetestSolution(0, 0, 0)) return true; } int n = starMap.FeaturesCount; if (m_Settings.PyramidOptimumStarsToMatch < n) { // TODO: Need to extract only the largest m_Settings.PyramidOptimumStarsToMatch features. } int total = n * (n - 1) * (n - 2) / 6; int counter = 0; int maxCombinationsBeforeFail = CorePyramidConfig.Default.MaxNumberOfCombinations; Stopwatch timeTaken = new Stopwatch(); timeTaken.Start(); bool delayWarningSent = false; // if (DebugResolvedStars != null) // { // int numInmagRegion, numPyramidStars; // GetNumStarsInRegionAndPyramidSet( // m_PyramidMinMag, m_PyramidMaxMag, // out numInmagRegion, out numPyramidStars); //#if ASTROMETRY_DEBUG // Trace.Assert(numInmagRegion > 3); // Trace.Assert(numPyramidStars > 3); //#endif // } if (m_ManualPairs != null && m_ManualPairs.Count <= 3) { if (m_ManualPairs.Count == 1) { int fixedFeatureIndex = m_ManualPairs.Keys.ToList()[0].FeatureId + 1; for (int k = 2; k <= n; k++) { for (int j = 1; j < k; j++) { var rv = CheckCombination(fixedFeatureIndex, j, k, starMap, toleranceInArcSec, callback, callbackWithRatios, timeTaken, ref counter, ref delayWarningSent, maxCombinationsBeforeFail, total, n); if (rv != null) return rv.Value; } } } else if (m_ManualPairs.Count == 2) { int fixedFeatureIndex1 = m_ManualPairs.Keys.ToList()[0].FeatureId + 1; int fixedFeatureIndex2 = m_ManualPairs.Keys.ToList()[1].FeatureId + 1; for (int k = 1; k <= n; k++) { var rv = CheckCombination(fixedFeatureIndex1, fixedFeatureIndex2, k, starMap, toleranceInArcSec, callback, callbackWithRatios, timeTaken, ref counter, ref delayWarningSent, maxCombinationsBeforeFail, total, n); if (rv != null) return rv.Value; } } else if (m_ManualPairs.Count == 3) { var m_FeatureId_i = m_ManualPairs.Keys.ToList()[0].FeatureId; var m_FeatureId_j = m_ManualPairs.Keys.ToList()[1].FeatureId; var m_FeatureId_k = m_ManualPairs.Keys.ToList()[2].FeatureId; ulong starNo1 = m_ManualPairs.Values.ToList()[0].StarNo; ulong starNo2 = m_ManualPairs.Values.ToList()[1].StarNo; ulong starNo3 = m_ManualPairs.Values.ToList()[2].StarNo; int fixedFeatureIndex1 = m_FeatureId_i + 1; int fixedFeatureIndex2 = m_FeatureId_j + 1; int fixedFeatureIndex3 = m_FeatureId_k + 1; var ijEntry = m_DistancesByMagnitude.FirstOrDefault(x => (x.Star1.StarNo == starNo1 && x.Star2.StarNo == starNo2) || (x.Star1.StarNo == starNo2 && x.Star2.StarNo == starNo1)); var ikEntry = m_DistancesByMagnitude.FirstOrDefault(x => (x.Star1.StarNo == starNo1 && x.Star2.StarNo == starNo3) || (x.Star1.StarNo == starNo3 && x.Star2.StarNo == starNo1)); var jkEntry = m_DistancesByMagnitude.FirstOrDefault(x => (x.Star1.StarNo == starNo3 && x.Star2.StarNo == starNo2) || (x.Star1.StarNo == starNo2 && x.Star2.StarNo == starNo3)); m_Solution = IsSuccessfulMatch(m_StarMap, fixedFeatureIndex1, fixedFeatureIndex2, fixedFeatureIndex3, ijEntry, ikEntry, jkEntry, starNo1, starNo2, starNo3, toleranceInArcSec); if (m_Solution != null) { if (ImproveAndRetestSolution(fixedFeatureIndex1, fixedFeatureIndex2, fixedFeatureIndex3)) { m_MatchedTriangle = string.Format("{0}-{1}-{2}:{5}:[{3}/{4}]", fixedFeatureIndex1, fixedFeatureIndex2, fixedFeatureIndex3, counter, total, n); return true; } } } } for (int k = 3; k <= n; k++) { for (int j = 2; j < k; j++) { for (int i = 1; i < j; i++) { var rv = CheckCombination(i, j, k, starMap, toleranceInArcSec, callback, callbackWithRatios, timeTaken, ref counter, ref delayWarningSent, maxCombinationsBeforeFail, total, n); if (rv != null) return rv.Value; } } } return false; }
public override void MouseDown(Point location) { if (m_SelectedCalibrationStar != null) { frmIdentifyCalibrationStar frmIdentifyCalibrationStar = new frmIdentifyCalibrationStar(m_CatalogueStars, m_UserStarIdentification); DialogResult res = m_VideoController.ShowDialog(frmIdentifyCalibrationStar); if (res == DialogResult.Abort) { m_UserStarIdentification.Clear(); } else if (res == DialogResult.OK && frmIdentifyCalibrationStar.SelectedStar != null) { m_UserStarIdentification.Add(m_SelectedCalibrationStar, frmIdentifyCalibrationStar.SelectedStar); if (m_UserStarIdentification.Keys.Count > 0 && m_UserStarIdentification.Keys.Count < 3) { m_VideoController.ShowMessageBox( string.Format("Identify another {0} star(s) to attempt calibration", 3 - m_UserStarIdentification.Keys.Count), "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Information); } if (m_UserStarIdentification.Keys.Count > 2) { List<PSFFit> keysList = m_UserStarIdentification.Keys.ToList(); IStar star1 = m_UserStarIdentification[keysList[0]]; IStar star2 = m_UserStarIdentification[keysList[1]]; IStar star3 = m_UserStarIdentification[keysList[2]]; double ArcSec1 = 1 / 3600.0; bool badRA = false; bool badDE = false; if (Math.Abs(star1.RADeg - star2.RADeg) < ArcSec1 || Math.Abs(star1.RADeg - star3.RADeg) < ArcSec1 || Math.Abs(star2.RADeg - star3.RADeg) < ArcSec1) { badRA = true; } if (Math.Abs(star1.DEDeg - star2.DEDeg) < ArcSec1 || Math.Abs(star1.DEDeg - star3.DEDeg) < ArcSec1 || Math.Abs(star2.DEDeg - star3.DEDeg) < ArcSec1) { badDE = true; } if (badRA) { m_VideoController.ShowMessageBox( "Two of the stars have almost identical Right Ascension. Please try again with different stars.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Clear(); } else if (badDE) { m_VideoController.ShowMessageBox( "Two of the stars have almost identical Declination. Please try again with different stars.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Clear(); } else { ThreeStarAstrometry threeStarSolution = ThreeStarAstrometry.SolveByThreeStars(m_Image, m_UserStarIdentification, m_Tolerance); if (threeStarSolution != null) { m_SolvedPlate = threeStarSolution; m_PlatesolveController.UpdateFocalLength((int)Math.Round(threeStarSolution.Image.EffectiveFocalLength)); m_RADegCenter = threeStarSolution.RA0Deg; m_DEDegCenter = threeStarSolution.DE0Deg; m_Image.EffectiveFocalLength = threeStarSolution.Image.EffectiveFocalLength; m_UserStarIdentification.Clear(); m_AstrometryController.RunCalibrationWithCurrentPreliminaryFit(); } else { m_VideoController.ShowMessageBox( "Cannot complete calibration. Please try again with higher initial fit tolerance and/or with different stars. Be sure that the stars are well separated.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Remove(m_UserStarIdentification.Keys.ToList()[2]); } } } } DrawCatalogStarsFit(); } else { m_StarPoint = new Point(location.X, location.Y); m_Panning = true; m_VideoController.SetPictureBoxCursor(CustomCursors.PanEnabledCursor); } }
private bool CheckTriangleByMagnitude(int i, int j, int k, double dij, double dik, double djk, double toleranceInArcSec) { List<DistanceEntry> ijCandidates = m_DistancesByMagnitude .Where(e => e.DistanceArcSec > dij - toleranceInArcSec && e.DistanceArcSec < dij + toleranceInArcSec).ToList(); if (m_ManualPairs != null && m_ManualPairs.Count <= 3) LimitIJtoManualPairs(ijCandidates); foreach (DistanceEntry ijEntry in ijCandidates) { List<DistanceEntry> ikCandidates = m_DistancesByMagnitude .Where(e => (e.Star1.StarNo == ijEntry.Star1.StarNo || e.Star2.StarNo == ijEntry.Star1.StarNo) && e.DistanceArcSec > dik - toleranceInArcSec && e.DistanceArcSec < dik + toleranceInArcSec) .ToList(); foreach (DistanceEntry ikEntry in ikCandidates) { ulong foundIdx0 = uint.MaxValue; ulong needIdx1 = uint.MaxValue; ulong needIdx2 = uint.MaxValue; if (ikEntry.Star1.StarNo == ijEntry.Star1.StarNo) { // ik_1 = ij_1 = (i) foundIdx0 = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; needIdx2 = ijEntry.Star2.StarNo; } else if (ikEntry.Star1.StarNo == ijEntry.Star2.StarNo) { // ik_1 = ij_2 = (i) foundIdx0 = ikEntry.Star1.StarNo; needIdx1 = ikEntry.Star2.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star1.StarNo) { // ik_2 = ij_1 = (i) foundIdx0 = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star2.StarNo; // (j) } else if (ikEntry.Star2.StarNo == ijEntry.Star2.StarNo) { // ik_2 = ij_2 = (i) foundIdx0 = ikEntry.Star2.StarNo; needIdx1 = ikEntry.Star1.StarNo; // (k) needIdx2 = ijEntry.Star1.StarNo; // (j) } else continue; if (needIdx1 == needIdx2) continue; DistanceEntry jkEntry = m_DistancesByMagnitude.Where(e => (e.Star1.StarNo == needIdx1 && e.Star2.StarNo == needIdx2) || (e.Star1.StarNo == needIdx2 && e.Star2.StarNo == needIdx1)).FirstOrDefault(); if (jkEntry != null) { if (jkEntry.DistanceArcSec + toleranceInArcSec < djk) continue; if (jkEntry.DistanceArcSec - toleranceInArcSec > djk) continue; if (jkEntry.Star1.StarNo == needIdx1 && jkEntry.Star2.StarNo == needIdx2) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, foundIdx0, needIdx1, needIdx2, toleranceInArcSec); if (m_Solution != null) return true; } if (jkEntry.Star1.StarNo == needIdx2 && jkEntry.Star2.StarNo == needIdx1) { m_Solution = IsSuccessfulMatch(m_StarMap, i, j, k, ijEntry, ikEntry, jkEntry, foundIdx0, needIdx1, needIdx2, toleranceInArcSec); if (m_Solution != null) return true; } } } } return false; }
public override void MouseMove(Point location) { bool dirty = false; int posX = location.X < 16 ? 16 : (location.X > TangraContext.Current.FrameWidth - 17 ? TangraContext.Current.FrameWidth - 17 : location.X); int posY = location.Y < 16 ? 16 : (location.Y > TangraContext.Current.FrameHeight - 17 ? TangraContext.Current.FrameHeight - 17 : location.Y); m_VideoController.DisplayCursorPositionDetails(location); m_SelectedCalibrationStar = null; if (!m_Panning) { if (m_Is3StarIdMode) { StarMapFeature closestFeature = AstrometryContext.Current.StarMap.GetFeatureInRadius(posX, posY, 2); if (closestFeature != null) { if (m_Is3StarIdMode) { m_VideoController.SetPictureBoxCursor(Cursors.Hand); PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit(posX, posY, 13, out psfFit); m_SelectedCalibrationStar = psfFit; } } else { m_VideoController.SetPictureBoxCursor(Cursors.Arrow); } } else { m_VideoController.SetPictureBoxCursor(CustomCursors.PanCursor); } } else if (m_Panning && m_StarPoint != Point.Empty) { ResetPreviousStar(); if (m_SolvedPlate != null) { double raDeg1, deDeg1, raDeg2, deDeg2; m_SolvedPlate.GetRADEFromImageCoords(location.X, location.Y, out raDeg1, out deDeg1); m_SolvedPlate.GetRADEFromImageCoords(m_StarPoint.X, m_StarPoint.Y, out raDeg2, out deDeg2); double ra = m_RADegCenter + (raDeg2 - raDeg1); double de = m_DEDegCenter + (deDeg2 - deDeg1); if (m_SolvedPlate is LeastSquareFittedAstrometry) { m_SolvedPlate = new LeastSquareFittedAstrometry(m_Image, ra, de, null /*m_SolvePlateConts*/); } else if (m_SolvedPlate is TangentalTransRotAstrometry) { m_SolvedPlate = new TangentalTransRotAstrometry(m_SolvedPlate as TangentalTransRotAstrometry, m_Image, ra, de, m_Eta); } else { m_SolvedPlate = new DirectTransRotAstrometry(m_Image, ra, de, m_Eta, m_Aspect); } } dirty = true; } if (dirty) { DrawCatalogStarsFit(); } }
public override void MouseDown(Point location) { if (m_SelectedCalibrationStar != null) { frmIdentifyCalibrationStar frmIdentifyCalibrationStar = new frmIdentifyCalibrationStar(m_CatalogueStars, m_UserStarIdentification); DialogResult res = m_VideoController.ShowDialog(frmIdentifyCalibrationStar); if (res == DialogResult.Abort) { m_UserStarIdentification.Clear(); } else if (res == DialogResult.OK && frmIdentifyCalibrationStar.SelectedStar != null) { m_UserStarIdentification.Add(m_SelectedCalibrationStar, frmIdentifyCalibrationStar.SelectedStar); if (m_UserStarIdentification.Keys.Count > 0 && m_UserStarIdentification.Keys.Count < 3) { m_VideoController.ShowMessageBox( string.Format("Identify another {0} star(s) to attempt calibration", 3 - m_UserStarIdentification.Keys.Count), "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Information); } if (m_UserStarIdentification.Keys.Count > 2) { List <PSFFit> keysList = m_UserStarIdentification.Keys.ToList(); IStar star1 = m_UserStarIdentification[keysList[0]]; IStar star2 = m_UserStarIdentification[keysList[1]]; IStar star3 = m_UserStarIdentification[keysList[2]]; double ArcSec1 = 1 / 3600.0; bool badRA = false; bool badDE = false; if (Math.Abs(star1.RADeg - star2.RADeg) < ArcSec1 || Math.Abs(star1.RADeg - star3.RADeg) < ArcSec1 || Math.Abs(star2.RADeg - star3.RADeg) < ArcSec1) { badRA = true; } if (Math.Abs(star1.DEDeg - star2.DEDeg) < ArcSec1 || Math.Abs(star1.DEDeg - star3.DEDeg) < ArcSec1 || Math.Abs(star2.DEDeg - star3.DEDeg) < ArcSec1) { badDE = true; } if (badRA) { m_VideoController.ShowMessageBox( "Two of the stars have almost identical Right Ascension. Please try again with different stars.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Clear(); } else if (badDE) { m_VideoController.ShowMessageBox( "Two of the stars have almost identical Declination. Please try again with different stars.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Clear(); } else { ThreeStarAstrometry threeStarSolution = ThreeStarAstrometry.SolveByThreeStars(m_Image, m_UserStarIdentification, m_Tolerance); if (threeStarSolution != null) { m_SolvedPlate = threeStarSolution; m_PlatesolveController.UpdateFocalLength((int)Math.Round(threeStarSolution.Image.EffectiveFocalLength)); m_RADegCenter = threeStarSolution.RA0Deg; m_DEDegCenter = threeStarSolution.DE0Deg; m_Image.EffectiveFocalLength = threeStarSolution.Image.EffectiveFocalLength; m_UserStarIdentification.Clear(); m_AstrometryController.RunCalibrationWithCurrentPreliminaryFit(); } else { m_VideoController.ShowMessageBox( "Cannot complete calibration. Please try again with higher initial fit tolerance and/or with different stars. Be sure that the stars are well separated.", "Tangra", MessageBoxButtons.OK, MessageBoxIcon.Error); m_UserStarIdentification.Remove(m_UserStarIdentification.Keys.ToList()[2]); } } } } DrawCatalogStarsFit(); } else { m_StarPoint = new Point(location.X, location.Y); m_Panning = true; m_VideoController.SetPictureBoxCursor(CustomCursors.PanEnabledCursor); } }
public void DrawCatalogStarsFit(Graphics g) { if (m_CatalogueStars == null) { m_LimitMag = -100; return; } bool hasManualStars = m_Is3StarIdMode && m_UserStarIdentification != null && m_UserStarIdentification.Count > 0; LeastSquareFittedAstrometry astrometry = null; astrometry = FittedAstrometryFromUserSelectedFitGrade(); IAstrometricFit fit = null; if (astrometry != null) { fit = astrometry; } else { fit = m_SolvedPlate; } if (fit != null) { double limitMag = (astrometry != null && astrometry.FitInfo.AllStarPairs.Count > 0) ? astrometry.FitInfo.AllStarPairs.Max(p => p.Mag) : m_LimitMag; foreach (IStar star in m_CatalogueStars) { if (star.Mag > limitMag) { continue; } double x, y; fit.GetImageCoordsFromRADE(star.RADeg, star.DEDeg, out x, out y); Pen starPen = catalogStarPen; Brush labelBruish = catalogBrushUnrecognized; if (astrometry != null) { PlateConstStarPair pair = astrometry.FitInfo.AllStarPairs.Find((p) => p.StarNo == star.StarNo); if (pair != null && pair.FitInfo.UsedInSolution) { starPen = referenceStarPen; labelBruish = catalogBrushReference; } else if (pair != null && pair.FitInfo.ExcludedForHighResidual) { starPen = rejectedStarPen; labelBruish = catalogBrushRejected; } else { starPen = unrecognizedStarPen; labelBruish = catalogBrushUnrecognized; } if (pair != null) { g.DrawLine(starPen, (float)x, (float)y, (float)pair.x, (float)pair.y); } } if (!m_Is3StarIdMode || astrometry != null) { float rad = (float)GetStarDiameter(m_LimitMag, 5, star.Mag) / 2; g.DrawEllipse(starPen, (float)x - rad, (float)y - rad, 2 * rad, 2 * rad); } if (m_ShowLabels || m_ShowMagnitudes) { string label; if (m_ShowLabels && m_ShowMagnitudes) { label = string.Format("{0} ({1}m)", star.GetStarDesignation(0), star.Mag); } else if (m_ShowLabels) { label = string.Format("{0}", star.GetStarDesignation(0)); } else { label = string.Format("{0}m", star.Mag); } g.DrawString(label, m_StarInfoFont, labelBruish, (float)x + 10, (float)y + 10); } } if (m_Is3StarIdMode && astrometry == null) { // Draw all features from the starMap (unless the configuration has been solved) if (AstrometryContext.Current.StarMap != null) { foreach (StarMapFeature feature in AstrometryContext.Current.StarMap.Features) { ImagePixel center = feature.GetCenter(); PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearAsymetricFit, out psfFit); #if ASTROMETRY_DEBUG PSFFit psfFit2; AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit2); double elong = psfFit.RX0 / psfFit.RY0; double elongPerc = Math.Abs(1 - elong) * 100; Trace.WriteLine(string.Format("({0:0}, {1:0}) Rx = {2:0.00} Ry = {3:0.00}, e = {4:0.000} ({5:0}%), FWHMxy = {6:0.0} | FWHMxx = {7:0.0}", center.X, center.Y, psfFit.RX0, psfFit.RY0, elong, elongPerc, psfFit.FWHM, psfFit2.FWHM)); #endif Pen pen = catalogStarPen; #if ASTROMETRY_DEBUG if (psfFit.FWHM < TangraConfig.Settings.Astrometry.MinReferenceStarFWHM || psfFit.FWHM > TangraConfig.Settings.Astrometry.MaxReferenceStarFWHM || psfFit.ElongationPercentage > TangraConfig.Settings.Astrometry.MaximumPSFElongation) { pen = rejectedStarPen; } #endif g.DrawLine(pen, (float)center.XDouble - 9, (float)center.YDouble, (float)center.XDouble - 5, (float)center.YDouble); g.DrawLine(pen, (float)center.XDouble + 5, (float)center.YDouble, (float)center.XDouble + 9, (float)center.YDouble); g.DrawLine(pen, (float)center.XDouble, (float)center.YDouble - 9, (float)center.XDouble, (float)center.YDouble - 5); g.DrawLine(pen, (float)center.XDouble, (float)center.YDouble + 5, (float)center.XDouble, (float)center.YDouble + 9); } } } else { if (m_Grid) { DrawEquatorialGrid(g); } } #region Draw the manual single star identification if (hasManualStars) { foreach (PSFFit psf in m_UserStarIdentification.Keys) { IStar star = m_UserStarIdentification[psf]; float rad = (float)GetStarDiameter(m_LimitMag, 5, star.Mag) / 2; g.DrawEllipse(Pens.DarkRed, (float)psf.XCenter - rad, (float)psf.YCenter - rad, 2 * rad, 2 * rad); g.DrawEllipse(Pens.DarkRed, (float)psf.XCenter - rad - 2, (float)psf.YCenter - rad - 2, 2 * rad + 4, 2 * rad + 4); } } #endregion ; } UpdateToolControlDisplay(); }
public override void MouseMove(Point location) { bool dirty = false; int posX = location.X < 16 ? 16 : (location.X > TangraContext.Current.FrameWidth - 17 ? TangraContext.Current.FrameWidth - 17 : location.X); int posY = location.Y < 16 ? 16 : (location.Y > TangraContext.Current.FrameHeight - 17 ? TangraContext.Current.FrameHeight - 17 : location.Y); m_VideoController.DisplayCursorPositionDetails(location); m_SelectedCalibrationStar = null; if (!m_Panning) { if (m_Is3StarIdMode) { StarMapFeature closestFeature = AstrometryContext.Current.StarMap.GetFeatureInRadius(posX, posY, 2); if (closestFeature != null) { if (m_Is3StarIdMode) { m_VideoController.SetPictureBoxCursor(Cursors.Hand); PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit(posX, posY, 13, out psfFit); m_SelectedCalibrationStar = psfFit; } } else m_VideoController.SetPictureBoxCursor(Cursors.Arrow); } else m_VideoController.SetPictureBoxCursor(CustomCursors.PanCursor); } else if (m_Panning && m_StarPoint != Point.Empty) { ResetPreviousStar(); if (m_SolvedPlate != null) { double raDeg1, deDeg1, raDeg2, deDeg2; m_SolvedPlate.GetRADEFromImageCoords(location.X, location.Y, out raDeg1, out deDeg1); m_SolvedPlate.GetRADEFromImageCoords(m_StarPoint.X, m_StarPoint.Y, out raDeg2, out deDeg2); double ra = m_RADegCenter + (raDeg2 - raDeg1); double de = m_DEDegCenter + (deDeg2 - deDeg1); if (m_SolvedPlate is LeastSquareFittedAstrometry) m_SolvedPlate = new LeastSquareFittedAstrometry(m_Image, ra, de, null /*m_SolvePlateConts*/); else if (m_SolvedPlate is TangentalTransRotAstrometry) m_SolvedPlate = new TangentalTransRotAstrometry(m_SolvedPlate as TangentalTransRotAstrometry, m_Image, ra, de, m_Eta); else m_SolvedPlate = new DirectTransRotAstrometry(m_Image, ra, de, m_Eta, m_Aspect); } dirty = true; } if (dirty) { DrawCatalogStarsFit(); } }
protected virtual void ReinitializePlateConstants() { m_Image = m_AstrometryController.GetCurrentAstroPlate(); m_Image.EffectiveFocalLength = m_FLength; if (m_SolvedPlate is LeastSquareFittedAstrometry) m_SolvedPlate = new LeastSquareFittedAstrometry(m_Image, m_RADegCenter, m_DEDegCenter, null /*m_SolvePlateConts*/); else if (m_SolvedPlate is TangentalTransRotAstrometry) m_SolvedPlate = new TangentalTransRotAstrometry(m_SolvedPlate as TangentalTransRotAstrometry, m_Image, m_RADegCenter, m_DEDegCenter, m_Eta); else { m_SolvedPlate = new DirectTransRotAstrometry(m_Image, m_RADegCenter, m_DEDegCenter, m_Eta, m_Aspect); } }