public override void MouseClick(ObjectClickEventArgs e) { if (m_State == FittingsState.Configuring) { m_OSDExcluderTool.MouseClick(e); } if (m_State == FittingsState.Solved) { IStarMap starMap = AstrometryContext.Current.StarMap; if (starMap != null) { int x, y; StarMapFeature feature = starMap.GetFeatureInRadius(e.Pixel.X, e.Pixel.Y, 5); if (feature != null) { x = feature.GetCenter().X; y = feature.GetCenter().Y; } else { x = e.Pixel.X; y = e.Pixel.Y; } int searchArea = Control.ModifierKeys == Keys.Shift ? 5 : 10; PSFFit psfFit; ImagePixel pixelCent = starMap.GetPSFFit(x, y, searchArea, out psfFit); if (pixelCent != null && pixelCent != ImagePixel.Unspecified) { PlateConstStarPair selectedPair = null; LeastSquareFittedAstrometry astrometry = FittedAstrometryFromUserSelectedFitGrade(); if (astrometry != null) { foreach (PlateConstStarPair pair in astrometry.FitInfo.AllStarPairs) { if (Math.Abs(pair.x - pixelCent.X) < 2 && Math.Abs(pair.y - pixelCent.Y) < 2) { selectedPair = pair; break; } } } DrawHighResFeature(pixelCent, selectedPair, astrometry); } else { ClearZoomImage(); } } } }
public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit) { IsTrackedSuccessfully = false; ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid( (int)TrackedObject.LastKnownX, (int)TrackedObject.LastKnownY, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius); if (centroid != null) { PSFFit psfFit; AstrometryContext.Current.StarMap.GetPSFFit( centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit); if (psfFit != null) { double ra, de; astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de); double maxPosDiffArcSec = astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage, astrometricFit.Image.CenterXImage + CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius, astrometricFit.Image.CenterYImage); if (!double.IsNaN(TrackedObject.RAHours)) { double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de); if (posDif > maxPosDiffArcSec) { // NOTE: Not a valid measurement Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif)); return; } } TrackedObject.RAHours = ra / 15.0; TrackedObject.DEDeg = de; TrackedObject.LastKnownX = psfFit.XCenter; TrackedObject.LastKnownY = psfFit.YCenter; TrackedObject.PSFFit = psfFit; IsTrackedSuccessfully = true; } } }
public void InitNewMatch(IStarMap imageFeatures, PyramidMatchType matchType, Dictionary <PSFFit, IStar> manualStars) { m_StarMap = imageFeatures; if (manualStars != null) { SetManuallyIdentifiedHints(manualStars); } matchType = PyramidMatchType.PlateSolve; m_IsCalibration = matchType == PyramidMatchType.ConfigCalibration; Context.Initialize(m_RA0Deg, m_DE0Deg, m_CelestialStars, m_PyramidMinMag, m_PyramidMaxMag, m_DetermineAutoLimitMagnitude, m_ManualStarMatch); #if ASTROMETRY_DEBUG AstrometricFitDebugger.Init(m_FitSettings, m_PyramidMinMag, m_PyramidMaxMag, m_AstrometryMinMag, m_AstrometryMaxMag); #endif }
internal FieldAlignmentResult DoFieldAlignment(IStarMap starMap) { return DoFieldAlignment(starMap, (FitInfo)null, false); }
private bool CheckTriangleWithRatios(IStarMap starMap, CheckTriangleWithRatiosCallback callback, int i, int j, int k, double toleranceInArcSec) { m_Feature_i = starMap.Features[i - 1]; m_Feature_j = starMap.Features[j - 1]; m_Feature_k = starMap.Features[k - 1]; m_FeatureId_i = m_Feature_i.FeatureId; m_FeatureId_j = m_Feature_j.FeatureId; m_FeatureId_k = m_Feature_k.FeatureId; long idx_ij = (m_FeatureId_i << 32) + m_FeatureId_j; long idx_ik = (m_FeatureId_i << 32) + m_FeatureId_k; long idx_jk = (m_FeatureId_j << 32) + m_FeatureId_k; ImagePixel feature_i_Center = null; ImagePixel feature_j_Center = null; ImagePixel feature_k_Center = null; double dist_ij; if (!m_FeaturesDistanceCache.TryGetValue(idx_ij, out dist_ij)) { if (feature_i_Center == null) feature_i_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_i), starMap); if (feature_j_Center == null) feature_j_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_j), starMap); } double dist_ik; if (!m_FeaturesDistanceCache.TryGetValue(idx_ik, out dist_ik)) { if (feature_i_Center == null) feature_i_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_i), starMap); if (feature_k_Center == null) feature_k_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_k), starMap); } double dist_jk; if (!m_FeaturesDistanceCache.TryGetValue(idx_jk, out dist_jk)) { if (feature_j_Center == null) feature_j_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_j), starMap); if (feature_k_Center == null) feature_k_Center = GetCenterOfFeature(starMap.GetFeatureById((int)m_FeatureId_k), starMap); } if (callback(i, j, k, feature_i_Center, feature_j_Center, feature_k_Center, toleranceInArcSec)) // solution found return true; return false; }
public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit) { IsTrackedSuccessfully = false; int searchRadius = (int)Math.Ceiling(Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius)); PSFFit psfFit = null; int startingX = (int)TrackedObject.LastKnownX; int startingY = (int)TrackedObject.LastKnownY; if (m_RepeatedIntergationPositions * 4 < m_PastFrameNos.Count) { var expectedPos = GetExpectedPosition(frameNo); if (expectedPos != null) { startingX = expectedPos.X; startingY = expectedPos.Y; } } var nearbyFeatures = starMap.GetFeaturesInRadius(startingX, startingY, searchRadius).ToArray(); var nonStarNearbyFeature = new List <StarMapFeature>(); foreach (var feature in nearbyFeatures) { var center = feature.GetCenter(); var referenceStarFeatures = astrometricFit.FitInfo.AllStarPairs.Where(x => x.FitInfo.UsedInSolution).ToList(); var refStar = referenceStarFeatures.FirstOrDefault(s => Math.Sqrt((s.x - center.X) * (s.x - center.X) + (s.y - center.Y) * (s.y - center.Y)) < 2); double raf, def; astrometricFit.GetRADEFromImageCoords(center.XDouble, center.YDouble, out raf, out def); var pastKnownStar = m_LastFrameStars.FirstOrDefault(s => AngleUtility.Elongation(s.RADeg, s.DEDeg, raf, def) * 3600.0 < 2); if (refStar == null && pastKnownStar == null) { nonStarNearbyFeature.Add(feature); } } if (nonStarNearbyFeature.Count > 0) { StarMapFeature closestFeature = nonStarNearbyFeature[0]; var lastKnownCenter = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY); var smallestDistance = lastKnownCenter.DistanceTo(closestFeature.GetCenter()); for (int i = 1; i < nonStarNearbyFeature.Count; i++) { var distance = lastKnownCenter.DistanceTo(nonStarNearbyFeature[i].GetCenter()); if (distance < smallestDistance) { smallestDistance = distance; closestFeature = nonStarNearbyFeature[i]; } } if (closestFeature != null) { var center = closestFeature.GetCenter(); AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit); } } if (psfFit == null) { // The expected location cannot be matched with any brighter feature so it is likely a faint object // with no brighter objects around. Lets find the brightest (faint) object in the are and use it ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid(startingX, startingY, searchRadius); if (centroid != null) { AstrometryContext.Current.StarMap.GetPSFFit(centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit); } } if (psfFit != null) { double ra, de; astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de); double maxPosDiffArcSec = astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage, astrometricFit.Image.CenterXImage + Math.Max(m_LastMovementPixels, CoreAstrometrySettings.Default.MaxAllowedDefaultMotionInPixels), astrometricFit.Image.CenterYImage); if (!double.IsNaN(TrackedObject.RAHours)) { double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de); if (posDif > maxPosDiffArcSec) { // NOTE: Not a valid measurement Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif)); return; } } TrackedObject.RAHours = ra / 15.0; TrackedObject.DEDeg = de; if (TrackedObject.PSFFit != null) { m_LastMovementPixels = 1.2 * ImagePixel.ComputeDistance(TrackedObject.LastKnownX, psfFit.XCenter, TrackedObject.LastKnownY, psfFit.YCenter); } TrackedObject.LastKnownX = psfFit.XCenter; TrackedObject.LastKnownY = psfFit.YCenter; TrackedObject.PSFFit = psfFit; var lastKnownCenter = new ImagePixel(TrackedObject.LastKnownX, TrackedObject.LastKnownY); var thisFrameStars = astrometricFit.FitInfo.AllStarPairs.Where(x => lastKnownCenter.DistanceTo(x.x, x.y) > 2 * psfFit.FWHM).ToList(); if (thisFrameStars.Count > 0) { m_LastFrameStars = thisFrameStars.Select(x => new Star(x.StarNo, x.RADeg, x.DEDeg, x.Mag) as IStar).ToList(); } IsTrackedSuccessfully = true; } if (psfFit != null && psfFit.XCenter > 0 && psfFit.YCenter > 0) { m_PastFramePosX.Add(psfFit.XCenter); m_PastFramePosY.Add(psfFit.YCenter); m_PastFrameNos.Add(frameNo); } }
public override void MouseMove(Point location) { IStarMap map = AstrometryContext.Current.StarMap; if (map == null) { return; } bool nearbyStarFound = false; AstrometricState state = AstrometryContext.Current.AstrometricState; if (state != null) { if (state.AstrometricFit != null) { for (int radius = 1; radius < 8; radius++) { ImagePixel centroid = map.GetCentroid(location.X, location.Y, radius); if (centroid == null) { continue; } foreach (PlateConstStarPair star in state.AstrometricFit.FitInfo.AllStarPairs) { if (Math.Abs(star.x - centroid.XDouble) < radius && Math.Abs(star.y - centroid.YDouble) < radius) { m_Object = star; nearbyStarFound = true; break; } } if (nearbyStarFound) { break; } } if (!nearbyStarFound) { m_State = SelectObjectState.NoObject; } else { m_State = SelectObjectState.ObjectLocked; } if (m_AstrometricState.MeasuringState == AstrometryInFramesState.Ready) { double ra, de; state.AstrometricFit.GetRADEFromImageCoords(location.X, location.Y, out ra, out de); string moreInfo = string.Format("RA={0} DE={1}", AstroConvert.ToStringValue(ra / 15, "HHhMMmSS.Ts"), AstroConvert.ToStringValue(de, "+DD°MM'SS\"")); m_VideoController.DisplayCursorPositionDetails(location, moreInfo); } } else { StarMapFeature nearbyFeature = map.GetFeatureInRadius(location.X, location.Y, 8); nearbyStarFound = nearbyFeature != null && nearbyFeature.PixelCount > 4; } m_VideoController.SetPictureBoxCursor(nearbyStarFound ? Cursors.Hand : (state.ManualStarIdentificationMode ? Cursors.Cross : Cursors.Default)); } }
public void InitNewFrame(IStarMap imageFeatures) { m_StarMap = imageFeatures; // NOTE: The m_Solution will be reused until the DistanceBasedAstrometrySolver is recreated }
internal FieldAlignmentResult DoFieldAlignmentFitFocalLength(IStarMap starMap) { return DoFieldAlignment(starMap, (FitInfo)null, true); }
private LeastSquareFittedAstrometry SolveStarPairs( IStarMap starMap, Dictionary<ImagePixel, IStar> matchedPairs, Dictionary<int, ulong> matchedFeatureIdToStarIdIndexes, ThreeStarFit.StarPair pair_i, ThreeStarFit.StarPair pair_j, ThreeStarFit.StarPair pair_k, double fittedFocalLength, PyramidEntry pyramidLog, int? minMatchedStars = null) { double RA0Deg, DE0Deg; ThreeStarFit coarseFit = new ThreeStarFit(m_PlateConfig, pair_i, pair_j, pair_k); if (!coarseFit.IsSolved) { if (coarseFit.IsSingularity) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine("ThreeStarFit.Var1 - Singularity"); Dictionary<ImagePixel, IStar> threeStarDict = new Dictionary<ImagePixel, IStar>(); try { threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(0, 255, pair_i.XImage, pair_i.YImage), pair_i.Star); threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(1, 255, pair_j.XImage, pair_j.YImage), pair_j.Star); threeStarDict.Add(ImagePixel.CreateImagePixelWithFeatureId(2, 255, pair_k.XImage, pair_k.YImage), pair_k.Star); } catch(ArgumentException) { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine("ThreeStarFit.Var2 - Failed with ArgumentException"); return null; } DirectTransRotAstrometry threeStarSolution = DirectTransRotAstrometry.SolveByThreeStars(m_PlateConfig, threeStarDict, 2); if (threeStarSolution == null) { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine("ThreeStarFit.Var2 - Failed"); return null; } else { RA0Deg = threeStarSolution.RA0Deg; DE0Deg = threeStarSolution.DE0Deg; } } else { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.ThreeStarFitFailed; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine("ThreeStarFit.Var1 - Failed"); return null; } } else { if (pyramidLog != null) pyramidLog.RegisterThreeStarFit(coarseFit); RA0Deg = coarseFit.RA0Deg; DE0Deg = coarseFit.DE0Deg; } #if DEBUG || PYRAMID_DEBUG if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { foreach (int key in matchedFeatureIdToStarIdIndexes.Keys) #if PYRAMID_DEBUG Trace #else Debug #endif .WriteLine(string.Format("Star({0}) -> Feature({1})", matchedFeatureIdToStarIdIndexes[key], key)); } #endif PlateConstantsSolver solver = new PlateConstantsSolver(m_PlateConfig); solver.InitPlateSolution(RA0Deg, DE0Deg); foreach (ImagePixel feature in matchedPairs.Keys) { IStar star = matchedPairs[feature]; var kvp = matchedFeatureIdToStarIdIndexes.Single(x => x.Value == star.StarNo); int featureId = kvp.Key; solver.AddStar(feature, star, featureId); } LeastSquareFittedAstrometry leastSquareFittedAstrometry = null; LeastSquareFittedAstrometry firstFit = null; try { // This is a linear regression when doing simple field alignment. We always use a Linear Fit leastSquareFittedAstrometry = solver.SolveWithLinearRegression( FitOrder.Linear, CorePyramidConfig.Default.MinPyramidAlignedStars, m_MaxLeastSquareResidual, out firstFit); } catch (DivideByZeroException) { } if (leastSquareFittedAstrometry != null) { if (pyramidLog != null) pyramidLog.RegisterLinearFit(leastSquareFittedAstrometry); if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine("Checking possible solution. "); List<ulong> usedStarIds = leastSquareFittedAstrometry.FitInfo.AllStarPairs .Where(p => p.FitInfo.UsedInSolution) .Select(p => p.StarNo) .ToList(); int usedStars = usedStarIds.Count; matchedFeatureIdToStarIdIndexes = matchedFeatureIdToStarIdIndexes .Where(kvp => usedStarIds.Contains(kvp.Value)) .ToDictionary(kvp => kvp.Key, kvp => kvp.Value); List<double> residuals = leastSquareFittedAstrometry.FitInfo.AllStarPairs .Where(p => !p.FitInfo.ExcludedForHighResidual) .Select(p => p.FitInfo.ResidualArcSec) .ToList(); double secondLargeResidual = 0; if (residuals.Count > 0) { residuals = residuals.OrderByDescending(r => r).ToList(); secondLargeResidual = residuals.Count > 1 ? residuals[1] : residuals[0]; } double onePixDistArcSec = m_PlateConfig.GetDistanceInArcSec(0, 0, 1, 1); if (secondLargeResidual > onePixDistArcSec * CorePyramidConfig.Default.MaxAllowedResidualInPixelsInSuccessfulFit) { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.SecondLargestResidualIsTooLarge; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(string.Format( "Failing preliminary solution because the second largest residual {0}\" is larger than {1}px", secondLargeResidual.ToString("0.0"), CorePyramidConfig.Default.MaxAllowedResidualInPixelsInSuccessfulFit)); return null; } if (minMatchedStars.HasValue) { if (usedStars < minMatchedStars.Value) { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.InsufficientStarsForCalibration; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(string.Format( "Failing preliminary solution because on {0} stars are used but {1} are required as a minimum for calibration.", usedStars, CorePyramidConfig.Default.MinMatchedStarsForCalibration)); return null; } } } else { if (pyramidLog != null) pyramidLog.FailureReason = PyramidEntryFailureReason.LinearFitFailed; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { Debug.WriteLine("DistanceBasedContext.LeastSquareFittedAstrometry Failed!"); foreach (PlateConstStarPair pair in solver.Pairs) { #if PYRAMID_DEBUG Trace #else Debug #endif .WriteLine(string.Format("{0} ({1}) -> Residuals: {2}\", {3}\"", pair.StarNo, pair.FitInfo.UsedInSolution ? "Included" : "Excluded", pair.FitInfo.ResidualRAArcSec.ToString("0.00"), pair.FitInfo.ResidualDEArcSec.ToString("0.00"))); } } } if (leastSquareFittedAstrometry != null) { leastSquareFittedAstrometry.FitInfo.FittedFocalLength = fittedFocalLength; if (pyramidLog != null) pyramidLog.RegisterFocalLength(fittedFocalLength); } return leastSquareFittedAstrometry; }
internal IAstrometricFit IsSuccessfulMatch( IStarMap starMap, int i, int j, int k, DistanceEntry ijEntry, DistanceEntry ikEntry, DistanceEntry jkEntry, ulong iStarNo, ulong starNo2, ulong starNo3, double fittedFocalLength, bool isRatioFittedFocalLength, double toleranceInArcSec) { i--; j--; k--; ImagePixel feature_i = GetCenterOfFeature(starMap.GetFeatureById(i), starMap); ImagePixel feature_j = GetCenterOfFeature(starMap.GetFeatureById(j), starMap); ImagePixel feature_k = GetCenterOfFeature(starMap.GetFeatureById(k), starMap); #region find the numbers of the three stars: i, j, k #if ASTROMETRY_DEBUG Trace.Assert(ijEntry.Star1.StarNo == iStarNo || ijEntry.Star2.StarNo == iStarNo); #endif ulong jStarNo, kStarNo; if (ijEntry.Star1.StarNo == iStarNo) { jStarNo = ijEntry.Star2.StarNo; if (ijEntry.Star2.StarNo == starNo2) kStarNo = starNo3; else kStarNo = starNo2; } else { jStarNo = ijEntry.Star1.StarNo; if (ijEntry.Star1.StarNo == starNo2) kStarNo = starNo3; else kStarNo = starNo2; } #if ASTROMETRY_DEBUG Trace.Assert(ikEntry.Star1.StarNo == kStarNo || ikEntry.Star2.StarNo == kStarNo); Trace.Assert(jkEntry.Star1.StarNo == kStarNo || jkEntry.Star2.StarNo == kStarNo); #endif #endregion //if (DebugResolvedStars != null) //{ // uint ii = 0, jj = 0, kk = 0; // if (DebugResolvedStars.TryGetValue(i + 1, out ii) && // DebugResolvedStars.TryGetValue(j + 1, out jj) && // DebugResolvedStars.TryGetValue(k + 1, out kk)) // { // if (ii == iStarNo && jj == starNo2 && kk == starNo3) // { // Debugger.Break(); // } // else // Trace.WriteLine(string.Format("PYRAMID: {0} = {1}, {2} = {3}, {4} = {5}", // i, i == ii ? "YES" : "NO" // , j, j == jj ? "YES" : "NO" // , k, k == kk ? "YES" : "NO")); // } // else // Trace.WriteLine(string.Format("PYRAMID: {0} = {1}, {2} = {3}, {4} = {5}", // i, i == ii ? "YES" : "MISSING" // , j, j == jj ? "YES" : "MISSING" // , k, k == kk ? "YES" : "MISSING")); //} #if ASTROMETRY_DEBUG PyramidEntry pyramidLog = new PyramidEntry(i, j, k, feature_i, feature_j, feature_k, iStarNo, jStarNo, kStarNo); #endif //// Note this is actually cheap way to confirm whether the 3 stars are good or not. //List<IStar> threeStars = m_CelestialAllStars.FindAll(s => s.StarNo == iStarNo || s.StarNo == jStarNo || s.StarNo == kStarNo); //if (threeStars.Count == 3) //{ // Dictionary<AstroPixel, IStar> threeStarDict = new Dictionary<AstroPixel, IStar>(); // IStar stari = threeStars.Find(s => s.StarNo == iStarNo); // threeStarDict.Add(feature_i, stari); // IStar starj = threeStars.Find(s => s.StarNo == jStarNo); // threeStarDict.Add(feature_j, starj); // IStar stark = threeStars.Find(s => s.StarNo == kStarNo); // threeStarDict.Add(feature_k, stark); // DirectTransRotAstrometry solution = DirectTransRotAstrometry.SolveByThreeStars(m_PlateConfig, threeStarDict); // if (solution != null) // { // pyramidLog.RegisterPreliminaryThreeStarFit(solution); // } //} int locatedStars = 3; m_MatchedPairs.Clear(); m_AmbiguousMatches.Clear(); m_MatchedFeatureIdToStarIdIndexes.Clear(); List<ulong> usedPyramidAngles = new List<ulong>(); foreach (StarMapFeature feature in starMap.Features) { if (feature.FeatureId == i) continue; if (feature.FeatureId == j) continue; if (feature.FeatureId == k) continue; long idx_ix = ((long)i << 32) + (long)feature.FeatureId; double dist_ix; ImagePixel feature_x = GetCenterOfFeature(feature, starMap); if (m_MatchedPairs.ContainsKey(feature_x)) continue; if (isRatioFittedFocalLength || !m_FeaturesDistanceCache.TryGetValue(idx_ix, out dist_ix)) { dist_ix = m_PlateConfig.GetDistanceInArcSec(feature_i.X, feature_i.Y, feature_x.X, feature_x.Y, fittedFocalLength); long idx_xi = ((long)feature.FeatureId << 32) + (long)i; if (!isRatioFittedFocalLength) { m_FeaturesDistanceCache.Add(idx_ix, dist_ix); m_FeaturesDistanceCache.Add(idx_xi, dist_ix); } } Dictionary<ulonglong, DistanceEntry> iStarDists = m_StarsDistanceCache[iStarNo]; foreach (ulonglong key in iStarDists.Keys) { // We have found a distance that matches the current feature ulong xStarNo = key.Lo; if (usedPyramidAngles.IndexOf(xStarNo) != -1) continue; DistanceEntry entry_ix = iStarDists[key]; if (entry_ix.DistanceArcSec + toleranceInArcSec < dist_ix) continue; if (entry_ix.DistanceArcSec - toleranceInArcSec > dist_ix) continue; Dictionary<ulonglong, DistanceEntry> xStarDists = m_StarsDistanceCache[xStarNo]; #region Test the J-X pair ulonglong jxKey = new ulonglong(xStarNo , jStarNo); DistanceEntry entry_jx; if (!xStarDists.TryGetValue(jxKey, out entry_jx)) continue; long idx_jx = ((long)j << 32) + (long)feature.FeatureId; double dist_jx; if (isRatioFittedFocalLength || !m_FeaturesDistanceCache.TryGetValue(idx_jx, out dist_jx)) { dist_jx = m_PlateConfig.GetDistanceInArcSec(feature_j.X, feature_j.Y, feature_x.X, feature_x.Y, fittedFocalLength); long idx_xj = ((long)feature.FeatureId << 32) + (long)j; if (!isRatioFittedFocalLength) { m_FeaturesDistanceCache.Add(idx_jx, dist_jx); m_FeaturesDistanceCache.Add(idx_xj, dist_jx); } } if (entry_jx.DistanceArcSec + toleranceInArcSec < dist_jx) continue; if (entry_jx.DistanceArcSec - toleranceInArcSec > dist_jx) continue; #endregion #region Test the K-X pair ulonglong kxKey = new ulonglong(xStarNo, kStarNo); DistanceEntry entry_kx; if (!xStarDists.TryGetValue(kxKey, out entry_kx)) continue; long idx_kx = ((long)k << 32) + (long)feature.FeatureId; double dist_kx; if (isRatioFittedFocalLength || !m_FeaturesDistanceCache.TryGetValue(idx_kx, out dist_kx)) { dist_kx = m_PlateConfig.GetDistanceInArcSec(feature_k.X, feature_k.Y, feature_x.X, feature_x.Y, fittedFocalLength); long idx_xk = ((long)feature.FeatureId << 32) + (long)k; if (!isRatioFittedFocalLength) { m_FeaturesDistanceCache.Add(idx_kx, dist_kx); m_FeaturesDistanceCache.Add(idx_xk, dist_kx); } } if (entry_kx.DistanceArcSec + toleranceInArcSec < dist_kx) continue; if (entry_kx.DistanceArcSec - toleranceInArcSec > dist_kx) continue; #endregion // If we are here, then we have found another star locatedStars++; IStar xStar = entry_kx.Star1.StarNo == xStarNo ? entry_kx.Star1 : entry_kx.Star2; #if ASTROMETRY_DEBUG Trace.Assert(xStar.StarNo != iStarNo); Trace.Assert(xStar.StarNo != jStarNo); Trace.Assert(xStar.StarNo != kStarNo); #endif if (RegisterRecognizedPair(feature_x, xStar, feature.FeatureId)) { usedPyramidAngles.Add(xStar.StarNo); } //Console.WriteLine(string.Format(" {0} ({1}) {2}\" {3}\" {4}\"", xStarNo, feature.FeatureId, dist_ix.ToString("0.0"), dist_jx.ToString("0.0"), dist_kx.ToString("0.0"))); } } if (locatedStars >= CorePyramidConfig.Default.MinPyramidAlignedStars) { ThreeStarFit.StarPair pair_i = new ThreeStarFit.StarPair(feature_i.X, feature_i.Y); ThreeStarFit.StarPair pair_j = new ThreeStarFit.StarPair(feature_j.X, feature_j.Y); ThreeStarFit.StarPair pair_k = new ThreeStarFit.StarPair(feature_k.X, feature_k.Y); if (ijEntry.Star1.StarNo == iStarNo) { pair_i.RADeg = ijEntry.Star1.RADeg; pair_i.DEDeg = ijEntry.Star1.DEDeg; pair_i.Star = ijEntry.Star1; pair_j.RADeg = ijEntry.Star2.RADeg; pair_j.DEDeg = ijEntry.Star2.DEDeg; pair_j.Star = ijEntry.Star2; #if ASTROMETRY_DEBUG Trace.Assert(ijEntry.Star1.StarNo == iStarNo); Trace.Assert(ijEntry.Star2.StarNo == jStarNo); #endif RegisterRecognizedPair(feature_i, ijEntry.Star1, i); RegisterRecognizedPair(feature_j, ijEntry.Star2, j); } else { pair_i.RADeg = ijEntry.Star2.RADeg; pair_i.DEDeg = ijEntry.Star2.DEDeg; pair_i.Star = ijEntry.Star2; pair_j.RADeg = ijEntry.Star1.RADeg; pair_j.DEDeg = ijEntry.Star1.DEDeg; pair_j.Star = ijEntry.Star1; #if ASTROMETRY_DEBUG Trace.Assert(ijEntry.Star2.StarNo == iStarNo); Trace.Assert(ijEntry.Star1.StarNo == jStarNo); #endif RegisterRecognizedPair(feature_i, ijEntry.Star2, i); RegisterRecognizedPair(feature_j, ijEntry.Star1, j); } if (ikEntry.Star1.StarNo == kStarNo) { pair_k.RADeg = ikEntry.Star1.RADeg; pair_k.DEDeg = ikEntry.Star1.DEDeg; pair_k.Star = ikEntry.Star1; #if ASTROMETRY_DEBUG Trace.Assert(ikEntry.Star1.StarNo == kStarNo); #endif RegisterRecognizedPair(feature_k, ikEntry.Star1, k); } else { pair_k.RADeg = ikEntry.Star2.RADeg; pair_k.DEDeg = ikEntry.Star2.DEDeg; pair_k.Star = ikEntry.Star2; #if ASTROMETRY_DEBUG Trace.Assert(ikEntry.Star2.StarNo == kStarNo); #endif RegisterRecognizedPair(feature_k, ikEntry.Star2, k); } if (m_AmbiguousMatches.Count > 0 && locatedStars - m_AmbiguousMatches.Count >= CorePyramidConfig.Default.MinPyramidAlignedStars) { // If we have sufficient number of stars and ambiguous stars (close doubles that satisfy more than one solution) // then remove all ambiguous stars before proceeding foreach (ImagePixel matchedPixel in m_AmbiguousMatches) { IStar matchedStar = m_MatchedPairs[matchedPixel]; int featureToRemove = -1; foreach (int featureId in m_MatchedFeatureIdToStarIdIndexes.Keys) { if (m_MatchedFeatureIdToStarIdIndexes[featureId] == matchedStar.StarNo) { featureToRemove = featureId; break; } } m_MatchedFeatureIdToStarIdIndexes.Remove(featureToRemove); m_MatchedPairs.Remove(matchedPixel); } } if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Debug.WriteLine(string.Format("Attempting DistanceBasedContext.LeastSquareFittedAstrometry ({0}={1}; {2}={3}; {4}={5})", i, iStarNo, j, jStarNo, k, kStarNo)); return SolveStarPairs( starMap, m_MatchedPairs, m_MatchedFeatureIdToStarIdIndexes, pair_i, pair_j, pair_k, fittedFocalLength, #if ASTROMETRY_DEBUG pyramidLog #else null #endif ); } else { #if PYRAMID_DEBUG || DEBUG foreach(ImagePixel pixel in m_MatchedPairs.Keys) { IStar star = m_MatchedPairs[pixel]; foreach(int featureId in m_MatchedFeatureIdToStarIdIndexes.Keys) { if (m_MatchedFeatureIdToStarIdIndexes[featureId] == star.StarNo) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) { #if DEBUG Debug #endif #if PYRAMID_DEBUG Trace #endif .WriteLine(string.Format("({0}, {1}) - StarNo: {2}; FeatureId: {3}", pixel.X, pixel.Y, star.StarNo, featureId)); } break; } } } #endif #if ASTROMETRY_DEBUG pyramidLog.FailBecauseOfTooFiewLocatedStars(locatedStars); AstrometricFitDebugger.RegisterFailedPyramid(pyramidLog); #endif } return null; }
internal IAstrometricFit IsSuccessfulMatch( IStarMap starMap, int i, int j, int k, DistanceEntry ijEntry, DistanceEntry ikEntry, DistanceEntry jkEntry, ulong iStarNo, ulong starNo2, ulong starNo3, double toleranceInArcSec) { return IsSuccessfulMatch( starMap, i, j, k, ijEntry, ikEntry, jkEntry, iStarNo, starNo2, starNo3, m_PlateConfig.EffectiveFocalLength, false, toleranceInArcSec); }
private ImagePixel GetCenterOfFeature(StarMapFeature feature, IStarMap starMap) { ImagePixel center = feature.GetCenter(); if (center == null) return ImagePixel.Unspecified; return starMap.GetCentroid(center.X, center.Y, (int)CoreAstrometrySettings.Default.SearchArea); }
internal FieldAlignmentResult DoFieldAlignment(IStarMap starMap, Dictionary<StarMapFeature, IStar> manualPairs) { m_ManualPairs = manualPairs; return DoFieldAlignment(starMap, (FitInfo)null, false); }
internal FieldAlignmentResult DoFieldAlignment(IStarMap starMap, double fittedFocalLength) { m_PlateConfig.EffectiveFocalLength = fittedFocalLength; return DoFieldAlignment(starMap, (FitInfo)null, false); }
internal bool LoopThroghFeatureTriangles(IStarMap starMap, double toleranceInArcSec, CheckTriangleWithRatiosCallback callback) { return LoopThroghFeatureTriangles(starMap, toleranceInArcSec, null, callback); }
internal FieldAlignmentResult DoFieldAlignment( IStarMap starMap, FitInfo previousFit, bool fitFocalLength) { #if ASTROMETRY_DEBUG Trace.Assert(m_CelestialPyramidStars != null, "m_CelestialPyramidStars hasn't been set! Initialize() not called or called twice?"); Trace.Assert(m_Settings.PyramidDistanceToleranceInPixels > 0); #endif double toleranceInArcSec = m_PlateConfig.GetDistanceInArcSec(m_Settings.PyramidDistanceToleranceInPixels); m_PreviousFit = previousFit; m_FeaturesDistanceCache.Clear(); m_MatchedPairs.Clear(); m_AmbiguousMatches.Clear(); m_MatchedFeatureIdToStarIdIndexes.Clear(); m_StarMap = starMap; if (m_DetermineAutoLimitMagnitude) { #if ASTROMETRY_DEBUG Trace.Assert(previousFit == null || previousFit.DetectedLimitingMagnitude != 0); #endif double detectedLimitingMagnitude = double.NaN; if (previousFit != null && !double.IsNaN(previousFit.DetectedLimitingMagnitude)) { detectedLimitingMagnitude = previousFit.DetectedLimitingMagnitude; } if (!(double.IsNaN(detectedLimitingMagnitude) && double.IsNaN(m_DetectedLimitingMagnitude)) && detectedLimitingMagnitude != m_DetectedLimitingMagnitude) { m_DetectedLimitingMagnitude = detectedLimitingMagnitude; if (double.IsNaN(m_DetectedLimitingMagnitude)) { m_CelestialPyramidStars = m_CelestialAllStars; if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(string.Format("Now using all {0} loaded stars as alignment stars", m_CelestialPyramidStars.Count)); } else { m_CelestialPyramidStars = m_CelestialAllStars .Where(s => s.Mag <= m_DetectedLimitingMagnitude) .ToList(); if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceVerbose()) Trace.WriteLine(string.Format("Limitting alignment stars to {0} start up to mag {1:0.0}", m_CelestialPyramidStars.Count, m_DetectedLimitingMagnitude)); } InitializePyramidMatching(); } } m_AbortSearch = false; try { m_OperationNotifier.SendNotification(new OperationNotifications(NotificationType.SearchStarted, null)); if (CorePyramidConfig.Default.ForceAlwaysUsePyramidWithRatios || fitFocalLength) { if (CoreAstrometrySettings.Default.UseQuickAlign) { if (LoopThroghFeatureTriangles(starMap, toleranceInArcSec, CheckTrianglesWithRatiosByMagnitude)) { return new FieldAlignmentResult() { Solution = m_Solution, ImprovedSolution = m_ImprovedSolution, Solver = m_SolutionSolver, MatchedTriangle = m_MatchedTriangle }; } } else { if (LoopThroghFeatureTriangles(starMap, toleranceInArcSec, CheckTriangleWithRatios)) { return new FieldAlignmentResult() { Solution = m_Solution, ImprovedSolution = m_ImprovedSolution, Solver = m_SolutionSolver, MatchedTriangle = m_MatchedTriangle }; } } } else { if (CoreAstrometrySettings.Default.UseQuickAlign) { if (LoopThroghFeatureTriangles(starMap, toleranceInArcSec, CheckTriangleByMagnitude)) { return new FieldAlignmentResult() { Solution = m_Solution, ImprovedSolution = m_ImprovedSolution, Solver = m_SolutionSolver, MatchedTriangle = m_MatchedTriangle }; } } else { if (LoopThroghFeatureTriangles(starMap, toleranceInArcSec, CheckTriangle)) { return new FieldAlignmentResult() { Solution = m_Solution, ImprovedSolution = m_ImprovedSolution, Solver = m_SolutionSolver, MatchedTriangle = m_MatchedTriangle }; } } } return null; } finally { m_OperationNotifier.SendNotification(new OperationNotifications(NotificationType.SearchFinished, null)); } }
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 void InitNewMatch(IStarMap imageFeatures, PyramidMatchType matchType, Dictionary<PSFFit, IStar> manualStars) { m_StarMap = imageFeatures; if (manualStars != null) SetManuallyIdentifiedHints(manualStars); matchType = PyramidMatchType.PlateSolve; m_IsCalibration = matchType == PyramidMatchType.ConfigCalibration; Context.Initialize(m_CelestialStars, m_PyramidMinMag, m_PyramidMaxMag, m_DetermineAutoLimitMagnitude, m_ManualStarMatch); #if ASTROMETRY_DEBUG AstrometricFitDebugger.Init(m_FitSettings, m_PyramidMinMag, m_PyramidMaxMag, m_AstrometryMinMag, m_AstrometryMaxMag); #endif }
private bool? CheckCombination(int i, int j, int k, IStarMap starMap, double toleranceInArcSec, CheckTriangleCallback callback, CheckTriangleWithRatiosCallback callbackWithRatios, Stopwatch timeTaken, ref int counter, ref bool delayWarningSent, int maxCombinationsBeforeFail, int total, int n) { if (i == j || i == k || j == k) return null; counter++; if (DebugResolvedStars != null) { if (!DebugResolvedStars.ContainsKey(i)) return null; if (!DebugResolvedStars.ContainsKey(j)) return null; if (!DebugResolvedStars.ContainsKey(k)) return null; if (DebugExcludeStars != null) { if (DebugExcludeStars.ContainsKey(i)) return null; if (DebugExcludeStars.ContainsKey(j)) return null; if (DebugExcludeStars.ContainsKey(k)) return null; } } #if PYRAMID_DEBUG Trace.WriteLine(string.Format("Trying triangle {0}-{1}-{2}", i, j, k)); #endif if (counter >= maxCombinationsBeforeFail) return false; if (m_AbortSearch) return false; if (counter % 5000 == 0) m_OperationNotifier.SendNotification(new OperationNotifications(NotificationType.SearchProgressed, null)); if (!delayWarningSent && timeTaken.ElapsedMilliseconds > m_Settings.PyramidTimeoutInSeconds * 100 && timeTaken.ElapsedMilliseconds > 5000) { m_OperationNotifier.SendNotification(new OperationNotifications(NotificationType.SearchTakingLonger, timeTaken.ElapsedMilliseconds)); delayWarningSent = true; } if (timeTaken.ElapsedMilliseconds > m_Settings.PyramidTimeoutInSeconds * 1000) { if (TangraConfig.Settings.TraceLevels.PlateSolving.TraceError()) Trace.WriteLine(string.Format("Timeout of {0}sec reached at {1}-{2}-{3}", m_Settings.PyramidTimeoutInSeconds, i, j, k)); return false; } if (callbackWithRatios != null) { if (CheckTriangleWithRatios(starMap, callbackWithRatios, i, j, k, toleranceInArcSec)) { if (ImproveAndRetestSolution(i, j, k)) { m_MatchedTriangle = string.Format("{0}-{1}-{2}:{5}:[{3}/{4}]", i, j, k, counter, total, n); return true; } } } else { if (CheckTriangle(starMap, callback, i, j, k, toleranceInArcSec)) { if (ImproveAndRetestSolution(i, j, k)) { m_MatchedTriangle = string.Format("{0}-{1}-{2}:{5}:[{3}/{4}]", i, j, k, counter, total, n); return true; } } } return null; }
public void NextFrame(int frameNo, IAstroImage astroImage, IStarMap starMap, LeastSquareFittedAstrometry astrometricFit) { IsTrackedSuccessfully = false; PSFFit psfFit = null; if (m_RepeatedIntergationPositions * 4 < m_PastFrameNos.Count) { var expectedPos = GetExpectedPosition(frameNo); if (expectedPos != null) AstrometryContext.Current.StarMap.GetPSFFit(expectedPos.X, expectedPos.Y, PSFFittingMethod.NonLinearFit, out psfFit); } if (psfFit == null) { var brightestFeature = starMap.GetFeatureInRadius((int)TrackedObject.LastKnownX, (int)TrackedObject.LastKnownY, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius); if (brightestFeature != null) { var center = brightestFeature.GetCenter(); var referenceStarFeatures = astrometricFit.FitInfo.AllStarPairs.Where(x => x.FitInfo.UsedInSolution).ToList(); var refStar = referenceStarFeatures.FirstOrDefault(s => Math.Sqrt((s.x - center.X) * (s.x - center.X) + (s.y - center.Y) * (s.y - center.Y)) < 2); if (refStar == null) // The brightest feature is not a reference star, so we assume it is our object AstrometryContext.Current.StarMap.GetPSFFit(center.X, center.Y, PSFFittingMethod.NonLinearFit, out psfFit); } } if (psfFit == null) { ImagePixel centroid = AstrometryContext.Current.StarMap.GetCentroid( (int)TrackedObject.LastKnownX, (int)TrackedObject.LastKnownY, CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius); if (centroid != null) AstrometryContext.Current.StarMap.GetPSFFit(centroid.X, centroid.Y, PSFFittingMethod.NonLinearFit, out psfFit); } if (psfFit != null) { double ra, de; astrometricFit.GetRADEFromImageCoords(psfFit.XCenter, psfFit.YCenter, out ra, out de); double maxPosDiffArcSec = astrometricFit.GetDistanceInArcSec(astrometricFit.Image.CenterXImage, astrometricFit.Image.CenterYImage, astrometricFit.Image.CenterXImage + CoreAstrometrySettings.Default.PreMeasureSearchCentroidRadius, astrometricFit.Image.CenterYImage); if (!double.IsNaN(TrackedObject.RAHours)) { double posDif = 3600 * AngleUtility.Elongation(15 * TrackedObject.RAHours, TrackedObject.DEDeg, ra, de); if (posDif > maxPosDiffArcSec) { // NOTE: Not a valid measurement Trace.WriteLine(string.Format("The target position is too far from the last measured position", posDif)); return; } } TrackedObject.RAHours = ra / 15.0; TrackedObject.DEDeg = de; TrackedObject.LastKnownX = psfFit.XCenter; TrackedObject.LastKnownY = psfFit.YCenter; TrackedObject.PSFFit = psfFit; IsTrackedSuccessfully = true; } if (psfFit != null && psfFit.XCenter > 0 && psfFit.YCenter > 0) { m_PastFramePosX.Add(psfFit.XCenter); m_PastFramePosY.Add(psfFit.YCenter); m_PastFrameNos.Add(frameNo); } }
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; }