From 66e970fb32119b2ae5d1127ac1b002c1e47f516c Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Sat, 26 Nov 2022 16:21:47 +0000 Subject: [PATCH 01/18] Eqmod Alignment integration WIP commit. --- EQMODAlignment/DataTypes/AxisPosition.cs | 184 ++ EQMODAlignment/DataTypes/EncoderPosition.cs | 182 ++ EQMODAlignment/DataTypes/EqascomDataTypes.cs | 130 ++ EQMODAlignment/EqascomAlignment.csproj | 4 + EQMODAlignment/EqmodNStarAlignment.csproj | 27 + EQMODAlignment/Model/AlignmentModel.cs | 414 ++++ .../Model/AlignmentModel_EqModVector.cs | 1715 +++++++++++++++++ .../Model/AlignmentModel_EqmodAlignment.cs | 75 + EQMODAlignment/Model/AlignmentModel_Math.cs | 1014 ++++++++++ EQMODAlignment/Model/AlignmentPoint.cs | 83 + EQMODAlignment/Utilities/AstroConvert.cs | 208 ++ EQMODAlignment/Utilities/EnumTypeConverter.cs | 57 + EQMODAlignment/Utilities/Range.cs | 121 ++ EQMODAlignment/Utilities/SiderealTime.cs | 22 + .../EqmodNStarAlignment.Tests.csproj | 69 + .../Properties/AssemblyInfo.cs | 20 + EqmodNStarAlignment.Tests/UnitTest1.cs | 14 + EqmodNStarAlignment.Tests/packages.config | 5 + GS.Ascom.SkyTelescope/CommandStrings.cs | 8 +- GS.Ascom.SkyTelescope/Telescope.cs | 42 +- GS.Server/Alignment/AlignmentV.xaml | 12 +- GS.Server/Alignment/AlignmentVM.cs | 3 +- GS.Server/Focuser/FocuserVM.cs | 2 +- GS.Server/GS.Server.csproj | 2 +- GS.Server/SkyTelescope/Axes.cs | 4 +- GS.Server/SkyTelescope/Enums.cs | 3 +- GS.Server/SkyTelescope/SkyServer.cs | 242 +-- GS.Server/SkyTelescope/SkyTelescopeVM.cs | 4 +- GS.Server/Snap/SnapVM.cs | 4 +- GS.Shared/Model3D.cs | 3 +- GS.SkyWatcher/Commands.cs | 2 +- GSSolution.sln | 40 + 32 files changed, 4563 insertions(+), 152 deletions(-) create mode 100644 EQMODAlignment/DataTypes/AxisPosition.cs create mode 100644 EQMODAlignment/DataTypes/EncoderPosition.cs create mode 100644 EQMODAlignment/DataTypes/EqascomDataTypes.cs create mode 100644 EQMODAlignment/EqascomAlignment.csproj create mode 100644 EQMODAlignment/EqmodNStarAlignment.csproj create mode 100644 EQMODAlignment/Model/AlignmentModel.cs create mode 100644 EQMODAlignment/Model/AlignmentModel_EqModVector.cs create mode 100644 EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs create mode 100644 EQMODAlignment/Model/AlignmentModel_Math.cs create mode 100644 EQMODAlignment/Model/AlignmentPoint.cs create mode 100644 EQMODAlignment/Utilities/AstroConvert.cs create mode 100644 EQMODAlignment/Utilities/EnumTypeConverter.cs create mode 100644 EQMODAlignment/Utilities/Range.cs create mode 100644 EQMODAlignment/Utilities/SiderealTime.cs create mode 100644 EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj create mode 100644 EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs create mode 100644 EqmodNStarAlignment.Tests/UnitTest1.cs create mode 100644 EqmodNStarAlignment.Tests/packages.config diff --git a/EQMODAlignment/DataTypes/AxisPosition.cs b/EQMODAlignment/DataTypes/AxisPosition.cs new file mode 100644 index 00000000..ca9cf786 --- /dev/null +++ b/EQMODAlignment/DataTypes/AxisPosition.cs @@ -0,0 +1,184 @@ +/* +BSD 2-Clause License + +Copyright (c) 2019, LunaticSoftware.org, Email: phil@lunaticsoftware.org +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using Newtonsoft.Json; + +namespace EqmodNStarAlignment.DataTypes +{ + /// + /// A structure to represent telescope mount axis positions + /// + public struct AxisPosition + { + private double _ra; + private double _dec; + + [JsonProperty] + public double RA + { + get => _ra; + set => _ra = value; + } + + [JsonProperty] + public double Dec + { + get => _dec; + set => _dec = value; + } + + + public AxisPosition(double[] axes) : this(axes[0], axes[1]) + { } + + /// + /// Create a new axis position + /// + /// RA axis encoder value + /// Dec axis encoder value + public AxisPosition(double ra, double dec) + { + _ra = ra; + _dec = dec; + } + + + public AxisPosition(string axisPositions) + { + var positions = axisPositions.Split('|'); + try + { + _ra = double.Parse(positions[0]); + _dec = double.Parse(positions[1]); + } + catch + { + throw new ArgumentException("Badly formed axis position string"); + } + } + + + public static implicit operator double[](AxisPosition axes) + { + return new[] { axes[0], axes[1] }; + } + + public static implicit operator AxisPosition(double[] axes) + { + return new AxisPosition(axes); + } + + /// + /// The axis position in degrees + /// + /// + /// + public double this[int index] + { + get + { + if (index < 0 || index > 2) + { + throw new ArgumentOutOfRangeException(); + } + return (index == 0 ? _ra : _dec); + } + set + { + if (index < 0 || index > 2) + { + throw new ArgumentOutOfRangeException(); + } + if (index == 0) + { + _ra = value; + } + else + { + _dec = value; + } + } + } + + /// + /// Compares the two specified sets of Axis positions. + /// + public static bool operator ==(AxisPosition pos1, AxisPosition pos2) + { + return (pos1.RA == pos2.RA && pos1.Dec == pos2.Dec); + } + + public static bool operator !=(AxisPosition pos1, AxisPosition pos2) + { + return !(pos1 == pos2); + } + + public static AxisPosition operator -(AxisPosition pos1, AxisPosition pos2) + { + return new AxisPosition(pos1.RA - pos2.RA, pos1.Dec - pos2.Dec); + } + + public static AxisPosition operator +(AxisPosition pos1, AxisPosition pos2) + { + return new AxisPosition(pos1.RA + pos2.RA, pos1.Dec + pos2.Dec); + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hash = 17; + // Suitable nullity checks etc, of course :) + hash = hash * 23 + _ra.GetHashCode(); + hash = hash * 23 + _dec.GetHashCode(); + return hash; + } + } + + public override bool Equals(object obj) + { + return (obj is AxisPosition position + && this == position); + } + + + public bool Equals(AxisPosition obj, double toleranceDegrees) + { + var deltaRa = Math.Abs(obj.RA - RA); + deltaRa = (deltaRa + 180) % 360 - 180; + var deltaDec = Math.Abs(obj.Dec - Dec); + deltaDec = (deltaDec + 180) % 360 - 180; + return (deltaRa <= toleranceDegrees + && deltaDec <= toleranceDegrees); + } + + + + } +} diff --git a/EQMODAlignment/DataTypes/EncoderPosition.cs b/EQMODAlignment/DataTypes/EncoderPosition.cs new file mode 100644 index 00000000..7c3ab22a --- /dev/null +++ b/EQMODAlignment/DataTypes/EncoderPosition.cs @@ -0,0 +1,182 @@ +/* +BSD 2-Clause License + +Copyright (c) 2019, LunaticSoftware.org, Email: phil@lunaticsoftware.org +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +* Redistributions of source code must retain the above copyright notice, this + list of conditions and the following disclaimer. + +* Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE +FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR +SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER +CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, +OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +using System; +using Newtonsoft.Json; + +namespace EqmodNStarAlignment.DataTypes +{ + /// + /// A structure to represent telescope mount axis positions + /// + public struct EncoderPosition + { + private long _ra; + private long _dec; + + [JsonProperty] + public long RA + { + get => _ra; + set => _ra = value; + } + + [JsonProperty] + public long Dec + { + get => _dec; + set => _dec = value; + } + + + public EncoderPosition(long[] axes) : this(axes[0], axes[1]) + { } + + /// + /// Create a new axis position + /// + /// RA axis encoder value + /// Dec axis encoder value + public EncoderPosition(long ra, long dec) + { + _ra = ra; + _dec = dec; + } + + + public EncoderPosition(string axisPositions) + { + var positions = axisPositions.Split('|'); + try + { + _ra = long.Parse(positions[0]); + _dec = long.Parse(positions[1]); + } + catch + { + throw new ArgumentException("Badly formed axis position string"); + } + } + + + public static implicit operator long[](EncoderPosition axes) + { + return new[] { axes[0], axes[1] }; + } + + public static implicit operator EncoderPosition(long[] axes) + { + return new EncoderPosition(axes); + } + + /// + /// The axis position in degrees + /// + /// + /// + public long this[long index] + { + get + { + if (index < 0 || index > 2) + { + throw new ArgumentOutOfRangeException(); + } + return (index == 0 ? _ra : _dec); + } + set + { + if (index < 0 || index > 2) + { + throw new ArgumentOutOfRangeException(); + } + if (index == 0) + { + _ra = value; + } + else + { + _dec = value; + } + } + } + + /// + /// Compares the two specified sets of Axis positions. + /// + public static bool operator ==(EncoderPosition pos1, EncoderPosition pos2) + { + return (pos1.RA == pos2.RA && pos1.Dec == pos2.Dec); + } + + public static bool operator !=(EncoderPosition pos1, EncoderPosition pos2) + { + return !(pos1 == pos2); + } + + public static EncoderPosition operator -(EncoderPosition pos1, EncoderPosition pos2) + { + return new EncoderPosition(pos1.RA - pos2.RA, pos1.Dec - pos2.Dec); + } + + public static EncoderPosition operator +(EncoderPosition pos1, EncoderPosition pos2) + { + return new EncoderPosition(pos1.RA + pos2.RA, pos1.Dec + pos2.Dec); + } + + public override int GetHashCode() + { + unchecked // Overflow is fine, just wrap + { + var hash = 17; + // Suitable nullity checks etc, of course :) + hash = hash * 23 + _ra.GetHashCode(); + hash = hash * 23 + _dec.GetHashCode(); + return hash; + } + } + + public override bool Equals(object obj) + { + return (obj is EncoderPosition position + && this == position); + } + + + public bool Equals(EncoderPosition obj, double toleranceDegrees) + { + var deltaRa = Math.Abs(obj.RA - RA); + var deltaDec = Math.Abs(obj.Dec - Dec); + return (deltaRa <= toleranceDegrees + && deltaDec <= toleranceDegrees); + } + + + + } +} diff --git a/EQMODAlignment/DataTypes/EqascomDataTypes.cs b/EQMODAlignment/DataTypes/EqascomDataTypes.cs new file mode 100644 index 00000000..3dca2d0b --- /dev/null +++ b/EQMODAlignment/DataTypes/EqascomDataTypes.cs @@ -0,0 +1,130 @@ +/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +// based on original work +// Copyright © 2006 Raymund Sarmiento +// +// Permission is hereby granted to use this Software for any purpose +// including combining with commercial products, creating derivative +// works, and redistribution of source or binary code, without +// limitation or consideration. Any redistributed copies of this +// Software must include the above Copyright Notice. +// +// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO +// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS +// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +// +// DISCLAIMER: + +// You can use the information on this site COMPLETELY AT YOUR OWN RISK. +// The modification steps and other information on this site is provided +// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, +// implied or otherwise, including without limitation any warranty of +// merchantability or fitness for any particular or intended purpose. +// In no event the author will be liable for any direct, indirect, +// punitive, special, incidental or consequential damages or loss of any +// kind whether or not the author has been advised of the possibility +// of such loss. +//--------------------------------------------------------------------- + +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.DataTypes +{ + public struct Coord + { + public double x; //x = X Coordinate + public double y; //y = Y Coordinate + public double z; + } + + //[Serializable] + //public struct Tdatholder + //{ + // public double dat; + // public short idx; + // public Coord cc; // cartesian coordinate + // public static Tdatholder CreateInstance() + // { + // Tdatholder result = new Tdatholder(); + // return result; + // } + //} + + //[Serializable] + //public struct THolder + //{ + // public double a; + // public double b; + // public double c; + //} + + + public struct Matrix + { + public double[,] Element; //2D array of elements + public static Matrix CreateInstance() + { + Matrix result = new Matrix(); + result.Element = new double[3, 3]; + return result; + } + } + + //[Serializable] + //public struct Matrix2 + //{ + // public double[,] Element; //2D array of elements + // public static Matrix2 CreateInstance() + // { + // Matrix2 result = new Matrix2(); + // result.Element = new double[4, 4]; + // return result; + // } + //} + + //[Serializable] + //public struct Coordt + //{ + // public double x; //x = X Coordinate + // public double y; //y = Y Coordinate + // public double z; + // public short f; + //} + + public struct CartesCoord + { + public double x; //x = X Coordinate + public double y; //y = Y Coordinate + public double r; // Radius Sign + public double ra; // Radius Alpha + } + + public struct SphericalCoord + { + public double x; //x = X Coordinate + public double y; //y = Y Coordinate + public double r; //r = RA Range Flag + } + + + //[Serializable] + //public struct TriangleCoord + //{ + // public double i; // Offset 1 + // public double j; // Offset 2 + // public double k; // offset 3 + + //} +} diff --git a/EQMODAlignment/EqascomAlignment.csproj b/EQMODAlignment/EqascomAlignment.csproj new file mode 100644 index 00000000..88a55094 --- /dev/null +++ b/EQMODAlignment/EqascomAlignment.csproj @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/EQMODAlignment/EqmodNStarAlignment.csproj b/EQMODAlignment/EqmodNStarAlignment.csproj new file mode 100644 index 00000000..cd7fa4a7 --- /dev/null +++ b/EQMODAlignment/EqmodNStarAlignment.csproj @@ -0,0 +1,27 @@ + + + + netstandard2.0 + + + + ..\Builds\Debug\ + x86 + + false + + + + + + + + + + + + + + + + diff --git a/EQMODAlignment/Model/AlignmentModel.cs b/EQMODAlignment/Model/AlignmentModel.cs new file mode 100644 index 00000000..29a83153 --- /dev/null +++ b/EQMODAlignment/Model/AlignmentModel.cs @@ -0,0 +1,414 @@ +using EqmodNStarAlignment.Utilities; +using EqmodNStarAlignment.DataTypes; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; + +namespace EqmodNStarAlignment.Model +{ + public enum NotificationType + { + Information, + Data, + Warning, + Error + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum PierSideEnum + { + [Description("Unknown")] + Unknown = -1, + [Description("East")] + EastLookingWest, + [Description("West")] + WestLookingEast, + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum ActivePointsEnum + { + [Description("All")] + All, + [Description("Pierside Only")] + PierSide, + [Description("Local Quadrant")] + LocalQuadrant + } + + public enum HemisphereEnum + { + Northern, + Southern + } + + public class NotificationEventArgs : EventArgs + { + public NotificationType NotificationType { get; set; } + public string Method { get; set; } + + public int Thread { get; set; } + public string Message { get; set; } + + + public NotificationEventArgs(NotificationType notificationType, string method, string message) + { + this.NotificationType = notificationType; + this.Method = method; + this.Message = message; + this.Thread = System.Threading.Thread.CurrentThread.ManagedThreadId; + } + } + + public partial class AlignmentModel + { + #region Events ... + + public event EventHandler Notification = delegate { }; + + private void RaiseNotification(NotificationType notificationType, string method, string message) + { + Volatile.Read(ref Notification).Invoke(this, new NotificationEventArgs(notificationType, method, message)); + } + + #endregion + + #region variables ... + private readonly List _exceptionMessages = new List(); + + private bool _threeStarEnabled = false; + #endregion + + #region Properties ... + public bool IsAlignmentOn { get; set; } + + private double _proximityLimit = 0.5; + /// + /// How close existing alignment points have to be to the new alignment point + /// before they are removed and replaced with the new one (degrees) + /// + public double ProximityLimit + { + get => _proximityLimit; + set + { + if (_proximityLimit == value) return; + _proximityLimit = value; + RefreshProximitySteps(); + } + } + + private void RefreshProximitySteps() + { + _proximityStepsRa = (long)this.ProximityLimit * (this.StepsPerRev.RA / 360); + _proximityStepsDec = (long)this.ProximityLimit * (this.StepsPerRev.Dec / 360); + } + + private long _proximityStepsRa = 12533; /// Approimately 0.5 degrees (if steps per rev = 9024000) + private long _proximityStepsDec = 12533; /// Approimately 0.5 degrees (if steps per rev = 9024000) + + private double _siteLongitude; + public double SiteLongitude + { + get => _siteLongitude; + set + { + if (_siteLongitude == value) return; + _siteLongitude = value; + SendToMatrix(); + } + } + + private double _siteLatitude; + public double SiteLatitude + { + get => _siteLatitude; + set + { + if (_siteLatitude == value) return; + _siteLatitude = value; + Hemisphere = (_siteLatitude >= 0 ? HemisphereEnum.Northern : HemisphereEnum.Southern); + SendToMatrix(); // Refresh the matrices as these are affected by the site latitude + } + } + + public HemisphereEnum Hemisphere { get; private set; } = HemisphereEnum.Northern; + + public double SiteElevation { get; set; } + + private bool _polarEnable; + public bool PolarEnable + { + get => _polarEnable; + set + { + if (_polarEnable == value) return; + _polarEnable = value; + SendToMatrix(); + } + } + + public bool CheckLocalPier { get; set; } + + public EncoderPosition HomeEncoder { get; private set; } + + public void SetHomePosition(long RAEncoder, long decEncoder) + { + // EQMod expects the RA Home position to have a step value of 0x800000 (0 hours) + // and the Dec Home position to be 0xA26C80 (90 degrees) + + // Set the home position to the internal zero position for RA and internal zero + 90 degrees for Dec + HomeEncoder = new EncoderPosition(_homeZeroPosition, _homeZeroPosition + this.StepsPerRev.Dec / 4); // Set the dec at 90 degrees. + + // Calculate the correction for mapping mount encoder positions to internal encoder positions + EncoderMappingOffset = new EncoderPosition(HomeEncoder.RA - RAEncoder, HomeEncoder.Dec - decEncoder); + // To convert: Mount = Internal - EncoderMappingOffset + // Internal = Mount + EncoderMappingOffset + + } + + public EncoderPosition StepsPerRev { get; private set; } + + public ActivePointsEnum ActivePoints { get; set; } + + public AlignmentPointCollection AlignmentPoints { get; } = new AlignmentPointCollection(); + + public DateTime? LastAccessDateTime { get; private set; } + + // String builder for building more detailed messages. + private readonly StringBuilder _stringBuilder = new StringBuilder(); + + private readonly object _accessLock = new object(); + + private readonly string _configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\Points.config"); + + private readonly string _timeStampFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\TimeStamp.config"); + + private const long _homeZeroPosition = 0x800000; // As per EQMOD + + public EncoderPosition EncoderMappingOffset { get; private set; } // Mapping from Mount encoder positions to internal encoder positions + + /// + /// RA/Dec encoder adjustments for when there is only one star/point logged. + /// + private EncoderPosition _oneStarAdjustment = new EncoderPosition(0, 0); + + #endregion + + #region Constructor ... + public AlignmentModel(double siteLatitude, double siteLongitude, double siteElevation, EncoderPosition stepsPerRev, bool clearPointsOnStartup = false) + { + SiteLatitude = siteLatitude; + SiteLongitude = siteLongitude; + SiteElevation = siteElevation; + StepsPerRev = stepsPerRev; + RefreshProximitySteps(); + + try + { + // Load the last access time property. + ReadLastAccessTime(); + // Re-load alignment points unless clear points on start up is specified + // In case of lost connections or restarts the points are only cleared if the last time the model was accessed is more than an hour ago. + if (!clearPointsOnStartup || (LastAccessDateTime != null && + (LastAccessDateTime.Value > DateTime.Now - new TimeSpan(1, 0, 0)))) + { + LoadAlignmentPoints(); + } + } + catch (Exception ex) + { + LogException(ex, true); + } + } + #endregion + + + #region Alignment point management ... + public bool SyncToRaDec(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) + { + try + { + lock (_accessLock) + { + + // AlignmentPoints.Add(new AlignmentPoint(encoder, origRaDec, target, syncTime)); + if (EQ_NPointAppend(new AlignmentPoint(encoder + this.EncoderMappingOffset, origRaDec, target + this.EncoderMappingOffset, syncTime))) + { + + } + //_currentChecksum = int.MinValue; // Reset checksum so that offsets are recalculated + + //OneStarAdjustment[0] = observedAxes[0] - mountAxes[0]; + //OneStarAdjustment[1] = observedAxes[1] - mountAxes[1]; + SaveAlignmentPoints(); + + return true; + } + } + catch (Exception ex) + { + LogException(ex, true); + } + return false; + } + + + public bool RemoveAlignmentPoint(AlignmentPoint pointToDelete) + { + try + { + bool result = AlignmentPoints.Remove(pointToDelete); + if (result) + { + SaveAlignmentPoints(); + } + + return result; + } + catch (Exception ex) + { + LogException(ex, true); + return false; + } + } + + + public void SaveAlignmentPoints(string filename) + { + File.WriteAllText(filename, JsonConvert.SerializeObject(AlignmentPoints, Formatting.Indented)); + } + + private void SaveAlignmentPoints() + { + var dir = Path.GetDirectoryName(_configFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + SaveAlignmentPoints(_configFile); + ReportAlignmentPoints(); + } + + + public void LoadAlignmentPoints(string filename) + { + AlignmentPoints.Clear(); + using (var file = File.OpenText(filename)) + { + var serializer = new JsonSerializer(); + try + { + var loaded = + (AlignmentPointCollection)serializer.Deserialize(file, typeof(AlignmentPointCollection)); + if (loaded != null) + { + foreach (var alignmentPoint in loaded) + { + AlignmentPoints.Add(alignmentPoint); + } + SendToMatrix(); // Updates the cartesean values. + } + } + catch (Exception ex) + { + LogException(ex); + } + } + + } + + private void LoadAlignmentPoints() + { + var dir = Path.GetDirectoryName(_configFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + if (File.Exists(_configFile)) + { + LoadAlignmentPoints(_configFile); + } + ReportAlignmentPoints(); + } + + public void ClearAlignmentPoints() + { + try + { + AlignmentPoints.Clear(); + SaveAlignmentPoints(); + } + catch (Exception ex) + { + LogException(ex, true); + } + } + + #endregion + + + #region Access time related ... + private void WriteLastAccessTime() + { + LastAccessDateTime = DateTime.Now; + var dir = Path.GetDirectoryName(_timeStampFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + File.WriteAllText(_timeStampFile, JsonConvert.SerializeObject(LastAccessDateTime, Formatting.Indented)); + } + + private void ReadLastAccessTime() + { + var dir = Path.GetDirectoryName(_timeStampFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + if (File.Exists(_timeStampFile)) + { + using (var file = File.OpenText(_timeStampFile)) + { + var serializer = new JsonSerializer(); + DateTime? loaded = (DateTime?)serializer.Deserialize(file, typeof(DateTime?)); + LastAccessDateTime = loaded; + } + } + } + #endregion + + #region Helper methods ... + private void ReportAlignmentPoints() + { + _stringBuilder.Clear(); + _stringBuilder.AppendLine("=============== Alignment points ==============="); + _stringBuilder.AppendLine("ID \tEncoder Ra/Dec \tOrig Ra/Dec \tTarget RaDec \tObserved time"); + foreach (var pt in AlignmentPoints) + { + _stringBuilder.AppendLine( + $"{pt.Id:D3}\t{pt.Encoder.RA}/{pt.Encoder.Dec}\t{pt.OrigRaDec.RA}/{pt.OrigRaDec.Dec}\t{pt.Target.RA}/{pt.Target.Dec}\t{pt.AlignTime}"); + } + RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod()?.Name, _stringBuilder.ToString()); + _stringBuilder.Clear(); + } + + private void LogException(Exception ex, bool allowDuplicates = false) + { + if (allowDuplicates || !_exceptionMessages.Contains(ex.Message)) + { + _exceptionMessages.Add(ex.Message); + string message = $"{ex.Message}|{ex.StackTrace}"; + RaiseNotification(NotificationType.Error, MethodBase.GetCurrentMethod()?.Name, message); + } + } + + #endregion + } +} diff --git a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs new file mode 100644 index 00000000..e154cee0 --- /dev/null +++ b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs @@ -0,0 +1,1715 @@ +/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +//--------------------------------------------------------------------- +// based on original work +// Copyright � 2006 Raymund Sarmiento +// +// Permission is hereby granted to use this Software for any purpose +// including combining with commercial products, creating derivative +// works, and redistribution of source or binary code, without +// limitation or consideration. Any redistributed copies of this +// Software must include the above Copyright Notice. +// +// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO +// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS +// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//--------------------------------------------------------------------- +// +// EQMODVECTOR.BAS - Matrix Transformation Routines for 3-Star Alignment +// (Renamed EQTakiAffine.cs) +// Written: 10-Dec-06 Raymund Sarmiento +// +// Edits: +// +// When Who What +// --------- --- -------------------------------------------------- +// 10-Dec-06 rcs Initial edit for EQ Mount 3-Star Matrix Transformation +// 14-Dec-06 rcs Added Taki Method on top of Affine Mapping Method for Comparison +// Taki Routines based on John Archbold's Excel computation +// 08-Apr-07 rcs N-star implementation +// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# +//--------------------------------------------------------------------- +// +// + +// DISCLAIMER: + +// You can use the information on this site COMPLETELY AT YOUR OWN RISK. +// The modification steps and other information on this site is provided +// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, +// implied or otherwise, including without limitation any warranty of +// merchantability or fitness for any particular or intended purpose. +// In no event the author will be liable for any direct, indirect, +// punitive, special, incidental or consequential damages or loss of any +// kind whether or not the author has been advised of the possibility +// of such loss. + +// WARNING: + +// Circuit modifications implemented on your setup could invalidate +// any warranty that you may have with your product. Use this +// information at your own risk. The modifications involve direct +// access to the stepper motor controls of your mount. Any "mis-control" +// or "mis-command" / "invalid parameter" or "garbage" data sent to the +// mount could accidentally activate the stepper motors and allow it to +// rotate "freely" damaging any equipment connected to your mount. +// It is also possible that any garbage or invalid data sent to the mount +// could cause its firmware to generate mis-steps pulse sequences to the +// motors causing it to overheat. Make sure that you perform the +// modifications and testing while there is no physical "load" or +// dangling wires on your mount. Be sure to disconnect the power once +// this event happens or if you notice any unusual sound coming from +// the motor assembly. +// + +using EqmodNStarAlignment.DataTypes; +using EqmodNStarAlignment.Utilities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.Model +{ + partial class AlignmentModel + { + + + + + //Define Affine Matrix + + public static Matrix EQMP = Matrix.CreateInstance(); + public static Matrix EQMQ = Matrix.CreateInstance(); + + public static Matrix EQMI = Matrix.CreateInstance(); + public static Matrix EQMM = Matrix.CreateInstance(); + public static Coord EQCO = new Coord(); + + + //Define Taki Matrix + + public static Matrix EQLMN1 = Matrix.CreateInstance(); + public static Matrix EQLMN2 = Matrix.CreateInstance(); + + public static Matrix EQMI_T = Matrix.CreateInstance(); + public static Matrix EQMT = Matrix.CreateInstance(); + public static Coord EQCT = new Coord(); + + + + //Function to put coordinate values into a LMN/lmn matrix array + + private Matrix GETLMN(Coord p1, Coord p2, Coord p3) + { + + Matrix temp = Matrix.CreateInstance(); + Matrix UnitVect = Matrix.CreateInstance(); + + + temp.Element[0, 0] = p2.x - p1.x; + temp.Element[1, 0] = p3.x - p1.x; + + temp.Element[0, 1] = p2.y - p1.y; + temp.Element[1, 1] = p3.y - p1.y; + + temp.Element[0, 2] = p2.z - p1.z; + temp.Element[1, 2] = p3.z - p1.z; + + + + + UnitVect.Element[0, 0] = (temp.Element[0, 1] * temp.Element[1, 2]) - (temp.Element[0, 2] * temp.Element[1, 1]); + UnitVect.Element[0, 1] = (temp.Element[0, 2] * temp.Element[1, 0]) - (temp.Element[0, 0] * temp.Element[1, 2]); + UnitVect.Element[0, 2] = (temp.Element[0, 0] * temp.Element[1, 1]) - (temp.Element[0, 1] * temp.Element[1, 0]); + UnitVect.Element[1, 0] = Math.Pow(UnitVect.Element[0, 0], 2) + Math.Pow(UnitVect.Element[0, 1], 2) + Math.Pow(UnitVect.Element[0, 2], 2); + UnitVect.Element[1, 1] = Math.Sqrt(UnitVect.Element[1, 0]); + if (UnitVect.Element[1, 1] != 0) + { + UnitVect.Element[1, 2] = 1 / UnitVect.Element[1, 1]; + } + + + + temp.Element[2, 0] = UnitVect.Element[1, 2] * UnitVect.Element[0, 0]; + temp.Element[2, 1] = UnitVect.Element[1, 2] * UnitVect.Element[0, 1]; + temp.Element[2, 2] = UnitVect.Element[1, 2] * UnitVect.Element[0, 2]; + + + + + return temp; + + } + + //Function to put coordinate values into a P/Q Affine matrix array + + private Matrix GETPQ(Coord p1, Coord p2, Coord p3) + { + + Matrix temp = Matrix.CreateInstance(); + + temp.Element[0, 0] = p2.x - p1.x; + temp.Element[1, 0] = p3.x - p1.x; + temp.Element[0, 1] = p2.y - p1.y; + temp.Element[1, 1] = p3.y - p1.y; + + return temp; + + } + + // Subroutine to draw the Transformation Matrix (Taki Method) + + private int EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + { + + + double Det = 0; + + + // Get the LMN Matrix + + EQLMN1 = GETLMN(a1, a2, a3); + + // Get the lmn Matrix + + EQLMN2 = GETLMN(m1, m2, m3); + + + + + // Get the Determinant + + Det = EQLMN1.Element[0, 0] * ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])); + Det -= (EQLMN1.Element[0, 1] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 2]))); + Det += (EQLMN1.Element[0, 2] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1]))); + + + // Compute for the Matrix Inverse of EQLMN1 + + if (Det == 0) + { + throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); + } + else + { + + EQMI_T.Element[0, 0] = ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])) / Det; + EQMI_T.Element[0, 1] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[0, 1] * EQLMN1.Element[2, 2])) / Det; + EQMI_T.Element[0, 2] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[1, 2]) - (EQLMN1.Element[1, 1] * EQLMN1.Element[0, 2])) / Det; + EQMI_T.Element[1, 0] = ((EQLMN1.Element[1, 2] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 2] * EQLMN1.Element[1, 0])) / Det; + EQMI_T.Element[1, 1] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[0, 2])) / Det; + EQMI_T.Element[1, 2] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[1, 0]) - (EQLMN1.Element[1, 2] * EQLMN1.Element[0, 0])) / Det; + EQMI_T.Element[2, 0] = ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1])) / Det; + EQMI_T.Element[2, 1] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[0, 0])) / Det; + EQMI_T.Element[2, 2] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[1, 1]) - (EQLMN1.Element[1, 0] * EQLMN1.Element[0, 1])) / Det; + } + + + + // Get the M Matrix by Multiplying EQMI and EQLMN2 + // EQMI_T - Matrix A + // EQLMN2 - Matrix B + + + EQMT.Element[0, 0] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[0, 1] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[0, 2] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 2]); + + EQMT.Element[1, 0] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[1, 1] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[1, 2] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 2]); + + EQMT.Element[2, 0] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[2, 1] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[2, 2] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 2]); + + + // Get the Coordinate Offset Vector and store it at EQCO Matrix + + EQCT.x = m1.x - ((a1.x * EQMT.Element[0, 0]) + (a1.y * EQMT.Element[1, 0]) + (a1.z * EQMT.Element[2, 0])); + EQCT.y = m1.y - ((a1.x * EQMT.Element[0, 1]) + (a1.y * EQMT.Element[1, 1]) + (a1.z * EQMT.Element[2, 1])); + EQCT.z = m1.z - ((a1.x * EQMT.Element[0, 2]) + (a1.y * EQMT.Element[1, 2]) + (a1.z * EQMT.Element[2, 2])); + + + if ((x + Y) == 0) + { + return 0; + } + else + { + return EQ_CheckPoint_in_Triangle(x, Y, a1.x, a1.y, a2.x, a2.y, a3.x, a3.y); + } + + + } + + + ////Function to transform the Coordinates (Taki Method) using the MT Matrix and Offset Vector + + //private Coord EQ_Transform_Taki(Coord ob) + //{ + + // // CoordTransform = Offset + CoordObject * Matrix MT + + // Coord result = new Coord(); + // result.x = EQCT.x + ((ob.x * EQMT.Element[0, 0]) + (ob.y * EQMT.Element[1, 0]) + (ob.z * EQMT.Element[2, 0])); + // result.y = EQCT.y + ((ob.x * EQMT.Element[0, 1]) + (ob.y * EQMT.Element[1, 1]) + (ob.z * EQMT.Element[2, 1])); + // result.z = EQCT.z + ((ob.x * EQMT.Element[0, 2]) + (ob.y * EQMT.Element[1, 2]) + (ob.z * EQMT.Element[2, 2])); + + + // return result; + //} + + // Subroutine to draw the Transformation Matrix (Affine Mapping Method) + + private int EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + { + + double Det = 0; + + // Get the P Matrix + EQMP = GETPQ(a1, a2, a3); + + // Get the Q Matrix + EQMQ = GETPQ(m1, m2, m3); + + // Get the Inverse of P + // Get the EQMP Determinant for Inverse Computation + Det = (EQMP.Element[0, 0] * EQMP.Element[1, 1]) - (EQMP.Element[0, 1] * EQMP.Element[1, 0]); + + // Make sure Determinant is NON ZERO + if (Det == 0) + { + throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); + } + else + { + //Perform the Matrix Inversion, put result to EQMI matrix + EQMI.Element[0, 0] = (EQMP.Element[1, 1]) / Det; + EQMI.Element[0, 1] = (-EQMP.Element[0, 1]) / Det; + EQMI.Element[1, 0] = (-EQMP.Element[1, 0]) / Det; + EQMI.Element[1, 1] = (EQMP.Element[0, 0]) / Det; + } + + // Get the M Matrix by Multiplying EQMI and EQMQ + // EQMI - Matrix A + // EQMQ - Matrix B + EQMM.Element[0, 0] = (EQMI.Element[0, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 0]); + EQMM.Element[0, 1] = (EQMI.Element[0, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 1]); + EQMM.Element[1, 0] = (EQMI.Element[1, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 0]); + EQMM.Element[1, 1] = (EQMI.Element[1, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 1]); + + // Get the Coordinate Offset Vector and store it at EQCO Matrix + EQCO.x = m1.x - ((a1.x * EQMM.Element[0, 0]) + (a1.y * EQMM.Element[1, 0])); + EQCO.y = m1.y - ((a1.x * EQMM.Element[0, 1]) + (a1.y * EQMM.Element[1, 1])); + + if ((x + Y) == 0) + { + return 0; + } + else + { + return EQ_CheckPoint_in_Triangle(x, Y, m1.x, m1.y, m2.x, m2.y, m3.x, m3.y); + } + + } + + + ////Function to transform the Coordinates (Affine Mapping) using the M Matrix and Offset Vector + + //private Coord EQ_Transform_Affine(Coord ob) + //{ + + // // CoordTransform = Offset + CoordObject * Matrix M + + // Coord result = new Coord(); + // result.x = EQCO.x + ((ob.x * EQMM.Element[0, 0]) + (ob.y * EQMM.Element[1, 0])); + // result.y = EQCO.y + ((ob.x * EQMM.Element[0, 1]) + (ob.y * EQMM.Element[1, 1])); + + // return result; + //} + + //Function to convert spherical coordinates to Cartesian using the Coord structure + + internal Coord EQ_sp2Cs(EncoderPosition pos) + { + Coord result = new Coord(); + + CartesCoord tmpobj = new CartesCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); + + if (PolarEnable) + { + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj = EQ_Polar2Cartes(tmpobj4); + result.x = tmpobj.x; + result.y = tmpobj.y; + result.z = 1; + } + else + { + result.x = pos.RA; + result.y = pos.Dec; + result.z = 1; + } + + return result; + } + + + ////Function to convert spherical coordinates to Cartesian using the Coord structure + + //internal Coord EQ_sp2Cs2(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECEncoder_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAEncoder_Home_pos = 0; + + // CartesCoord tmpobj = new CartesCoord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, this.StepsPerRev, this.HomeEncoder, Math.Abs(gLatitude)); + // tmpobj = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + // result.x = tmpobj.x; + // result.y = tmpobj.y; + // result.z = 1; + // } + // else + // { + // result.x = obj.x; + // result.y = obj.y; + // result.z = 1; + // } + + // return result; + //} + + + ////Function to convert polar coordinates to Cartesian using the Coord structure + + + //internal Coord EQ_pl2Cs(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECEncoder_Home_pos = 0; + // double gTot_step = 0; + // object HC = null; + // double RAEncoder_Home_pos = 0; + + // CartesCoord tmpobj = new CartesCoord(); + + // if (PolarEnable) + // { + // tmpobj = EQ_Polar2Cartes(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // result.x = tmpobj.x; + // result.y = tmpobj.y; + // result.z = 1; + // } + // else + // { + // result.x = obj.x; + // result.y = obj.y; + // result.z = 1; + // } + + // return result; + //} + + ////Implement an Affine transformation on a Polar coordinate system + ////This is done by converting the Polar Data to Cartesian, Apply affine transformation + ////Then restore the transformed Cartesian Coordinates back to polar + + + //internal Coord EQ_plAffine(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECEncoder_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAEncoder_Home_pos = 0; + + // CartesCoord tmpobj1 = new CartesCoord(); + // Coord tmpobj2 = new Coord(); + // Coord tmpobj3 = new Coord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); + + // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // tmpobj2.x = tmpobj1.x; + // tmpobj2.y = tmpobj1.y; + // tmpobj2.z = 1; + + // tmpobj3 = EQ_Transform_Affine(tmpobj2); + + // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); + + // } + // else + // { + // tmpobj3 = EQ_Transform_Affine(obj); + // result.x = tmpobj3.x; + // result.y = tmpobj3.y; + // result.z = 1; + // } + + // return result; + //} + + + //internal Coord EQ_plAffine2(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECEncoder_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAEncoder_Home_pos = 0; + + // CartesCoord tmpobj1 = new CartesCoord(); + // Coord tmpobj2 = new Coord(); + // Coord tmpobj3 = new Coord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); + + // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // tmpobj2.x = tmpobj1.x; + // tmpobj2.y = tmpobj1.y; + // tmpobj2.z = 1; + + // tmpobj3 = EQ_Transform_Affine(tmpobj2); + + // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + + // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); + + // } + // else + // { + // tmpobj3 = EQ_Transform_Affine(obj); + // result.x = tmpobj3.x; + // result.y = tmpobj3.y; + // result.z = 1; + // } + + // return result; + //} + ////Implement a TAKI transformation on a Polar coordinate system + ////This is done by converting the Polar Data to Cartesian, Apply TAKI transformation + ////Then restore the transformed Cartesian Coordinates back to polar + + //internal Coord EQ_plTaki(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECEncoder_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAEncoder_Home_pos = 0; + + // CartesCoord tmpobj1 = new CartesCoord(); + // Coord tmpobj2 = new Coord(); + // Coord tmpobj3 = new Coord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); + // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // tmpobj2.x = tmpobj1.x; + // tmpobj2.y = tmpobj1.y; + // tmpobj2.z = 1; + + // tmpobj3 = EQ_Transform_Taki(tmpobj2); + + // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + + // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); + + // } + // else + // { + // tmpobj3 = EQ_Transform_Taki(obj); + // result.x = tmpobj3.x; + // result.y = tmpobj3.y; + // result.z = 1; + // } + + // return result; + //} + + // Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates + + private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) + { + CartesCoord result = new CartesCoord(); + double i = 0; + + // make angle stays within the 360 bound + if (polar.x > this.HomeEncoder.RA) + { + i = ((polar.x - this.HomeEncoder.RA) / this.StepsPerRev.RA) * 360; + } + else + { + i = ((this.HomeEncoder.RA - polar.x) / this.StepsPerRev.RA) * 360; + i = 360 - i; + } + + double theta = AstroConvert.DegToRad(Range.Range360(i)); + + //treat y as the radius of the polar coordinate + + double radius = polar.y - this.HomeEncoder.Dec; + + double radpeak = 0; + + + // Avoid division 0 errors + + if (radius == 0) + { + radius = 1; + } + + // Get the cartesian coordinates + + result.x = Math.Cos(theta) * radius; + result.y = Math.Sin(theta) * radius; + result.ra = radpeak; + + // if radius is a negative number, pass this info on the next conversion routine + + if (radius > 0) + { + result.r = 1; + } + else + { + result.r = -1; + } + + return result; + } + + ////Function to convert the Cartesian Coordinate data back to RA/DEC polar + + //private Coord EQ_Cartes2Polar(double x, double Y, double r, double RA, double TOT, double RACENTER, double DECCENTER) + //{ + // Coord result = new Coord(); + // double PI = 0; + // double RAD_DEG = 0; + + + // // Ah the famous radius formula + + // double radiusder = Math.Sqrt((x * x) + (Y * Y)) * r; + + + // // And the nasty angle compute routine (any simpler way to impelent this ?) + + // double angle = 0; + // if (x > 0) + // { + // angle = Math.Atan(Y / x); + // } + // if (x < 0) + // { + // if (Y >= 0) + // { + // angle = Math.Atan(Y / x) + PI; + + // } + // else + // { + // angle = Math.Atan(Y / x) - PI; + // } + // } + // if (x == 0) + // { + // if (Y > 0) + // { + // angle = PI / 2d; + // } + // else + // { + // angle = -1 * (PI / 2d); + // } + // } + + // // Convert angle to degrees + + // angle *= RAD_DEG; + + // if (angle < 0) + // { + // angle = 360 + angle; + // } + + // if (r < 0) + // { + // angle = Range.Range360((angle + 180)); + // } + + // if (angle > 180) + // { + // result.x = RACENTER - (((360 - angle) / 360d) * TOT); + // } + // else + // { + // result.x = ((angle / 360d) * TOT) + RACENTER; + // } + + // //treat y as the polar coordinate radius (ra var not used - always 0) + + // result.y = radiusder + DECCENTER + RA; + + // return result; + //} + + //internal int EQ_UpdateTaki(double x, double Y) + //{ + // int g3PointAlgorithm = 0; + // int gAlignmentStars_count = 0; + + // TriangleCoord tr = new TriangleCoord(); + // Coord tmpcoord = new Coord(); + + // // Adjust only if there are four alignment stars + // if (gAlignmentStars_count < 3) + // { + // return 0; + // } + + + // switch (g3PointAlgorithm) + // { + // case 1: + // // find the 50 nearest points - then find the nearest enclosing triangle + // tr = EQ_ChooseNearest3Points(x, Y); + // break; + // default: + // // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + // tr = EQ_Choose_3Points(x, Y); + // break; + // } + + // double gTaki1 = tr.i; + // double gTaki2 = tr.j; + // double gTaki3 = tr.k; + + // if (gTaki1 == 0 || gTaki2 == 0 || gTaki3 == 0) + // { + // return 0; + // } + + // tmpcoord.x = x; + // tmpcoord.y = Y; + // tmpcoord = EQ_sp2Cs(tmpcoord); + // return EQ_AssembleMatrix_Taki(tmpcoord.x, tmpcoord.y, EQASCOM.ct_PointsC[Convert.ToInt32(gTaki1)], EQASCOM.ct_PointsC[Convert.ToInt32(gTaki2)], EQASCOM.ct_PointsC[Convert.ToInt32(gTaki3)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki1)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki2)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki3)]); + + //} + + //internal int EQ_UpdateAffine(AxisPosition encoder) + //{ + // int result = 0; + // int g3PointAlgorithm = 0; + // int gAlignmentStars_count = 0; + + // TriangleCoord tr = new TriangleCoord(); + + // if (gAlignmentStars_count < 3) + // { + // return result; + // } + + // switch (g3PointAlgorithm) + // { + // case 1: + // // find the 50 nearest points - then find the nearest enclosing triangle + // tr = EQ_ChooseNearest3Points(encoder); + // break; + // default: + // // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + // tr = EQ_Choose_3Points(encoder); + // break; + // } + + // double gAffine1 = tr.i; + // double gAffine2 = tr.j; + // double gAffine3 = tr.k; + + // if (gAffine1 == 0 || gAffine1 == 0 || gAffine1 == 0) + // { + // return 0; + // } + + // Coord tmpcoord = EQ_sp2Cs(encoder); + + // result = EQ_AssembleMatrix_Affine(tmpcoord.x, tmpcoord.y, EQASCOM.my_PointsC[Convert.ToInt32(gAffine1)], EQASCOM.my_PointsC[Convert.ToInt32(gAffine2)], EQASCOM.my_PointsC[Convert.ToInt32(gAffine3)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine1)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine2)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine3)]); + + // if (result == 0) + // { + // gAffine1 = 0; + // gAffine2 = 0; + // gAffine3 = 0; + // } + + // return result; + //} + + //// Subroutine to implement find Array index with the lowest value + //private int EQ_FindLowest(double[] List, int min, int max) + //{ + // double val = 0; + // double newval = 0; + // int i = 0; + + // int idx = -1; + // int tempForEndVar = 0; + // if (!(min >= max || max > List.GetUpperBound(0))) + // { + + // val = List[min]; + // tempForEndVar = max; + // for (i = min; i <= tempForEndVar; i++) + // { + // newval = List[i]; + // if (newval <= val) + // { + // val = newval; + // idx = i; + // } + // } + + // } + + // return idx; + //} + + //private void EQ_FindLowest3(double[] List, int[] Sublist, int min, int max) + //{ + // double val = 0; + // double min1 = 0; + // double min2 = 0; + // double min3 = 0; + // int i = 0; + + // int tempForEndVar = 0; + // if (!(min >= max || max > List.GetUpperBound(0))) + // { + + // if (List[1] <= List[2] && List[1] <= List[3]) + // { + // //List 1 is first + // min1 = List[1]; + // if (List[2] <= List[3]) + // { + // //List2 is second + // //List3 is third + // min2 = List[2]; + // min3 = List[3]; + // } + // else + // { + // //List3 is second + // //List2 is third + // min2 = List[3]; + // min3 = List[2]; + // } + // } + // else + // { + // if (List[2] <= List[1] && List[2] <= List[3]) + // { + // //List 2 is first + // min1 = List[2]; + // if (List[1] <= List[3]) + // { + // //List1 is second + // //List3 is third + // min2 = List[1]; + // min3 = List[3]; + // } + // else + // { + // //List3 is second + // //List1 is third + // min2 = List[3]; + // min3 = List[1]; + // } + // } + // else + // { + // if (List[3] <= List[1] && List[3] <= List[2]) + // { + // //List 3 is first + // min1 = List[3]; + // if (List[1] <= List[2]) + // { + // //List1 is second + // //List2 is third + // min2 = List[1]; + // min3 = List[2]; + // } + // else + // { + // //List2 is second + // //List1 is third + // min2 = List[2]; + // min3 = List[1]; + // } + // } + // } + // } + + // val = List[min]; + + // tempForEndVar = max; + // for (i = min; i <= tempForEndVar; i++) + // { + // val = List[i]; + // if (val < min1) + // { + // min1 = val; + // Sublist[3] = Sublist[2]; + // Sublist[2] = Sublist[1]; + // Sublist[1] = i; + // } + // else + // { + // if (val < min2) + // { + // min2 = val; + // Sublist[3] = Sublist[2]; + // Sublist[2] = i; + // } + // else + // { + // if (val < min3) + // { + // Sublist[3] = i; + // } + // } + // } + // } + + // } + + + //} + + + + + //// Subroutine to implement an Array sort + //private void EQ_Quicksort(double[] List, double[] Sublist, int min, int max) + //{ + + + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // double med_value = List[i]; + // double submed = Sublist[i]; + + // List[i] = List[min]; + // Sublist[i] = Sublist[min]; + + // int lo = min; + // int hi = max; + // do + // { + + // while (List[hi] >= med_value) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // Sublist[lo] = submed; + // break; + // } + + // List[lo] = List[hi]; + // Sublist[lo] = Sublist[hi]; + + // lo++; + + // while (List[lo] < med_value) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // Sublist[hi] = submed; + // break; + // } + + // List[hi] = List[lo]; + // Sublist[hi] = Sublist[lo]; + + // } + // while (true); + + // EQ_Quicksort(List, Sublist, min, lo - 1); + // EQ_Quicksort(List, Sublist, lo + 1, max); + + //} + + + //// Subroutine to implement an Array sort + + //private void EQ_Quicksort2(Tdatholder[] List, int min, int max) + //{ + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // Tdatholder med_value = Tdatholder.CreateInstance(); + + // List[i] = List[min]; + + // int lo = min; + // int hi = max; + + // do + // { + + // while (List[hi].dat >= med_value.dat) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // break; + // } + + // List[lo] = List[hi]; + + // lo++; + + // while (List[lo].dat < med_value.dat) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // break; + // } + + // List[hi] = List[lo]; + // } + // while (true); + + // EQ_Quicksort2(List, min, lo - 1); + // EQ_Quicksort2(List, lo + 1, max); + + //} + + //// Subroutine to implement an Array sort with three sublists + + //private void EQ_Quicksort3(double[] List, double[] Sublist1, double[] Sublist2, double[] Sublist3, int min, int max) + //{ + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // double med_value = List[i]; + // double submed1 = Sublist1[i]; + // double submed2 = Sublist2[i]; + // double submed3 = Sublist3[i]; + + // List[i] = List[min]; + // Sublist1[i] = Sublist1[min]; + // Sublist2[i] = Sublist2[min]; + // Sublist3[i] = Sublist3[min]; + + // int lo = min; + // int hi = max; + // do + // { + + + // while (List[hi] >= med_value) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // Sublist1[lo] = submed1; + // Sublist2[lo] = submed2; + // Sublist3[lo] = submed3; + // break; + // } + + + // List[lo] = List[hi]; + // Sublist1[lo] = Sublist1[hi]; + // Sublist2[lo] = Sublist2[hi]; + // Sublist3[lo] = Sublist3[hi]; + + // lo++; + + // while (List[lo] < med_value) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // Sublist1[hi] = submed1; + // Sublist2[hi] = submed2; + // Sublist3[hi] = submed3; + // break; + // } + + // List[hi] = List[lo]; + // Sublist1[hi] = Sublist1[lo]; + // Sublist2[hi] = Sublist2[lo]; + // Sublist3[hi] = Sublist3[lo]; + // } + // while (true); + + // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, min, lo - 1); + // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, lo + 1, max); + + //} + + // Function to compute for an area of a triangle + + private double EQ_Triangle_Area(double px1, double py1, double px2, double py2, double px3, double py3) + { + + + //True formula is this + // EQ_Triangle_Area = Abs(((px2 * py1) - (px1 * py2)) + ((px3 * py2) - (px2 * py3)) + ((px1 * py3) - (px3 * py1))) / 2 + + // Make LARGE numerical value safe for Windows by adding a scaling factor + + double ta = (((px2 * py1) - (px1 * py2)) / 10000d) + (((px3 * py2) - (px2 * py3)) / 10000d) + (((px1 * py3) - (px3 * py1)) / 10000d); + + return Math.Abs(ta) / 2d; + + } + + // Function to check if a point is inside the triangle. Computed based sum of areas method + + private int EQ_CheckPoint_in_Triangle(double px, double py, double px1, double py1, double px2, double py2, double px3, double py3) + { + + + double ta = EQ_Triangle_Area(px1, py1, px2, py2, px3, py3); + double t1 = EQ_Triangle_Area(px, py, px2, py2, px3, py3); + double t2 = EQ_Triangle_Area(px1, py1, px, py, px3, py3); + double t3 = EQ_Triangle_Area(px1, py1, px2, py2, px, py); + + + if (Math.Abs(ta - t1 - t2 - t3) < 2) + { + return 1; + } + else + { + return 0; + } + + } + + + + + //private Coord EQ_GetCenterPoint(Coord p1, Coord p2, Coord p3) + //{ + + // Coord result = new Coord(); + // double p2x = 0; + // double p2y = 0; + // double p4x = 0; + // double p4y = 0; + + + + + + // // Get the two line 4 point data + + // double p1x = p1.x; + // double p1y = p1.y; + + + // if (p3.x > p2.x) + // { + // p2x = ((p3.x - p2.x) / 2d) + p2.x; + // } + // else + // { + // p2x = ((p2.x - p3.x) / 2d) + p3.x; + // } + + // if (p3.y > p2.y) + // { + // p2y = ((p3.y - p2.y) / 2d) + p2.y; + // } + // else + // { + // p2y = ((p2.y - p3.y) / 2d) + p3.y; + // } + + // double p3x = p2.x; + // double p3y = p2.y; + + + // if (p1.x > p3.x) + // { + // p4x = ((p1.x - p3.x) / 2d) + p3.x; + // } + // else + // { + // p4x = ((p3.x - p1.x) / 2d) + p1.x; + // } + + // if (p1.y > p3.y) + // { + // p4y = ((p1.y - p3.y) / 2d) + p3.y; + // } + // else + // { + // p4y = ((p3.y - p1.y) / 2d) + p1.y; + // } + + + // double XD1 = p2x - p1x; + // double XD2 = p4x - p3x; + // double YD1 = p2y - p1y; + // double YD2 = p4y - p3y; + // double XD3 = p1x - p3x; + // double YD3 = p1y - p3y; + + + // double dv = (YD2 * XD1) - (XD2 * YD1); + + // if (dv == 0) + // { + // dv = 0.00000001d; + // } //avoid div 0 errors + + + // double ua = ((XD2 * YD3) - (YD2 * XD3)) / dv; + // double ub = ((XD1 * YD3) - (YD1 * XD3)) / dv; + + // result.x = p1x + (ua * XD1); + // result.y = p1y + (ub * YD1); + + // return result; + //} + + + private SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) + { + SphericalCoord result = new SphericalCoord(); + + double ha = Get_EncoderHours(spherical.RA); + double dec = Range.Range360(Get_EncoderDegrees(spherical.Dec) + 270); + + double[] altAz = AstroConvert.HaDec2AltAz(ha, dec, SiteLatitude); + + + result.x = (((altAz[1] - 180) / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; + result.y = (((altAz[0] + 90) / 180d) * this.StepsPerRev.Dec) + this.HomeEncoder.Dec; + + // Check if RA value is within allowed visible range + double quadrant = this.StepsPerRev.RA / 4d; + if ((spherical.RA <= (this.HomeEncoder.RA + quadrant)) && (spherical.RA >= (this.HomeEncoder.RA - quadrant))) + { + result.r = 1; + } + else + { + result.r = 0; + } + + return result; + } + + //private Coord EQ_PolarSpherical(double RA, double DEC, double TOT, double RACENTER, double DECCENTER, double Latitude, double range) + //{ + // Coord result = new Coord(); + // double x = 0; + // double y = 0; + + + // double i = (((RA - RACENTER) / TOT) * 360) + 180; + // double j = (((DEC - DECCENTER) / TOT) * 180) - 90; + + // object tempAuxVar = aa_hadec[Convert.ToInt32(Latitude * DEG_RAD), Convert.ToInt32(j * DEG_RAD), Convert.ToInt32(i * DEG_RAD), Convert.ToInt32(x), Convert.ToInt32(y)]; + + // if (i > 180) + // { + // if (range == 0) + // { + // y = Range.Range360(180 - AstroConvert.RadToDeg(y)); + // } + // else + // { + // y = Range.Range360(AstroConvert.RadToDeg(y)); + // } + // } + // else + // { + // if (range == 0) + // { + // y = Range.Range360(AstroConvert.RadToDeg(y)); + // } + // else + // { + // y = Range.Range360(180 - AstroConvert.RadToDeg(y)); + // } + // } + + // j = Range.Range360(y + 90); + + // if (j < 180) + // { + // if (range == 1) + // { + // x = Range.Range24(AstroConvert.RadToHrs(x)); + // } + // else + // { + // x = Range.Range24(24 + AstroConvert.RadToHrs(x)); + // } + // } + // else + // { + // x = Range.Range24(12 + AstroConvert.RadToHrs(x)); + // } + + + // result.x = Get_EncoderfromHours(this.HomeEncoder.RA, x, this.StepsPerRev.RA, 0); + // result.y = Get_EncoderfromDegrees(this.HomeEncoder.Dec, y + 90, this.StepsPerRev.Dec, 0, 0); + + // return result; + //} + + + //private CartesCoord EQ_Spherical2Cartes(double RA, double DEC, double TOT, double RACENTER, double DECCENTER) + //{ + // CartesCoord result = new CartesCoord(); + // double gLatitude = 0; + + + // SphericalCoord tmpobj4 = EQ_SphericalPolar(RA, DEC, TOT, RACENTER, DECCENTER, gLatitude); + + // CartesCoord tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, TOT, RACENTER, DECCENTER); + + // result.x = tmpobj1.x; + // result.y = tmpobj1.y; + // result.ra = tmpobj1.ra; + // result.r = tmpobj1.r; + + // return result; + //} + + //private Coord EQ_Cartes2Spherical(double x, double Y, double r, double RA, double range, double TOT, double RACENTER, double DECCENTER) + //{ + // double gDECEncoder_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // double RAEncoder_Home_pos = 0; + + // Coord tmpobj2 = EQ_Cartes2Polar(x, Y, r, RA, TOT, RACENTER, DECCENTER); + // return EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, range); + + //} + + + //internal TriangleCoord EQ_Choose_3Points(AxisPosition encoder) + //{ + // TriangleCoord result = new TriangleCoord(); + // Coord tmpcoords = new Coord(); + // Coord p1 = new Coord(); + // Coord p2 = new Coord(); + // Coord p3 = new Coord(); + // Coord pc = new Coord(); + + // Tdatholder[] datholder = new Tdatholder[EQASCOM.MAX_STARS]; + // double combi_cnt = 0; + // double tmp1 = 0; + // int tmp2 = 0; + // bool first = false; + // double last_dist = 0; + // double new_dist = 0; + + // // Adjust only if there are three alignment stars + + // if (AlignmentPoints.Count < 3) + // { + // result.i = 1; + // result.j = 2; + // result.k = 3; + // return result; + // } + + // Coord tmpcoord = EQ_sp2Cs(encoder); + + // int Count = 0; + // for (int i = 0; i < EQASCOM.gAlignmentStars_count; i++) + // { + + // datholder[Count].cc = EQASCOM.my_PointsC[i]; + // switch (ActivePoints) + // { + // case ActivePointsEnum.All: + // // all points + + // break; + // case ActivePointsEnum.PierSide: + // // only consider points on this side of the meridian + // if (datholder[Count].cc.y * tmpcoord.y < 0) + // { + // goto NextPoint; + // } + + // break; + // case ActivePointsEnum.LocalQuadrant: + // // local quadrant + // if (!GetQuadrant(tmpcoord).Equals(GetQuadrant(datholder[Count].cc))) + // { + // goto NextPoint; + // } + + // break; + // } + + // if (CheckLocalPier) + // { + // // calculate polar distance + // datholder[Count].dat = Math.Pow(EQASCOM.my_Points[i].x - x, 2) + Math.Pow(EQASCOM.my_Points[i].y - Y, 2); + // } + // else + // { + // // calculate cartesian disatnce + // datholder[Count].dat = Math.Pow(datholder[Count].cc.x - tmpcoord.x, 2) + Math.Pow(datholder[Count].cc.y - tmpcoord.y, 2); + // } + + // // Also save the reference star id for this particular reference star + // datholder[Count].idx = Convert.ToInt16(i); + + // Count++; + // NextPoint:; + // } + + // if (Count < 3) + // { + // // not enough points to do 3-point + // result.i = 0; + // result.j = 0; + // result.k = 0; + // return result; + // } + + // // now sort the disatnces so the closest stars are at the top + // EQ_Quicksort2(datholder, 1, Count); + + // //Just use the nearest 50 stars (max) - saves processing time + // if (Count > EQASCOM.gMaxCombinationCount - 1) + // { + // combi_cnt = EQASCOM.gMaxCombinationCount; + // } + // else + // { + // combi_cnt = Count; + // } + + // // combi_offset = 1 + // tmp1 = combi_cnt - 1; + // tmp2 = Convert.ToInt32(combi_cnt - 2); + // first = true; + // // iterate through all the triangles posible using the nearest alignment points + // int l = 1; + // int m = 2; + // int n = 3; + // int tempForEndVar2 = (tmp2); + // for (int i = 1; i <= tempForEndVar2; i++) + // { + // p1 = datholder[Convert.ToInt32(i) - 1].cc; + // double tempForEndVar3 = (tmp1); + // for (int j = i + 1; j <= tempForEndVar3; j++) + // { + // p2 = datholder[Convert.ToInt32(j) - 1].cc; + // double tempForEndVar4 = combi_cnt; + // for (int k = (j + 1); k <= tempForEndVar4; k++) + // { + // p3 = datholder[Convert.ToInt32(k) - 1].cc; + + // if (EQ_CheckPoint_in_Triangle(tmpcoord.x, tmpcoord.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y) == 1) + // { + // // Compute for the center point + // pc = EQ_GetCenterPoint(p1, p2, p3); + // // don't need full pythagoras - sum of squares is good enough + // new_dist = Math.Pow(pc.x - tmpcoord.x, 2) + Math.Pow(pc.y - tmpcoord.y, 2); + + // if (first) + // { + // // first time through + // last_dist = new_dist; + // first = false; + // l = i; + // m = j; + // n = Convert.ToInt32(k); + // } + // else + // { + // if (new_dist < last_dist) + // { + // l = i; + // m = j; + // n = Convert.ToInt32(k); + // last_dist = new_dist; + // } + // } + // } + // } + // } + // } + + // if (first) + // { + // result.i = 0; + // result.j = 0; + // result.k = 0; + // } + // else + // { + // result.i = datholder[Convert.ToInt32(l) - 1].idx; + // result.j = datholder[Convert.ToInt32(m) - 1].idx; + // result.k = datholder[n - 1].idx; + // } + + // return result; + //} + + //internal TriangleCoord EQ_ChooseNearest3Points(AxisPosition encoder) + //{ + // TriangleCoord result = new TriangleCoord(); + // Coord p1 = new Coord(); + // Coord p2 = new Coord(); + // Coord p3 = new Coord(); + // Coord pc = new Coord(); + + // Tdatholder[] datholder = new Tdatholder[EQASCOM.MAX_STARS]; + // double combi_cnt = 0; + // double tmp1 = 0; + // int tmp2 = 0; + // bool first = false; + + // // Adjust only if there are three alignment stars + + // if (AlignmentPoints.Count <= 3) + // { + // result.i = 1; + // result.j = 2; + // result.k = 3; + // return result; + // } + + // Coord tmpcoord = EQ_sp2Cs(encoder); + + // int Count = 0; + // // first find out the distances to the alignment stars + // for (int i = 1; i <= EQASCOM.gAlignmentStars_count; i++) + // { + + // datholder[Count].cc = EQASCOM.my_PointsC[Convert.ToInt32(i)]; + + // switch (ActivePoints) + // { + // case ActivePointsEnum.All: + // // all points + + // break; + // case ActivePointsEnum.PierSide: + // // only consider points on this side of the meridian + // if (datholder[Count].cc.y * tmpcoord.y < 0) + // { + // goto NextPoint; + // } + + // break; + // case ActivePointsEnum.LocalQuadrant: + // // local quadrant + // if (!GetQuadrant(tmpcoord).Equals(GetQuadrant(datholder[Count].cc))) + // { + // goto NextPoint; + // } + + // break; + // } + + // if (CheckLocalPier) + // { + // // calculate polar distance + // datholder[Count].dat = Math.Pow(EQASCOM.my_Points[i].x - x, 2) + Math.Pow(EQASCOM.my_Points[i].y - Y, 2); + // } + // else + // { + // // calculate cartesian disatnce + // datholder[Count].dat = Math.Pow(datholder[Count].cc.x - tmpcoord.x, 2) + Math.Pow(datholder[Count].cc.y - tmpcoord.y, 2); + // } + + // // Also save the reference star id for this particular reference star + // datholder[Count].idx = Convert.ToInt16(i); + + // Count++; + // NextPoint:; + // } + + // if (Count < 3) + // { + // // not enough points to do 3-point + // result.i = 0; + // result.j = 0; + // result.k = 0; + // return result; + // } + + // // now sort the disatnces so the closest stars are at the top + // EQ_Quicksort2(datholder, 1, Count); + + // //Just use the nearest 50 stars (max) - saves processing time + // if (Count > EQASCOM.gMaxCombinationCount - 1) + // { + // combi_cnt = EQASCOM.gMaxCombinationCount; + // } + // else + // { + // combi_cnt = Count; + // } + + // tmp1 = combi_cnt - 1; + // tmp2 = Convert.ToInt32(combi_cnt - 2); + // first = true; + + // // iterate through all the triangles posible using the nearest alignment points + // int l = 1; + // int m = 2; + // int n = 3; + // int tempForEndVar2 = (tmp2); + // for (int i = 1; i <= tempForEndVar2; i++) + // { + // p1 = datholder[Convert.ToInt32(i) - 1].cc; + // double tempForEndVar3 = (tmp1); + // for (int j = i + 1; j <= tempForEndVar3; j++) + // { + // p2 = datholder[Convert.ToInt32(j) - 1].cc; + // double tempForEndVar4 = combi_cnt; + // for (int k = (j + 1); k <= tempForEndVar4; k++) + // { + // p3 = datholder[Convert.ToInt32(k) - 1].cc; + + // if (EQ_CheckPoint_in_Triangle(tmpcoord.x, tmpcoord.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y) == 1) + // { + // l = i; + // m = j; + // n = Convert.ToInt32(k); + // goto alldone; + // } + // } + // } + // } + + // result.i = 0; + // result.j = 0; + // result.k = 0; + // return result; + + //alldone: + // result.i = datholder[Convert.ToInt32(l) - 1].idx; + // result.j = datholder[Convert.ToInt32(m) - 1].idx; + // result.k = datholder[n - 1].idx; + + // return result; + //} + + //public static float GetRnd() + //{ + // Random r = new Random(); + // return (float)(r.Next(1, 1000) / 1000.0); + //} + + } +} + + diff --git a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs new file mode 100644 index 00000000..a56dc3e2 --- /dev/null +++ b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs @@ -0,0 +1,75 @@ +using EqmodNStarAlignment.Utilities; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +namespace EqmodNStarAlignment.Model +{ + partial class AlignmentModel + { + public bool EQ_NPointAppend(AlignmentPoint data) + { + bool eq_NPointAppend = true; + _oneStarAdjustment = data.Delta; + + if (AlignmentPoints.Count < 3) + { + // Less than three alignment points so just add the incoming one. + AlignmentPoints.Add(data); + } + else + { + if (AlignmentPoints.Count == 3) + { + // Update the matrices + SendToMatrix(); + } + else + { + // Now have more than 3 so see if this point is a replacement + var nearPoints = this.AlignmentPoints.Where(ap => Math.Abs(ap.Encoder.RA - data.Encoder.RA) < _proximityStepsRa + || Math.Abs(ap.Encoder.Dec - data.Encoder.Dec) < _proximityStepsDec).ToList(); + foreach (AlignmentPoint ap in nearPoints) + { + this.AlignmentPoints.Remove(ap); + } + + // Add the incoming point + AlignmentPoints.Add(data); + + // Update the matrices + SendToMatrix(); + } + } + return eq_NPointAppend; + } + public void SendToMatrix() + { + foreach (AlignmentPoint pt in AlignmentPoints) + { + pt.EncoderCartesian = EQ_sp2Cs(pt.Encoder); + pt.TargetCartesian = EQ_sp2Cs(pt.Target); + + } + + ActivateMatrix(); + } + + private void ActivateMatrix() + { + _threeStarEnabled = false; + if (AlignmentPoints.Count >= 3) + { + + _ =EQ_AssembleMatrix_Taki(0, 0, + AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian, + AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian,AlignmentPoints[2].EncoderCartesian); + _ =EQ_AssembleMatrix_Affine(0, 0, + AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian, AlignmentPoints[2].EncoderCartesian, + AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian); + } + } + // /pec /showalignment + } +} diff --git a/EQMODAlignment/Model/AlignmentModel_Math.cs b/EQMODAlignment/Model/AlignmentModel_Math.cs new file mode 100644 index 00000000..c7acce79 --- /dev/null +++ b/EQMODAlignment/Model/AlignmentModel_Math.cs @@ -0,0 +1,1014 @@ +/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +//--------------------------------------------------------------------- +// based on original work +// Copyright © 2006 Raymund Sarmiento +// +// Permission is hereby granted to use this Software for any purpose +// including combining with commercial products, creating derivative +// works, and redistribution of source or binary code, without +// limitation or consideration. Any redistributed copies of this +// Software must include the above Copyright Notice. +// +// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO +// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS +// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//--------------------------------------------------------------------- +// +// EQMATH.bas - Math functions for EQMOD ASCOM RADECALTAZ computations +// +// +// Written: 07-Oct-06 Raymund Sarmiento +// +// Edits: +// +// When Who What +// --------- --- -------------------------------------------------- +// 04-Nov-06 rcs Initial edit for EQ Mount Driver Function Prototype +// 20-Nov-06 rcs wrote a new function for now_lst that will generate millisecond +// granularity +// 21-Nov-06 rcs Append RA GOTO Compensation to minimize discrepancy +// 19-Mar-07 rcs Initial Edit for Three star alignment +// 05-Apr-07 rcs Add MAXSYNC +// 08-Apr-07 rcs N-star implementation +// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# +//--------------------------------------------------------------------- +// +// +// DISCLAIMER: + +// You can use the information on this site COMPLETELY AT YOUR OWN RISK. +// The modification steps and other information on this site is provided +// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, +// implied or otherwise, including without limitation any warranty of +// merchantability or fitness for any particular or intended purpose. +// In no event the author will be liable for any direct, indirect, +// punitive, special, incidental or consequential damages or loss of any +// kind whether or not the author has been advised of the possibility +// of such loss. + +using EqmodNStarAlignment.DataTypes; +using EqmodNStarAlignment.Utilities; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.Model +{ + partial class AlignmentModel + { + + //private const double DEG_RAD = 0.0174532925d; + //private const double RAD_DEG = 57.2957795d; + //private const double HRS_RAD = 0.2617993881d; + //private const double RAD_HRS = 3.81971863d; + + //private const double SID_RATE = 15.041067d; + //private const double SOL_RATE = 15; + //private const double LUN_RATE = 14.511415d; + + //private const double gEMUL_RATE = 20.98d; // 0.2 * 9024000/( (23*60*60)+(56*60)+4) + // // 0.2 = 200ms + + //private const double gEMUL_RATE2 = 104.730403903004d; // (9024000/86164.0905) + + //// 104.73040390300411747513310083625 + + //private const double gARCSECSTEP = 0.144d; // .144 arcesconds / step + + //// Iterative GOTO Constants + ////Public Const NUM_SLEW_RETRIES As Long = 5 ' Iterative MAX retries + //private const double gRA_Allowed_diff = 10; // Iterative Slew minimum difference + + + //// Home Position of the mount (pointing at NCP/SCP) + + //private const double RAEncoder_Home_pos = 0x800000; // Start at 0 Hour + //private const double DECEncoder_Home_pos = 0xA26C80; // Start at 90 Degree position + + //private const double gRAEncoder_Zero_pos = 0x800000; // ENCODER 0 Hour initial position + //private const double gDECEncoder_Zero_pos = 0x800000; // ENCODER 0 Degree Initial position + + //private const double gDefault_step = 9024000; // Total Encoder count (EQ5/6) + + + + ////Public Const EQ_MAXSYNC As Double = &H111700 + + //// Public Const EQ_MAXSYNC_Const As Double = &H88B80 ' Allow a 45 degree discrepancy + + + //private const double EQ_MAXSYNC_Const = 0x113640; // Allow a 45 degree discrepancy + + ////------------------------------------------------------------------------------------------------ + + //// Define all Global Variables + + + //public static double gXshift = 0; + //public static double gYshift = 0; + //public static double gXmouse = 0; + //public static double gYmouse = 0; + + + //public static double gEQ_MAXSYNC = 0; // Max Sync Diff + //public static double gSiderealRate = 0; // Sidereal rate arcsecs/sec + //public static double gMount_Ver = 0; // Mount Version + //public static int gMount_Features = 0; // Mount Features + + //public static double gRA_LastRate = 0; // Last PEC Rate + //public static int gpl_interval = 0; // Pulseguide Interval + + //public static double eqres = 0; + //public static double gTot_step = 0; // Total Common RA-Encoder Steps + //public static double gTot_RA = 0; // Total RA Encoder Steps + //public static double gTot_DEC = 0; // Total DEC Encoder Steps + //public static double gRAWormSteps = 0; // Steps per RA worm revolution + //public static double gRAWormPeriod = 0; // Period of RA worm revolution + //public static double gDECWormSteps = 0; // Steps per DEC worm revolution + //public static double gDECWormPeriod = 0; // Period of DEC worm revolution + + //public static double gLatitude = 0; // Site Latitude + //public static double gLongitude = 0; // Site Longitude + //public static double gElevation = 0; // Site Elevation + //public static int gHemisphere = 0; + + //public static double gDECEncoder_Home_pos = 0; // DEC HomePos - Varies with different mounts + + //public static double gRA_Encoder = 0; // RA Current Polled RA Encoder value + //public static double gDec_Encoder = 0; // DEC Current Polled Encoder value + //public static double gRA_Hours = 0; // RA Encoder to Hour position + //public static double gDec_Degrees = 0; // DEC Encoder to Degree position Ranged to -90 to 90 + //public static double gDec_DegNoAdjust = 0; // DEC Encoder to actual degree position + //public static double gRAStatus = 0; // RA Polled Motor Status + //public static bool gRAStatus_slew = false; // RA motor tracking poll status + //public static double gDECStatus = 0; // DEC Polloed motor status + + //public static double gRA_Limit_East = 0; // RA Limit at East Side + //public static double gRA_Limit_West = 0; // RA Limit at West Side + + //public static double gRA1Star = 0; // Initial RA Alignment adjustment + //public static double gDEC1Star = 0; // Initial DEC Alignment adjustment + + //public static double gRASync01 = 0; // Initial RA sync adjustment + //public static double gDECSync01 = 0; // Initial DEC sync adjustment + + //public static double gRA = 0; + //public static double gDec = 0; + //public static double gAlt = 0; + //public static double gAz = 0; + //public static double gha = 0; + //public static double gSOP = 0; + + //public static string gPort = ""; + //public static int gBaud = 0; + //public static int gTimeout = 0; + //public static int gRetry = 0; + + //public static int gTrackingStatus = 0; + //public static bool gSlewStatus = false; + + //public static double gRAMoveAxis_Rate = 0; + //public static double gDECMoveAxis_Rate = 0; + + + //// Added for emulated Stepper Counters + //public static double gEmulRA = 0; + //public static double gEmulDEC = 0; + //public static bool gEmulOneShot = false; + //public static bool gEmulNudge = false; + + //public static double gCurrent_time = 0; + //public static double gLast_time = 0; + //public static double gEmulRA_Init = 0; + + //public enum PierSide2 + //{ + // pierUnknown2 = -1, + // PierEast2 = 0, + // PierWest2 = 1 + //} + + //public static PierSide2 gSideofPier = PierSide2.PierEast2; + + + //public static int gRAEncoderPolarHomeGoto = 0; + //public static int gDECEncoderPolarHomeGoto = 0; + //public static int gRAEncoderUNPark = 0; + //public static int gDECEncoderUNPark = 0; + //public static int gRAEncoderPark = 0; + //public static int gDECEncoderPark = 0; + //public static int gRAEncoderlastpos = 0; + //public static int gDECEncoderlastpos = 0; + //public static int gEQparkstatus = 0; + + //public static int gEQRAPulseDuration = 0; + //public static int gEQDECPulseDuration = 0; + //public static int gEQRAPulseEnd = 0; + //public static int gEQDECPulseEnd = 0; + //public static int gEQDECPulseStart = 0; + //public static int gEQRAPulseStart = 0; + //public static bool gEQPulsetimerflag = false; + + //public static double gEQTimeDelta = 0; + + + + //// Public variables for Custom Tracking rates + + //public static double gDeclinationRate = 0; + //public static double gRightAscensionRate = 0; + + + //// Public Variables for Spiral Slew + + //public static int gSPIRAL_JUMP = 0; + //public static double gDeclination_Start = 0; + //public static double gRightAscension_Start = 0; + //public static double gDeclination_Dir = 0; + //public static double gRightAscension_Dir = 0; + //public static int gDeclination_Len = 0; + //public static int gRightAscension_Len = 0; + + //public static double gSpiral_AxisFlag = 0; + + + + //// Public variables for debugging + + //public static double gAffine1 = 0; + //public static double gAffine2 = 0; + //public static double gAffine3 = 0; + + //public static double gTaki1 = 0; + //public static double gTaki2 = 0; + //public static double gTaki3 = 0; + + + ////Pulseguide Indicators + + //public const int gMAX_plotpoints = 100; + //public static int gMAX_RAlevel = 0; + //public static int gMAX_DEClevel = 0; + //public static int gPlot_ra_pos = 0; + //public static int gPlot_dec_pos = 0; + //public static double gplot_ra_cur = 0; + //public static double gPlot_dec_cur = 0; + //public static double gRAHeight = 0; + //public static double gDecHeight = 0; + + //// Polar Alignment Variables + + //public static double gPolarAlign_RA = 0; + //public static double gPolarAlign_DEC = 0; + + ////UPGRADE_NOTE: (2041) The following line was commented. More Information: https://www.mobilize.net/vbtonet/ewis/ewi2041 + //////UPGRADE_TODO: (1050) Structure SYSTEMTIME may require marshalling attributes to be passed as an argument in this Declare statement. More Information: https://www.mobilize.net/vbtonet/ewis/ewi1050 + ////[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] + ////extern public static void GetSystemTime(ref UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME lpSystemTime); + + + + private double Get_EncoderHours(double RAencoderPosition) + { + + double hours; + + // Compute in Hours the encoder value based on 0 position value (RAOffset0) + // and Total 360 degree rotation microstep count (Tot_Enc + + if (RAencoderPosition > this.HomeEncoder.RA) + { + hours = ((RAencoderPosition - this.HomeEncoder.RA) / StepsPerRev.RA) * 24; + hours = 24 - hours; + } + else + { + hours = ((this.HomeEncoder.RA - RAencoderPosition) / StepsPerRev.RA) * 24; + } + + if (Hemisphere == HemisphereEnum.Northern) + { + return Range.Range24(hours + 6d); // Set to true Hours which is perpendicula to RA Axis + } + else + { + return Range.Range24((24 - hours) + 6d); + } + + } + + //private int Get_EncoderfromHours(double encOffset0, double hourval, double Tot_enc, int hmspr) + //{ + + // hourval = Range24(hourval - 6d); // Re-normalize from a perpendicular position + // if (hmspr == 0) + // { + // if (hourval < 12) + // { + // return Convert.ToInt32(encOffset0 - ((hourval / 24d) * Tot_enc)); + // } + // else + // { + // return Convert.ToInt32((((24 - hourval) / 24d) * Tot_enc) + encOffset0); + // } + // } + // else + // { + // if (hourval < 12) + // { + // return Convert.ToInt32(((hourval / 24d) * Tot_enc) + encOffset0); + // } + // else + // { + // return Convert.ToInt32(encOffset0 - (((24 - hourval) / 24d) * Tot_enc)); + // } + // } + + //} + + //private int Get_EncoderfromDegrees(double encOffset0, double degval, double Tot_enc, double Pier, int hmspr) + //{ + + // if (hmspr == 1) + // { + // degval = 360 - degval; + // } + // if ((degval > 180) && (Pier == 0)) + // { + // return Convert.ToInt32(encOffset0 - (((360 - degval) / 360d) * Tot_enc)); + // } + // else + // { + // return Convert.ToInt32(((degval / 360d) * Tot_enc) + encOffset0); + // } + + //} + + + private double Get_EncoderDegrees(double DecEncoderPosition) + { + + double decDegrees = 0; + + // Compute in Hours the encoder value based on 0 position value (EncOffset0) + // and Total 360 degree rotation microstep count (Tot_Enc + + if (DecEncoderPosition > this.HomeEncoder.Dec) + { + decDegrees = ((DecEncoderPosition - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 360; + } + else + { + decDegrees = ((this.HomeEncoder.Dec - DecEncoderPosition) / this.StepsPerRev.Dec) * 360; + decDegrees = 360 - decDegrees; + } + + if (this.Hemisphere == HemisphereEnum.Northern) + { + return Range.Range360(decDegrees); + } + else + { + return Range.Range360(360 - decDegrees); + } + } + + //// Function that will ensure that the DEC value will be between -90 to 90 + //// Even if it is set at the other side of the pier + + //private double Range_DEC(double decdegrees) + //{ + + // if ((decdegrees >= 270) && (decdegrees <= 360)) + // { + // return decdegrees - 360; + // } + + // if ((decdegrees >= 180) && (decdegrees < 270)) + // { + // return 180 - decdegrees; + // } + + // if ((decdegrees >= 90) && (decdegrees < 180)) + // { + // return 180 - decdegrees; + // } + + // return decdegrees; + + //} + + + + //internal int Get_RAEncoderfromRA(double ra_in_hours, double dec_in_degrees, double pLongitude, double encOffset0, double Tot_enc, int hmspr) + //{ + + + // double i = ra_in_hours - SiderealTime.GetLocalSiderealTime(SiteLongitude); // EQnow_lst(pLongitude * DEG_RAD); + + // if (hmspr == 0) + // { + // if ((dec_in_degrees > 90) && (dec_in_degrees <= 270)) + // { + // i -= 12d; + // } + // } + // else + // { + // if ((dec_in_degrees > 90) && (dec_in_degrees <= 270)) + // { + // i += 12d; + // } + // } + + // i = Range24(i); + + // return Get_EncoderfromHours(encOffset0, ref i, Tot_enc, hmspr); + + //} + + //private int Get_RAEncoderfromAltAz(double Alt_in_deg, double Az_in_deg, double pLongitude, double pLatitude, double encOffset0, double Tot_enc, int hmspr) + //{ + // object[,,,,] aa_hadec = null; + + // double ttha = 0; + // double ttdec = 0; + + // object tempAuxVar = aa_hadec[Convert.ToInt32(pLatitude * DEG_RAD), Convert.ToInt32(Alt_in_deg * DEG_RAD), Convert.ToInt32((360d - Az_in_deg) * DEG_RAD), Convert.ToInt32(ttha), Convert.ToInt32(ttdec)]; + // double i = (ttha * RAD_HRS); + // i = Range24(i); + // return Get_EncoderfromHours(encOffset0, ref i, Tot_enc, hmspr); + + //} + + //private int Get_DECEncoderfromAltAz(double Alt_in_deg, double Az_in_deg, double pLongitude, double pLatitude, double encOffset0, double Tot_enc, double Pier, int hmspr) + //{ + // object[,,,,] aa_hadec = null; + + // double ttha = 0; + // double ttdec = 0; + + // object tempAuxVar = aa_hadec[Convert.ToInt32(pLatitude * DEG_RAD), Convert.ToInt32(Alt_in_deg * DEG_RAD), Convert.ToInt32((360d - Az_in_deg) * DEG_RAD), Convert.ToInt32(ttha), Convert.ToInt32(ttdec)]; + // double i = ttdec * RAD_DEG; // tDec was in Radians + // if (Pier == 1) + // { + // i = 180 - i; + // } + // return Get_EncoderfromDegrees(encOffset0, ref i, Tot_enc, Pier, hmspr); + + //} + + //private int Get_DECEncoderfromDEC(double dec_in_degrees, double Pier, double encOffset0, double Tot_enc, int hmspr) + //{ + + + // double i = dec_in_degrees; + // if (Pier == 1) + // { + // i = 180 - i; + // } + // return Get_EncoderfromDegrees(encOffset0, ref i, Tot_enc, Pier, hmspr); + + //} + + //private string printhex(double inpval) + //{ + + // return " " + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF00000) / 1048576d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF0000) / 65536d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF000) / 4096d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF00) / 256d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF0) / 16d) & 0xF).ToString("X") + (Convert.ToInt32(inpval) & 0xF).ToString("X"); + + //} + + ////private string FmtSexa(double N, bool ShowPlus) + ////{ + //// string result = ""; + + //// string sg = "+"; // Assume positive + //// if (N < 0) + //// { // Check neg. + //// N = -N; // Make pos. + //// sg = "-"; // Remember sign + //// } + + //// int m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Units (deg or hr) + //// string us = StringsHelper.Format(m, "00"); + + //// N = (N - m) * 60d; + //// m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Minutes + //// string ms = StringsHelper.Format(m, "00"); + + //// N = (N - m) * 60d; + //// m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Minutes + //// string ss = StringsHelper.Format(m, "00"); + + //// result = us + ":" + ms + ":" + ss; + //// if (ShowPlus || (sg == "-")) + //// { + //// result = sg + result; + //// } + + //// return result; + ////} + + ////private double EQnow_lst(double plong) + ////{ + //// object mjd_hr = null; + //// object mjd_day = null; + //// double[] vb_mjd = null; + //// object[, ] obliq = null; + //// double[] radhr = null; + //// object[, ] range = null; + //// object[, , ] utc_gst = null; + //// object[, , ] nut = null; + + //// UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME typTime = new UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME(); + //// double eps = 0; + //// double lst = 0; + //// double deps = 0; + //// double dpsi = 0; + + //// // mjd = vb_mjd(CDbl(Now) + gGPSTimeDelta) + + //// UpgradeSolution1Support.PInvoke.SafeNative.kernel32.GetSystemTime(ref typTime); + //// double mjd = vb_mjd[Convert.ToInt32(DateTime.Now.AddDays(gEQTimeDelta).AddDays(typTime.wMilliseconds / 86400000d).ToOADate())]; + //// object tempAuxVar = utc_gst[ReflectionHelper.GetPrimitiveValue(((Array) mjd_day).GetValue(Convert.ToInt32(mjd))), ReflectionHelper.GetPrimitiveValue(((Array) mjd_hr).GetValue(Convert.ToInt32(mjd))), Convert.ToInt32(lst)]; + //// lst += radhr[Convert.ToInt32(plong)]; + //// object tempAuxVar2 = obliq[Convert.ToInt32(mjd), Convert.ToInt32(eps)]; + //// object tempAuxVar3 = nut[Convert.ToInt32(mjd), Convert.ToInt32(deps), Convert.ToInt32(dpsi)]; + //// lst += radhr[Convert.ToInt32(dpsi * Math.Cos(eps + deps))]; + //// object tempAuxVar4 = range[Convert.ToInt32(lst), 24L]; + + //// return lst; + //// // EQnow_lst = now_lst(plong) + + ////} + + + ////private double EQnow_lst_norange() + ////{ + + //// UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME typTime = new UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME(); + + //// UpgradeSolution1Support.PInvoke.SafeNative.kernel32.GetSystemTime(ref typTime); + //// double mjd = (typTime.wMinute * 60) + (typTime.wSecond) + (typTime.wMilliseconds / 1000d); + //// double MTMP = (typTime.wHour); + //// MTMP *= 3600; + //// mjd = mjd + MTMP + (typTime.wDay * 86400); + + //// return mjd; + + ////} + + + ////private double EQnow_lst_time(double plong, double ptime) + ////{ + //// object mjd_hr = null; + //// object mjd_day = null; + //// double[] vb_mjd = null; + //// object[, ] obliq = null; + //// double[] radhr = null; + //// object[, ] range = null; + //// object[, , ] utc_gst = null; + //// object[, , ] nut = null; + + //// double eps = 0; + //// double lst = 0; + //// double deps = 0; + //// double dpsi = 0; + + //// double mjd = vb_mjd[Convert.ToInt32(ptime)]; + //// object tempAuxVar = utc_gst[ReflectionHelper.GetPrimitiveValue(((Array) mjd_day).GetValue(Convert.ToInt32(mjd))), ReflectionHelper.GetPrimitiveValue(((Array) mjd_hr).GetValue(Convert.ToInt32(mjd))), Convert.ToInt32(lst)]; + //// lst += radhr[Convert.ToInt32(plong)]; + //// object tempAuxVar2 = obliq[Convert.ToInt32(mjd), Convert.ToInt32(eps)]; + //// object tempAuxVar3 = nut[Convert.ToInt32(mjd), Convert.ToInt32(deps), Convert.ToInt32(dpsi)]; + //// lst += radhr[Convert.ToInt32(dpsi * Math.Cos(eps + deps))]; + //// object tempAuxVar4 = range[Convert.ToInt32(lst), 24L]; + + //// return lst; + + ////} + + + //private PierSide2 SOP_DEC(double DEC) + //{ + + // DEC = Math.Abs(DEC - 180); + + // if (DEC <= 90) + // { + // return PierSide2.PierEast2; + // } + // else + // { + // return PierSide2.PierWest2; + // } + + //} + + ////private PierSide2 SOP_Physical(double vha) + ////{ + //// object gAscomCompatibility = null; + + //// double ha = RangeHA(vha - 6d); + + //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPhysicalSideOfPier")) + //// { + //// return (ha >= 0) ? PierSide2.PierWest2 : PierSide2.PierEast2; + //// } + //// else + //// { + //// return (ha >= 0) ? PierSide2.PierEast2 : PierSide2.PierWest2; + //// } + + + + ////} + + ////private PierSide2 SOP_Pointing(double DEC) + ////{ + //// PierSide2 result = PierSide2.PierEast2; + //// object gAscomCompatibility = null; + + //// if (DEC <= 90 || DEC >= 270) + //// { + //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPointingSideOfPier")) + //// { + //// result = PierSide2.PierEast2; + //// } + //// else + //// { + //// result = PierSide2.PierWest2; + //// } + //// } + //// else + //// { + //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPointingSideOfPier")) + //// { + //// result = PierSide2.PierWest2; + //// } + //// else + //// { + //// result = PierSide2.PierEast2; + //// } + //// } + + //// // in the south east is west and west is east! + //// if (gHemisphere == 1) + //// { + //// if (result == PierSide2.PierWest2) + //// { + //// result = PierSide2.PierEast2; + //// } + //// else + //// { + //// result = PierSide2.PierWest2; + //// } + //// } + + //// return result; + ////} + ////private PierSide2 SOP_RA(double vRA, double pLongitude) + ////{ + + //// double i = vRA - EQnow_lst(pLongitude * DEG_RAD); + //// i = RangeHA(i - 6d); + //// return (i < 0) ? PierSide2.PierEast2 : PierSide2.PierWest2; + + ////} + + //private double Range24(double vha) + //{ + + // while (vha < 0d) + // { + // vha += 24d; + // } + // while (vha >= 24d) + // { + // vha -= 24d; + // } + + // return vha; + + //} + + //private double Range360(double vdeg) + //{ + + // while (vdeg < 0d) + // { + // vdeg += 360d; + // } + // while (vdeg >= 360d) + // { + // vdeg -= 360d; + // } + + // return vdeg; + + //} + //private double Range90(double vdeg) + //{ + + // while (vdeg < -90d) + // { + // vdeg += 360d; + // } + // while (vdeg >= 360d) + // { + // vdeg -= 90d; + // } + + // return vdeg; + + //} + + + //private double GetSlowdown(double deltaval) + //{ + + // double i = deltaval - 80000; + // if (i < 0) + // { + // i = deltaval * 0.5d; + // } + // return i; + + //} + + //private double Delta_RA_Map(double RAENCODER) + //{ + + // return RAENCODER + gRA1Star + gRASync01; + + //} + + //private double Delta_DEC_Map(double DecEncoder) + //{ + + // return DecEncoder + gDEC1Star + gDECSync01; + + //} + + + //private Coordt Delta_Matrix_Map(double RA, double DEC) + //{ + // Coordt result = new Coordt(); + // Coord obtmp = new Coord(); + + // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) + // { + // result.x = RA; + // result.y = DEC; + // result.z = 1; + // result.f = 0; + // return result; + // } + + // obtmp.x = RA; + // obtmp.y = DEC; + // obtmp.z = 1; + + // // re transform based on the nearest 3 stars + // int i = EQ_UpdateTaki(RA, DEC); + + // Coord obtmp2 = EQ_plTaki(obtmp); + + // result.x = obtmp2.x; + // result.y = obtmp2.y; + // result.z = 1; + // result.f = (short)i; + + // return result; + //} + + + //private Coordt Delta_Matrix_Reverse_Map(double RA, double DEC) + //{ + + // Coordt result = new Coordt(); + // Coord obtmp = new Coord(); + + // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) + // { + // result.x = RA; + // result.y = DEC; + // result.z = 1; + // result.f = 0; + // return result; + // } + + // obtmp.x = RA + gRASync01; + // obtmp.y = DEC + gDECSync01; + // obtmp.z = 1; + + // // re transform using the 3 nearest stars + // int i = EQ_UpdateAffine(obtmp.x, obtmp.y); + // Coord obtmp2 = EQ_plAffine(obtmp); + + // result.x = obtmp2.x; + // result.y = obtmp2.y; + // result.z = 1; + // result.f = (short)i; + + + // return result; + //} + + + //private Coordt DeltaSync_Matrix_Map(double RA, double DEC) + //{ + // Coordt result = new Coordt(); + // int i = 0; + + // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) + // { + // result.x = RA; + // result.y = DEC; + // result.z = 0; + // result.f = 0; + // } + // else + // { + // i = GetNearest(RA, DEC); + // if (i != -1) + // { + // EQASCOM.gSelectStar = i; + // result.x = RA + (EQASCOM.ct_Points[i].x - EQASCOM.my_Points[i].x) + gRASync01; + // result.y = DEC + (EQASCOM.ct_Points[i].y - EQASCOM.my_Points[i].y) + gDECSync01; + // result.z = 1; + // result.f = 0; + // } + // else + // { + // result.x = RA; + // result.y = DEC; + // result.z = 0; + // result.f = 0; + // } + // } + // return result; + //} + + + //private Coordt DeltaSyncReverse_Matrix_Map(double RA, double DEC) + //{ + // Coordt result = new Coordt(); + // int i = 0; + + // if ((RA >= 0x1000000) || (DEC >= 0x1000000) || EQASCOM.gAlignmentStars_count == 0) + // { + // result.x = RA; + // result.y = DEC; + // result.z = 1; + // result.f = 0; + // } + // else + // { + // i = GetNearest(RA, DEC); + + // if (i != -1) + // { + // EQASCOM.gSelectStar = i; + // result.x = RA - (EQASCOM.ct_Points[i].x - EQASCOM.my_Points[i].x); + // result.y = DEC - (EQASCOM.ct_Points[i].y - EQASCOM.my_Points[i].y); + // result.z = 1; + // result.f = 0; + // } + // else + // { + // result.x = RA; + // result.y = DEC; + // result.z = 1; + // result.f = 0; + // } + // } + // return result; + //} + //private int GetQuadrant(Coord tmpcoord) + //{ + // int ret = 0; + + // if (tmpcoord.x >= 0) + // { + // if (tmpcoord.y >= 0) + // { + // ret = 0; + // } + // else + // { + // ret = 1; + // } + // } + // else + // { + // if (tmpcoord.y >= 0) + // { + // ret = 2; + // } + // else + // { + // ret = 3; + // } + // } + + // return ret; + + //} + + + //private int GetNearest(double RA, double DEC) + //{ + // int i = 0; + // Coord tmpcoord = new Coord(); + // Coord tmpcoord2 = new Coord(); + // double[] datholder = new double[EQASCOM.MAX_STARS]; + // int[] datholder2 = new int[EQASCOM.MAX_STARS]; + + // tmpcoord.x = RA; + // tmpcoord.y = DEC; + // tmpcoord = EQ_sp2Cs(tmpcoord); + + // int Count = 0; + + // for (i = 1; i <= EQASCOM.gAlignmentStars_count; i++) + // { + + // tmpcoord2 = EQASCOM.my_PointsC[i]; + + // switch (ActivePoints) + // { + // case ActivePointsEnum.All: + // // all points + + // break; + // case ActivePointsEnum.PierSide: + // // only consider points on this side of the meridian + // if (tmpcoord2.y * tmpcoord.y < 0) + // { + // goto NextPoint; + // } + + // break; + // case ActivePointsEnum.LocalQuadrant: + // // local quadrant + // if (GetQuadrant(tmpcoord) != GetQuadrant(tmpcoord2)) + // { + // goto NextPoint; + // } + + // break; + // } + + // Count++; + // if (CheckLocalPier) + // { + // // calculate polar distance + // datholder[Count - 1] = Math.Pow(EQASCOM.my_Points[i].x - RA, 2) + Math.Pow(EQASCOM.my_Points[i].y - DEC, 2); + // } + // else + // { + // // calculate cartesian disatnce + // datholder[Count - 1] = Math.Pow(tmpcoord2.x - tmpcoord.x, 2) + Math.Pow(tmpcoord2.y - tmpcoord.y, 2); + // } + + // datholder2[Count - 1] = i; + + // NextPoint:; + // } + + // if (Count == 0) + // { + // return -1; + // } + // else + // { + // // i = EQ_FindLowest(datholder(), 1, gAlignmentStars_count) + // i = EQ_FindLowest(datholder, 1, Count); + // if (i == -1) + // { + // return -1; + // } + // else + // { + // return datholder2[i - 1]; + // } + // } + + //} + + + } +} + + diff --git a/EQMODAlignment/Model/AlignmentPoint.cs b/EQMODAlignment/Model/AlignmentPoint.cs new file mode 100644 index 00000000..933bdafa --- /dev/null +++ b/EQMODAlignment/Model/AlignmentPoint.cs @@ -0,0 +1,83 @@ +using EqmodNStarAlignment.DataTypes; +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; +using System.Text; + +namespace EqmodNStarAlignment.Model +{ + public class AlignmentPoint + { + /// + /// Unique ID for alignment point + /// + public int Id { get; set; } + + /// + /// Alignment date and time of the sync + /// + public DateTime AlignTime { get;set;} + + /// + /// The Encoder positions at sync time + /// + public EncoderPosition Encoder { get;set;} + + /// + /// The Cartesian equivalent of the EncoderPosition + /// + public Coord EncoderCartesian { get; set;} + + + /// + /// The Target Ra/Dec in hours/degrees + /// + public AxisPosition OrigRaDec { get;set;} + + + /// + /// The unadjusted encoder positions + /// + public EncoderPosition Target { get;set;} + + /// + /// The cartesean version of the unadjusted encoder positions + /// + [JsonIgnore] + public Coord TargetCartesian { get; set;} + + public EncoderPosition Delta => (Target - Encoder); + + public AlignmentPoint(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) + { + Encoder = new EncoderPosition(encoder); + OrigRaDec = new AxisPosition(origRaDec); + Target = new EncoderPosition(target); + + } + + } + + public class AlignmentPointCollection : ObservableCollection + { + protected override void InsertItem(int index, AlignmentPoint item) + { + if (item != null && item.Id == 0) + { + if (Items.Any()) + { + item.Id = Items.Max(i => i.Id) + 1; + } + else + { + item.Id = 1; + } + } + base.InsertItem(index, item); + } + + + } +} diff --git a/EQMODAlignment/Utilities/AstroConvert.cs b/EQMODAlignment/Utilities/AstroConvert.cs new file mode 100644 index 00000000..66cdcfc0 --- /dev/null +++ b/EQMODAlignment/Utilities/AstroConvert.cs @@ -0,0 +1,208 @@ +/* +MIT License + +Copyright (c) 2017 Phil Crompton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + Portions + Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +using System; + +namespace EqmodNStarAlignment.Utilities +{ + + public class AstroConvert + { + /// + /// Radians per degree + /// + private const double DegRad = 0.0174532925; // Radians per degree + /// + /// Degrees per radian + /// + private const double RadDeg = 57.2957795; // Degrees per Radian + + /// + /// Radians per hour + /// + private const double HrsRad = 0.2617993881; // Radians per hour + + #region Unit convertsions ... + + public static double DegToRad(double degrees) { return (degrees * DegRad); } + public static double HrsToRad(double hours) { return (hours * HrsRad); } + + public static double RadToHrs(double radians) { return (radians / HrsRad); } + + public static double RadToDeg(double rad) { return (rad * RadDeg); } + + #endregion + + /// + /// Right Ascension to Local 12 Hour Angles + /// + /// + /// The hour angle (HA) of an object is equal to the difference between + /// the current local sidereal time (LST) and the right ascension of that object. + /// Adopted from ASCOM + /// + /// In decimal hours + /// In decimal hours + /// Local Hour Angles in decimal hours + public static double Ra2Ha12(double rightAscension, double localSiderealTime) + { + var a = localSiderealTime - rightAscension; + var ra2Ha = Range.Range12(a); + return ra2Ha; + } + + + /// + /// Right Ascension and Declination to Altitude and Azimuth + /// Adopted from ASCOM + /// + /// In decimal hours + /// In decimal degrees + /// In decimal hours + /// In decimal degrees + /// Array of Azimuth, Altitude in decimal degrees + public static double[] RaDec2AltAz(double rightAscension, double declination, double localSiderealTime, double latitude) + { + var a = Ra2Ha12(rightAscension, localSiderealTime); + var raDec2AltAz = HaDec2AltAz(a, declination, latitude); + return raDec2AltAz; + } + + /// + /// Hour Angles and Declination to Altitude and Azimuth + /// Adopted from ASCOM + /// + /// Local Hour angle + /// In decimal degrees + /// In decimal degrees + /// Array of Azimuth, Altitude in decimal degrees + public static double[] HaDec2AltAz(double hourAngle, double declination, double latitude) + { + double a = HrsToRad(hourAngle); + double b = DegToRad(declination); + double c = DegToRad(latitude); + double d = Math.Sin(a); + double e = Math.Cos(a); + double f = Math.Sin(b); + double g = Math.Cos(b); + double h = Math.Sin(c); + double i = Math.Cos(c); + double j = f * i - e * g * h; + double k = -(d * g); + double l = e * g * i + f * h; + double m = Math.Sqrt(j * j + k * k); + double n = RadToDeg(Math.Atan2(k, j)); + double o = RadToDeg(Math.Atan2(l, m)); + double p = Range.Range360(n); + double q = Range.Range90(o); + double[] altAz = { q, p }; + return altAz; + } + + /// + /// Azimuth and Altitude to Right Ascension and Declination + /// + /// In decimal degrees + /// In decimal degrees + /// In decimal degrees + /// In decimal hours + /// Ra in decimal hours, Dec in decimal degrees + public static double[] AltAz2RaDec(double altitude, double azimuth, double latitude, double lst) + { + var a = AltAz2Ra(altitude, azimuth, latitude, lst); + var b = AltAz2Dec(altitude, azimuth, latitude); + var altAz2RaDec = new[] { a, b }; + return altAz2RaDec; + } + + /// + /// Azimuth and Altitude to Declination + /// Adopted from ASCOM + /// + /// In decimal degrees + /// In decimal degrees + /// In decimal degrees + /// Declination in decimal degrees + public static double AltAz2Dec(double altitude, double azimuth, double latitude) + { + var a = DegToRad(azimuth); + var b = DegToRad(altitude); + var c = DegToRad(latitude); + //var d = Math.Sin(a); + var e = Math.Cos(a); + var f = Math.Sin(b); + var g = Math.Cos(b); + var h = Math.Sin(c); + var i = Math.Cos(c); + var j = e * i * g + h * f; + var k = RadToDeg(Math.Asin(j)); + var altAz2Dec = Range.Range90(k); + return altAz2Dec; + } + + /// + /// Azimuth and Altitude to Right Ascension + /// Adopted from ASCOM + /// + /// In decimal degrees + /// In decimal degrees + /// In decimal degrees + /// In decimal hours + /// Right Ascension in decimal hours + public static double AltAz2Ra(double altitude, double azimuth, double latitude, double lst) + { + var a = DegToRad(azimuth); + var b = DegToRad(altitude); + var c = DegToRad(latitude); + var d = Math.Sin(a); + var e = Math.Cos(a); + var f = Math.Sin(b); + var g = Math.Cos(b); + var h = Math.Sin(c); + var i = Math.Cos(c); + var j = -d * g; + var k = -e * h * g + f * i; + var l = RadToHrs(Math.Atan2(j, k)); + var altAz2Ra = Range.Range24(lst - l); + return altAz2Ra; + } + } +} diff --git a/EQMODAlignment/Utilities/EnumTypeConverter.cs b/EQMODAlignment/Utilities/EnumTypeConverter.cs new file mode 100644 index 00000000..7e2a1cb2 --- /dev/null +++ b/EQMODAlignment/Utilities/EnumTypeConverter.cs @@ -0,0 +1,57 @@ +using System; +using System.ComponentModel; +using System.Globalization; +using System.Reflection; + +namespace EqmodNStarAlignment.Utilities +{ + public class EnumTypeConverter : EnumConverter + { + private Type m_EnumType; + public EnumTypeConverter(Type type) + : base(type) + { + m_EnumType = type; + } + + public override bool CanConvertTo(ITypeDescriptorContext context, Type destType) + { + return destType == typeof(string); + } + + public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType) + { + DescriptionAttribute dna = null; + if (value != null) + { + FieldInfo fi = m_EnumType.GetField(Enum.GetName(m_EnumType, value)); + dna = + (DescriptionAttribute)Attribute.GetCustomAttribute( + fi, typeof(DescriptionAttribute)); + } + if (dna != null) + return dna.Description; + else + return (value != null ? value.ToString() : ""); + } + + public override bool CanConvertFrom(ITypeDescriptorContext context, Type srcType) + { + return srcType == typeof(string); + } + + public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) + { + foreach (FieldInfo fi in m_EnumType.GetFields()) + { + DescriptionAttribute dna = + (DescriptionAttribute)Attribute.GetCustomAttribute( + fi, typeof(DescriptionAttribute)); + + if ((dna != null) && ((string)value == dna.Description)) + return Enum.Parse(m_EnumType, fi.Name); + } + return Enum.Parse(m_EnumType, (string)value ?? string.Empty); + } + } +} diff --git a/EQMODAlignment/Utilities/Range.cs b/EQMODAlignment/Utilities/Range.cs new file mode 100644 index 00000000..ee5b27d8 --- /dev/null +++ b/EQMODAlignment/Utilities/Range.cs @@ -0,0 +1,121 @@ +/* Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com), + Phil Crompton (phil@unitysoftware.co.uk) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +namespace EqmodNStarAlignment.Utilities +{ + /// + /// Forces parameters to be within a certain range + /// + /// Attention to the order of parameters (AltAz vs AzAlt) in the method names + public static class Range + { + /// + /// Returns double in the range -12 to +12 + /// + /// 90.169444444444451 + /// -5.8305555555555486 + public static double Range12(double d) + { + while ((d > 12.0) || (d <= -12.0)) + { + if (d <= -12.0) d += 24.0; + if (d > 12.0) d -= 24.0; + } + return d; + } + + /// + /// Returns double in the range 0 to 24.0 + /// + /// 90.169444444444451 + /// 18.169444444444451 + public static double Range24(double d) + { + while ((d >= 24.0) || (d < 0.0)) + { + if (d < 0.0) d += 24.0; + if (d >= 24.0) d -= 24.0; + } + return d; + } + + /// + /// Returns double in the range -90 to 90 + /// + /// 90.169444444444451 + /// 89.830555555555549 + public static double Range90(double d) + { + while ((d > 90.0) || (d < -90.0)) + { + if (d < -90.0) d += 180.0; + if (d > 90.0) d = 180.0 - d; + } + return d; + } + + /// + /// Returns double in the range 0 to 360 + /// + /// 590.169444444444451 + /// 230.16944444444448 + public static double Range360(double d) + { + while ((d >= 360.0) || (d < 0.0)) + { + if (d < 0.0) d += 360.0; + if (d >= 360.0) d -= 360.0; + } + return d; + } + + /// + /// Returns double in the range -180 to 180 + /// + /// 590.169444444444451 + /// 230.16944444444448 + public static double RangePlusOrMinus180(double d) + { + while (d <= 180.0) + { + d = d + 360.0; + } + + while (d > 180) + { + d = d - 360.0; + } + return d; + } + + public static double RangeHa(double ha) + { + + while (ha < -12d) + { + ha += 24d; + } + while (ha >= 12d) + { + ha -= 24d; + } + + return ha; + + } + + } +} diff --git a/EQMODAlignment/Utilities/SiderealTime.cs b/EQMODAlignment/Utilities/SiderealTime.cs new file mode 100644 index 00000000..75ff83a0 --- /dev/null +++ b/EQMODAlignment/Utilities/SiderealTime.cs @@ -0,0 +1,22 @@ +using GS.Principles; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.Utilities +{ + public static class SiderealTime + { + public static double GetLocalSiderealTime(double longitude) + { + return GetLocalSiderealTime(HiResDateTime.UtcNow, longitude); + } + + public static double GetLocalSiderealTime(DateTime utcNow, double longitude) + { + var gsjd = JDate.Ole2Jd(utcNow); + return Time.Lst(JDate.Epoch2000Days(), gsjd, false, longitude); + } + + } +} diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj new file mode 100644 index 00000000..571a88cf --- /dev/null +++ b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj @@ -0,0 +1,69 @@ + + + + + + Debug + AnyCPU + {A546006B-D866-41B9-B378-F0666F18618C} + Library + Properties + EqmodNStarAlignment.Tests + EqmodNStarAlignment.Tests + v4.7.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 15.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll + + + ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll + + + + + + + + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs b/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..3278a883 --- /dev/null +++ b/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs @@ -0,0 +1,20 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +[assembly: AssemblyTitle("EqmodNStarAlignment.Tests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EqmodNStarAlignment.Tests")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +[assembly: ComVisible(false)] + +[assembly: Guid("a546006b-d866-41b9-b378-f0666f18618c")] + +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/EqmodNStarAlignment.Tests/UnitTest1.cs b/EqmodNStarAlignment.Tests/UnitTest1.cs new file mode 100644 index 00000000..e30b9044 --- /dev/null +++ b/EqmodNStarAlignment.Tests/UnitTest1.cs @@ -0,0 +1,14 @@ +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace EqmodNStarAlignment.Tests +{ + [TestClass] + public class UnitTest1 + { + [TestMethod] + public void TestMethod1() + { + } + } +} diff --git a/EqmodNStarAlignment.Tests/packages.config b/EqmodNStarAlignment.Tests/packages.config new file mode 100644 index 00000000..5230bc10 --- /dev/null +++ b/EqmodNStarAlignment.Tests/packages.config @@ -0,0 +1,5 @@ + + + + + \ No newline at end of file diff --git a/GS.Ascom.SkyTelescope/CommandStrings.cs b/GS.Ascom.SkyTelescope/CommandStrings.cs index bdd157a6..1f9932ca 100644 --- a/GS.Ascom.SkyTelescope/CommandStrings.cs +++ b/GS.Ascom.SkyTelescope/CommandStrings.cs @@ -11,12 +11,12 @@ public static string ProcessCommand(string command, bool raw) //if (raw) { throw new DriverException("Raw param error"); } if (command.Length < 2) { throw new DriverException("Command length error"); } if (!command.Contains(":")) { throw new DriverException("Command colon error"); } - + // case statement for the mount commands - switch (command.Substring(0,2)) + switch (command.Substring(0, 2)) { case ":O":// Trigger Snap Port - if (command.Length != 4){ throw new DriverException("Param Cmd error"); } + if (command.Length != 4) { throw new DriverException("Param Cmd error"); } switch (command.Substring(2, 1)) { case "1": //Port 1 @@ -37,6 +37,7 @@ public static string ProcessCommand(string command, bool raw) SkyServer.SimTasks(MountTaskName.SetSnapPort1); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort1); break; default: @@ -61,6 +62,7 @@ public static string ProcessCommand(string command, bool raw) SkyServer.SimTasks(MountTaskName.SetSnapPort2); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort2); break; default: diff --git a/GS.Ascom.SkyTelescope/Telescope.cs b/GS.Ascom.SkyTelescope/Telescope.cs index c65284cf..e8bc6e19 100644 --- a/GS.Ascom.SkyTelescope/Telescope.cs +++ b/GS.Ascom.SkyTelescope/Telescope.cs @@ -93,9 +93,12 @@ public string Action(string ActionName, string ActionParameters) var monitorItem = new MonitorEntry { - Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, - Category = MonitorCategory.Driver, Type = MonitorType.Information, - Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, + Datetime = HiResDateTime.UtcNow, + Device = MonitorDevice.Server, + Category = MonitorCategory.Driver, + Type = MonitorType.Information, + Method = MethodBase.GetCurrentMethod()?.Name, + Thread = Thread.CurrentThread.ManagedThreadId, Message = $" ActionName:{ActionName}, ActionParameters:'{ActionParameters}'" }; MonitorLog.LogToMonitor(monitorItem); @@ -104,7 +107,7 @@ public string Action(string ActionName, string ActionParameters) { // ReSharper disable once StringLiteralTypo case string str when str.Equals("telescope:setparkposition", StringComparison.InvariantCultureIgnoreCase): - if (SkyServer.IsMountRunning == false){throw new NotConnectedException("Mount Not Connected");} + if (SkyServer.IsMountRunning == false) { throw new NotConnectedException("Mount Not Connected"); } var found = SkySettings.ParkPositions.Find(x => string.Equals(x.Name, ActionParameters, StringComparison.InvariantCultureIgnoreCase)); if (found == null) { @@ -132,7 +135,7 @@ public ArrayList SupportedActions MonitorLog.LogToMonitor(monitorItem); // ReSharper disable once StringLiteralTypo - var sa = new ArrayList {@"Telescope:SetParkPosition"}; + var sa = new ArrayList { @"Telescope:SetParkPosition" }; return sa; } @@ -538,7 +541,7 @@ public string CommandString(string Command, bool Raw) try { var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{Command},{Raw}") }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{Command},{Raw}") }; MonitorLog.LogToMonitor(monitorItem); if (string.IsNullOrWhiteSpace(Command)) { throw new MethodNotImplementedException("CommandString"); } @@ -583,7 +586,7 @@ public bool Connected } } - public double Declination + public double Declination { get { @@ -620,7 +623,7 @@ public double DeclinationRate } } - public string Description + public string Description { get { @@ -921,7 +924,7 @@ public void PulseGuide(GuideDirections Direction, int Duration) } var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Data, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{Direction},{Duration}") }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Data, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{Direction},{Duration}") }; MonitorLog.LogToMonitor(monitorItem); if (!SkyServer.AsComOn) { throw new InvalidOperationException("Not accepting commands"); } @@ -942,7 +945,7 @@ public void PulseGuide(GuideDirections Direction, int Duration) SkyServer.IsPulseGuidingRa = false; SkyServer.IsPulseGuidingDec = false; var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Warning, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{e.Message}") }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Warning, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = FormattableString.Invariant($"{e.Message}") }; MonitorLog.LogToMonitor(monitorItem); throw; } @@ -1028,11 +1031,11 @@ public void SetupDialog() while (true) { Thread.Sleep(100); - if (SkyServer.OpenSetupDialogFinished){break;} + if (SkyServer.OpenSetupDialogFinished) { break; } } monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"Open:{SkyServer.OpenSetupDialog}, Finished:{SkyServer.OpenSetupDialogFinished}" }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"Open:{SkyServer.OpenSetupDialog}, Finished:{SkyServer.OpenSetupDialogFinished}" }; MonitorLog.LogToMonitor(monitorItem); } @@ -1549,8 +1552,8 @@ public DateTime UTCDate { get { - // var r = HiResDateTime.UtcNow.Add(SkySettings.UTCDateOffset); - var r = HiResDateTime.UtcNow; + // var r = HiResDateTime.UtcNow.Add(SkySettings.UTCDateOffset); + var r = HiResDateTime.UtcNow; var monitorItem = new MonitorEntry { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Data, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{r}" }; @@ -1626,7 +1629,7 @@ private static void CheckTrackingRate(string propertyOrMethod, DriveRates enumVa throw new InvalidValueException("TrackingRate invalid"); } - + private void CheckRate(TelescopeAxes axis, double rate) { var monitorItem = new MonitorEntry @@ -1756,7 +1759,7 @@ private static void CheckParked(string property) private static void CheckRate(double rate) { var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{rate}" }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Driver, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{rate}" }; MonitorLog.LogToMonitor(monitorItem); if (rate > SkyServer.SlewSpeedEight || rate < -SkyServer.SlewSpeedEight) @@ -1848,6 +1851,7 @@ private static void DelayInterval(int additional = 0) delay += SkySettings.DisplayInterval; break; case MountType.SkyWatcher: + case MountType.AstroEQ: delay += 20; // some go tos have been off .10 to .70 seconds, not sure exactly why delay += SkySettings.DisplayInterval; break; @@ -1865,12 +1869,12 @@ private static void DelayInterval(int additional = 0) /// planetarium programs fix which doesn't turn on tracking before a goto private static void CycleOnTracking(bool silence) { - if (silence){SkyServer.TrackingSpeak = false;} + if (silence) { SkyServer.TrackingSpeak = false; } - SkyServer.Tracking = false; + SkyServer.Tracking = false; SkyServer.Tracking = true; - if(silence){ SkyServer.TrackingSpeak = true;} + if (silence) { SkyServer.TrackingSpeak = true; } } #endregion diff --git a/GS.Server/Alignment/AlignmentV.xaml b/GS.Server/Alignment/AlignmentV.xaml index 8986e0ab..7845b8e4 100644 --- a/GS.Server/Alignment/AlignmentV.xaml +++ b/GS.Server/Alignment/AlignmentV.xaml @@ -203,12 +203,12 @@ - - - - - - + + + + + + diff --git a/GS.Server/Alignment/AlignmentVM.cs b/GS.Server/Alignment/AlignmentVM.cs index ceaa97b4..a16b6ca9 100644 --- a/GS.Server/Alignment/AlignmentVM.cs +++ b/GS.Server/Alignment/AlignmentVM.cs @@ -23,7 +23,7 @@ You should have received a copy of the GNU General Public License using GS.Shared.Command; using GS.Utilities.Controls.Dialogs; using MaterialDesignThemes.Wpf; -using NStarAlignment.DataTypes; +using EqmodNStarAlignment.DataTypes; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -39,6 +39,7 @@ You should have received a copy of the GNU General Public License using MessageBox = System.Windows.MessageBox; using OpenFileDialog = Microsoft.Win32.OpenFileDialog; using SaveFileDialog = Microsoft.Win32.SaveFileDialog; +using EqmodNStarAlignment.Model; namespace GS.Server.Alignment { diff --git a/GS.Server/Focuser/FocuserVM.cs b/GS.Server/Focuser/FocuserVM.cs index b3e6ec41..b2347e69 100644 --- a/GS.Server/Focuser/FocuserVM.cs +++ b/GS.Server/Focuser/FocuserVM.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License using NINA.Model.MyFocuser; using NINA.Utility; using NINA.ViewModel.Equipment.Focuser; -using NStarAlignment.Utilities; +using EqmodNStarAlignment.Utilities; using System; using System.ComponentModel; using System.Reflection; diff --git a/GS.Server/GS.Server.csproj b/GS.Server/GS.Server.csproj index 4e4175cf..c8bc8239 100644 --- a/GS.Server/GS.Server.csproj +++ b/GS.Server/GS.Server.csproj @@ -77,6 +77,7 @@ false + false @@ -92,7 +93,6 @@ - diff --git a/GS.Server/SkyTelescope/Axes.cs b/GS.Server/SkyTelescope/Axes.cs index a2f39fe3..0404bc74 100644 --- a/GS.Server/SkyTelescope/Axes.cs +++ b/GS.Server/SkyTelescope/Axes.cs @@ -69,6 +69,7 @@ internal static double[] AxesAppToMount(double[] axes) } break; case MountType.SkyWatcher: + case MountType.AstroEQ: if (SkyServer.SouthernHemisphere) { a[0] = 180 - a[0]; @@ -113,6 +114,7 @@ internal static double[] AxesMountToApp(double[] axes) break; case MountType.SkyWatcher: + case MountType.AstroEQ: if (SkyServer.SouthernHemisphere) { a[0] = a[0] * -1.0; @@ -310,7 +312,7 @@ internal static double[] AxesXYToRaDec(double[] axes) { return AxesXYToRaDec(axes, SkyServer.SiderealTime); } - + /// /// convert a RaDec position to an axes positions. /// diff --git a/GS.Server/SkyTelescope/Enums.cs b/GS.Server/SkyTelescope/Enums.cs index 2c4b6292..d098bbbe 100644 --- a/GS.Server/SkyTelescope/Enums.cs +++ b/GS.Server/SkyTelescope/Enums.cs @@ -119,7 +119,8 @@ public enum MountTaskName public enum MountType { Simulator, - SkyWatcher + SkyWatcher, + AstroEQ } public enum ErrorCode diff --git a/GS.Server/SkyTelescope/SkyServer.cs b/GS.Server/SkyTelescope/SkyServer.cs index 0e883423..564415e7 100644 --- a/GS.Server/SkyTelescope/SkyServer.cs +++ b/GS.Server/SkyTelescope/SkyServer.cs @@ -22,7 +22,7 @@ You should have received a copy of the GNU General Public License using GS.Shared; using GS.Simulator; using GS.SkyWatcher; -using NStarAlignment.Model; +using EqmodNStarAlignment.Model; using System; using System.Collections.Generic; using System.ComponentModel; @@ -119,11 +119,12 @@ static SkyServer() SkySettings.Latitude, SkySettings.Longitude, SkySettings.Elevation, + new EqmodNStarAlignment.DataTypes.EncoderPosition(SkyServer.StepsPerRevolution[0], SkyServer.StepsPerRevolution[1]), AlignmentSettings.ClearModelOnStartup) { IsAlignmentOn = (AlignmentShow && AlignmentSettings.IsAlignmentOn) }; - AlignmentModel.SetHomePosition(_homeAxes.X, _homeAxes.Y); + AlignmentModel.SetHomePosition(0, 0); AlignmentModel.Notification += AlignmentModel_Notification; // attach handler to watch for SkySettings changing. @@ -437,6 +438,7 @@ public static double RateRa _ = new CmdRate(0, Axis.Axis1, _rateRaDec.X); break; case MountType.SkyWatcher: + case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -562,6 +564,7 @@ public static bool IsMountRunning _mountRunning = MountQueue.IsRunning; break; case MountType.SkyWatcher: + case MountType.AstroEQ: _mountRunning = SkyQueue.IsRunning; break; } @@ -819,6 +822,7 @@ public static double RateAxisDec _ = new CmdRateAxis(0, Axis.Axis2, _rateAxes.Y); break; case MountType.SkyWatcher: + case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis2, rate.Y); break; @@ -871,6 +875,7 @@ public static double RateAxisRa _ = new CmdRateAxis(0, Axis.Axis1, _rateAxes.X); break; case MountType.SkyWatcher: + case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -908,6 +913,7 @@ public static double RateDec _ = new CmdRate(0, Axis.Axis2, _rateRaDec.Y); break; case MountType.SkyWatcher: + case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -992,7 +998,7 @@ public static PierSide SideOfPier Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Server, - Type = MonitorType.Information, + Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{value}|{SkySettings.HourAngleLimit}|{b[0]}|{b[1]}" @@ -1134,7 +1140,7 @@ public static bool Tracking get => _trackingMode != TrackingMode.Off; set { - if (value == _tracking){return;} //off + if (value == _tracking) { return; } //off var monitorItem = new MonitorEntry { @@ -1152,7 +1158,7 @@ public static bool Tracking { if (AtPark) { - if (TrackingSpeak){Synthesizer.Speak(Application.Current.Resources["vceParked"].ToString());} + if (TrackingSpeak) { Synthesizer.Speak(Application.Current.Resources["vceParked"].ToString()); } throw new ASCOM.ParkedException(Application.Current.Resources["exParked"].ToString()); } @@ -1445,6 +1451,7 @@ public static void SimTasks(MountTaskName taskName) switch (SkySettings.Mount) { case MountType.SkyWatcher: + case MountType.AstroEQ: break; case MountType.Simulator: switch (taskName) @@ -1594,9 +1601,9 @@ private static void CalcCustomTrackingOffset() _trackingOffsetRate = new Vector(0.0, 0.0); //calculate mount sidereal :I, add offset to :I, Calculate new rate, Add rate difference to rate - if (SkySettings.Mount != MountType.SkyWatcher){return;} //only use for sky watcher mounts + if (SkySettings.Mount != MountType.SkyWatcher) { return; } //only use for sky watcher mounts - if (SkySettings.CustomGearing == false) {return;} + if (SkySettings.CustomGearing == false) { return; } var ratioFactor = (double)StepsTimeFreq[0] / StepsPerRevolution[0] * 1296000.0; //generic factor for calc var siderealI = ratioFactor / _siderealRate; @@ -1611,7 +1618,7 @@ private static void CalcCustomTrackingOffset() TrackingOffsetDecRate = _siderealRate - newRate; var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{TrackingOffsetRaRate}|{TrackingOffsetDecRate}" }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{TrackingOffsetRaRate}|{TrackingOffsetDecRate}" }; MonitorLog.LogToMonitor(monitorItem); } @@ -1681,7 +1688,7 @@ private static int SkyGoTo(double[] target, bool trackingState) var stopwatch = Stopwatch.StartNew(); SkyTasks(MountTaskName.StopAxes); - var skyTarget = GetAdjustedAxesForSlewing(Axes.AxesAppToMount(target), SideOfPierRaDec(TargetRa)); + var skyTarget = Axes.AxesAppToMount(target); #region First Slew // time could be off a bit may need to deal with each axis separate @@ -1854,7 +1861,7 @@ private static int SkyPrecisionGoToRA(double[] target, bool trackingState, Stopw if (deltaDegree < gotoPrecision) { break; } target[0] += deltaDegree; - var deltaTarget = GetAdjustedAxesForSlewing(Axes.AxesAppToMount(target), SideOfPierRaDec(TargetRa)); + var deltaTarget = Axes.AxesAppToMount(target); if (SlewState == SlewType.SlewNone) { break; } //check for a stop object _ = new SkyAxisGoToTarget(0, AxisId.Axis1, deltaTarget[0]); //move to new target @@ -1914,6 +1921,7 @@ public static void SkyTasks(MountTaskName taskName) case MountType.Simulator: break; case MountType.SkyWatcher: + case MountType.AstroEQ: switch (taskName) { case MountTaskName.AllowAdvancedCommandSet: @@ -1926,7 +1934,7 @@ public static void SkyTasks(MountTaskName taskName) _ = new SkySetDecPulseToGoTo(0, SkySettings.DecPulseToGoTo); break; case MountTaskName.CanAdvancedCmdSupport: - var SkyCanAdvanced= new SkyGetAdvancedCmdSupport(SkyQueue.NewId); + var SkyCanAdvanced = new SkyGetAdvancedCmdSupport(SkyQueue.NewId); bool.TryParse(Convert.ToString(SkyQueue.GetCommandResult(SkyCanAdvanced).Result), out bool pAdvancedResult); CanAdvancedCmdSupport = pAdvancedResult; break; @@ -1988,10 +1996,10 @@ public static void SkyTasks(MountTaskName taskName) SkySettings.PPecOn = false; break; } - if (ppeconstr.Contains("!")){SkySettings.PPecOn = false; } + if (ppeconstr.Contains("!")) { SkySettings.PPecOn = false; } break; case MountTaskName.PolarLedLevel: - if (SkySettings.PolarLedLevel < 0 || SkySettings.PolarLedLevel > 255){return;} + if (SkySettings.PolarLedLevel < 0 || SkySettings.PolarLedLevel > 255) { return; } _ = new SkySetPolarLedLevel(0, AxisId.Axis1, SkySettings.PolarLedLevel); break; case MountTaskName.StopAxes: @@ -2168,7 +2176,8 @@ public static void SkyErrorHandler(Exception ex) /// true for errors found and not successful private static bool CheckSkyErrors(ISkyCommand command) { - if (command.Exception != null) { + if (command.Exception != null) + { var monitorItem = new MonitorEntry { Datetime = HiResDateTime.UtcNow, @@ -2221,6 +2230,7 @@ public static void AbortSlew(bool speak) SimTasks(MountTaskName.StopAxes); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); break; default: @@ -2274,6 +2284,7 @@ public static async void AutoHomeAsync(int degreeLimit = 100, int offSetDec = 0) returncode2 = await Task.Run(() => autosim.StartAutoHome(Axis.Axis2, degreeLimit, offSetDec)); break; case MountType.SkyWatcher: + case MountType.AstroEQ: var autossky = new AutoHomeSky(); returncode1 = await Task.Run(() => autossky.StartAutoHome(AxisId.Axis1, degreeLimit)); AutoHomeProgressBar = 50; @@ -2429,6 +2440,7 @@ private static bool AxesStopValidate() } return false; case MountType.SkyWatcher: + case MountType.AstroEQ: stopwatch = Stopwatch.StartNew(); while (stopwatch.Elapsed.TotalMilliseconds <= 5000) { @@ -2697,7 +2709,7 @@ public static double CurrentTrackingRate() if (rate < _siderealRate * 2 & rate != 0) //add any custom gearing offset { - rate += TrackingOffsetRaRate; + rate += TrackingOffsetRaRate; } //Implement Pec @@ -2814,6 +2826,7 @@ private static double[] GetRawDegrees() actualDegrees = (double[])MountQueue.GetCommandResult(simPositions).Result; break; case MountType.SkyWatcher: + case MountType.AstroEQ: var skyPositions = new SkyGetPositionsInDegrees(SkyQueue.NewId); actualDegrees = (double[])SkyQueue.GetCommandResult(skyPositions).Result; return CheckSkyErrors(skyPositions) ? null : actualDegrees; @@ -2838,6 +2851,7 @@ private static double ConvertStepsToDegrees(double steps, int axis) degrees = steps / FactorStep[axis]; break; case MountType.SkyWatcher: + case MountType.AstroEQ: degrees = Principles.Units.Rad2Deg1(steps * FactorStep[axis]); break; default: @@ -2863,6 +2877,7 @@ private static double[] GetRawSteps() steps[1] *= FactorStep[1]; break; case MountType.SkyWatcher: + case MountType.AstroEQ: var skySteps = new SkyGetSteps(SkyQueue.NewId); steps = (double[])SkyQueue.GetCommandResult(skySteps).Result; return CheckSkyErrors(skySteps) ? new[] { double.NaN, double.NaN } : steps; @@ -2895,6 +2910,7 @@ private static double[] GetRawSteps() return null; } case MountType.SkyWatcher: + case MountType.AstroEQ: switch (axis) { case 0: @@ -2929,6 +2945,7 @@ private static double[] GetRawSteps() return null; } case MountType.SkyWatcher: + case MountType.AstroEQ: switch (axis) { case 0: @@ -3019,6 +3036,7 @@ private static async void GoToAsync(double[] target, SlewType slewState) returncode = await Task.Run(() => SimGoTo(target, trackingState)); break; case MountType.SkyWatcher: + case MountType.AstroEQ: returncode = await Task.Run(() => SkyGoTo(target, trackingState)); break; default: @@ -3263,6 +3281,7 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo change[1] = SideOfPier == PierSide.pierEast ? delta : -delta; break; case MountType.SkyWatcher: + case MountType.AstroEQ: change[1] = SideOfPier == PierSide.pierEast ? -delta : delta; break; default: @@ -3277,6 +3296,7 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo change[1] = SideOfPier == PierSide.pierWest ? delta : -delta; break; case MountType.SkyWatcher: + case MountType.AstroEQ: change[1] = SideOfPier == PierSide.pierWest ? -delta : delta; break; default: @@ -3514,6 +3534,7 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo break; case MountType.SkyWatcher: + case MountType.AstroEQ: // implement anti-backlash if (Math.Abs(stepsNeededDec) > 0) { @@ -3625,7 +3646,7 @@ private static bool MountConnect() break; } counter++; - + rawPositions = GetRawDegrees(); msg = rawPositions != null ? $"GetRawDegrees:{rawPositions[0]}|{rawPositions[1]}" : $"NULL"; monitorItem = new MonitorEntry @@ -3657,6 +3678,7 @@ private static bool MountConnect() break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyHCRate = new Vector(0, 0); SkyTrackingRate = new Vector(0, 0); @@ -3670,7 +3692,10 @@ private static bool MountConnect() } // defaults - SkyTasks(MountTaskName.AllowAdvancedCommandSet); + if (SkySettings.Mount == MountType.SkyWatcher) + { + SkyTasks(MountTaskName.AllowAdvancedCommandSet); + } SkyTasks(MountTaskName.LoadDefaults); SkyTasks(MountTaskName.StepsPerRevolution); SkyTasks(MountTaskName.StepsWormPerRevolution); @@ -3705,7 +3730,7 @@ private static bool MountConnect() //log current positions var steps = GetRawSteps(); monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"GetSteps:{steps[0]}|{steps[1]}" }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"GetSteps:{steps[0]}|{steps[1]}" }; MonitorLog.LogToMonitor(monitorItem); // checks if the mount is close enough to home position to set default position. If not use the positions from the mount @@ -3722,7 +3747,7 @@ private static bool MountConnect() break; } counter++; - + //get positions and log them rawPositions = GetRawDegrees(); msg = rawPositions != null ? $"GetDegrees|{rawPositions[0]}|{rawPositions[1]}" : $"NULL"; @@ -3748,7 +3773,7 @@ private static bool MountConnect() //was mount powered and at 0,0 are both axes close to home? if not then don't change current mount positions if (!rawPositions[0].IsBetween(-.1, .1) || !rawPositions[1].IsBetween(-.1, .1)) { continue; } - + //Mount is close to home 0,0 so set the default position _ = new SkySetAxisPosition(0, AxisId.Axis1, positions[0]); _ = new SkySetAxisPosition(0, AxisId.Axis2, positions[1]); @@ -3763,7 +3788,7 @@ private static bool MountConnect() msg = positionsSet ? $"SetPositions|{positions[0]}|{positions[1]}" : $"PositionsNotSet"; monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = msg }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = msg }; MonitorLog.LogToMonitor(monitorItem); monitorItem = new MonitorEntry @@ -3794,7 +3819,7 @@ private static bool MountConnect() MonitorLog.LogToMonitor(monitorItem); // Update Alignment Model home position - AlignmentModel.SetHomePosition(_homeAxes.X, _homeAxes.Y); + AlignmentModel.SetHomePosition(0, 0); return true; } @@ -3816,6 +3841,7 @@ private static void MountStart() if (!MountQueue.IsRunning) { throw new Exception("Failed to start simulator queue"); } break; case MountType.SkyWatcher: + case MountType.AstroEQ: // open serial port SkySystem.ConnectSerial = false; SkySystem.ConnectSerial = true; @@ -3825,15 +3851,15 @@ private static void MountStart() $"Serial Failed COM{SkySettings.ComPort}"); } // Start up, pass custom mount gearing if needed - var Custom360Steps = new[] {0,0}; - var CustomWormSteps = new[] {0.0,0.0}; + var Custom360Steps = new[] { 0, 0 }; + var CustomWormSteps = new[] { 0.0, 0.0 }; if (SkySettings.CustomGearing) { Custom360Steps = new[] { SkySettings.CustomRa360Steps, SkySettings.CustomDec360Steps }; - CustomWormSteps= new[] { (double) SkySettings.CustomRa360Steps / SkySettings.CustomRaWormTeeth, (double) SkySettings.CustomDec360Steps / SkySettings.CustomDecWormTeeth}; + CustomWormSteps = new[] { (double)SkySettings.CustomRa360Steps / SkySettings.CustomRaWormTeeth, (double)SkySettings.CustomDec360Steps / SkySettings.CustomDecWormTeeth }; } - SkyQueue.Start(SkySystem.Serial, Custom360Steps, CustomWormSteps); + SkyQueue.Start(SkySystem.Serial, Custom360Steps, CustomWormSteps); if (!SkyQueue.IsRunning) { throw new SkyServerException(ErrorCode.ErrMount, "Failed to start sky queue"); @@ -3866,7 +3892,7 @@ private static void MountStart() private static void MountStop() { var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Server, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{SkySettings.Mount}" }; + { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Server, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{SkySettings.Mount}" }; MonitorLog.LogToMonitor(monitorItem); AxesStopValidate(); @@ -3891,7 +3917,7 @@ private static void MountStop() /// in milliseconds public static void PulseGuide(GuideDirections direction, int duration) { - if (!IsMountRunning) { throw new Exception("Mount not running") ; } + if (!IsMountRunning) { throw new Exception("Mount not running"); } var monitorItem = new MonitorEntry { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Mount, Type = MonitorType.Data, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, Message = $"{direction}|{duration}" }; @@ -3931,6 +3957,7 @@ public static void PulseGuide(GuideDirections direction, int duration) _ = new CmdAxisPulse(0, Axis.Axis2, decGuideRate, duration); break; case MountType.SkyWatcher: + case MountType.AstroEQ: _ = new SkyAxisPulse(0, AxisId.Axis2, decGuideRate, duration, decbacklashamount); break; default: @@ -3955,13 +3982,14 @@ public static void PulseGuide(GuideDirections direction, int duration) { if (direction == GuideDirections.guideEast) { raGuideRate = -raGuideRate; } } - + switch (SkySettings.Mount) { case MountType.Simulator: _ = new CmdAxisPulse(0, Axis.Axis1, raGuideRate, duration); break; case MountType.SkyWatcher: + case MountType.AstroEQ: _ = new SkyAxisPulse(0, AxisId.Axis1, raGuideRate, duration); break; default: @@ -3981,7 +4009,8 @@ public static void ReSyncAxes(ParkPosition parkPosition = null) { if (!IsMountRunning) { return; } if (Tracking) { Tracking = false; } - if (IsSlewing){ + if (IsSlewing) + { StopAxes(); return; } @@ -3993,7 +4022,7 @@ public static void ReSyncAxes(ParkPosition parkPosition = null) //set to park position if (parkPosition != null) { - position = Axes.AxesAppToMount(new[] { parkPosition.X, parkPosition.Y}); + position = Axes.AxesAppToMount(new[] { parkPosition.X, parkPosition.Y }); name = parkPosition.Name; } @@ -4018,6 +4047,7 @@ public static void ReSyncAxes(ParkPosition parkPosition = null) _ = new CmdAxisToDegrees(0, Axis.Axis2, position[1]); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); _ = new SkySetAxisPosition(0, AxisId.Axis1, position[0]); _ = new SkySetAxisPosition(0, AxisId.Axis2, position[1]); @@ -4175,6 +4205,7 @@ private static void SetTracking() _ = new CmdAxisTracking(0, Axis.Axis1, rateChange); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTrackingRate.X = rateChange; var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); @@ -4287,8 +4318,14 @@ public static PierSide SideOfPierActual(double RightAscension, double Declinatio var flipreq = Axes.IsFlipRequired(new[] { RightAscension, Declination }); var monitorItem = new MonitorEntry - { Datetime = HiResDateTime.UtcNow, Device = MonitorDevice.Server, Category = MonitorCategory.Server, Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, - Message = $"Ra:{RightAscension}|Dec:{Declination}|Flip:{flipreq}|SoP:{SideOfPier}" + { + Datetime = HiResDateTime.UtcNow, + Device = MonitorDevice.Server, + Category = MonitorCategory.Server, + Type = MonitorType.Information, + Method = MethodBase.GetCurrentMethod()?.Name, + Thread = Thread.CurrentThread.ManagedThreadId, + Message = $"Ra:{RightAscension}|Dec:{Declination}|Flip:{flipreq}|SoP:{SideOfPier}" }; MonitorLog.LogToMonitor(monitorItem); @@ -4338,6 +4375,7 @@ public static double[] CheckAlternatePosition(double[] position) if (SouthernHemisphere) { alt[0] = 180 - alt[0]; } break; case MountType.SkyWatcher: + case MountType.AstroEQ: if (SouthernHemisphere) { alt[0] = 180 - alt[0]; @@ -4400,10 +4438,7 @@ private static void SlewAltAz(Vector targetAltAzm) if (target.LengthSquared > 0) { - var targetAxes = new[] { target.X, target.Y }; - var raDec = Axes.AxesXYToRaDec(targetAxes); - var a = GetAdjustedAxesForSlewing(targetAxes, SideOfPierRaDec(raDec[0])); - SlewMount(new Vector(a[0], a[1]), SlewType.SlewAltAz); + SlewMount(target, SlewType.SlewAltAz); } } @@ -4483,6 +4518,7 @@ public static void StopAxes() SimTasks(MountTaskName.StopAxes); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); break; default: @@ -4525,6 +4561,7 @@ public static void SyncToAltAzm(double targetAzimuth, double targetAltitude) SimTasks(MountTaskName.SyncAltAz); break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); SkyTasks(MountTaskName.SyncAltAz); break; @@ -4576,6 +4613,7 @@ public static void SyncToTargetRaDec() } break; case MountType.SkyWatcher: + case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); if (AlignmentModel.IsAlignmentOn) { @@ -4614,7 +4652,7 @@ public static bool CheckRaDecSyncLimit(double ra, double dec) //convert ra dec to mount positions var xy = Axes.RaDecToAxesXY(new[] { ra, dec }); - var target = GetAdjustedAxesForSlewing(Axes.AxesAppToMount(xy), SideOfPierRaDec(ra)); + var target = Axes.AxesAppToMount(xy); //convert current position to mount position var current = Axes.AxesMountToApp(new[] { _mountAxisX, _mountAxisY }); @@ -4719,77 +4757,57 @@ private static void AlignmentModel_Notification(object sender, NotificationEvent }; MonitorLog.LogToMonitor(monitorItem); } + internal static double DegToRad(double degree) { return (degree / 180.0 * Math.PI); } + internal static double RadToDeg(double rad) { return (rad / Math.PI * 180.0); } private static void AddAlignmentPoint() { - // The mount axis and alt az are are the mount things it should be pointing based on the target RA and Dec - // The sky axis and alt az are the positions last determined from GetRawDegrees in the UpdateUIEvent. - double[] target = Axes.RaDecToAxesXY(new[] { SkyServer.TargetRa, SkyServer.TargetDec, SiderealTime }); - var mountAxes = Axes.AxesAppToMount(target); - var mountAzAlt = Axes.AxesXYToAzAlt(target); - var mountAltAz = new[] { mountAzAlt[1], mountAzAlt[0] }; - double[] observedAxes = new double[] { ActualAxisX, ActualAxisY }; - double[] observedAltAz = new double[] { Altitude, Azimuth }; - - AlignmentModel.AddAlignmentPoint( - mountAltAz, - observedAltAz, - mountAxes, - observedAxes, - (int)SideOfPier, - DateTime.Now); + // At this point: + // SkyServer.Steps contains the current encoder posititions. + // SkyServer.FactorStep contains the conversion from radians to steps + // To get the target steps + var xy = Axes.RaDecToAxesXY(new[] { TargetRa, TargetDec }); + var targ = Axes.AxesAppToMount(new[] { xy[0], xy[1] }); + var targetSteps = new[] { + (long)Math.Floor(DegToRad(targ[0]) + SkyServer.FactorStep[0]), + (long)Math.Floor(DegToRad(targ[1]) + SkyServer.FactorStep[1])}; - var monitorItem = new MonitorEntry - { - Datetime = HiResDateTime.UtcNow, - Device = MonitorDevice.Server, - Category = MonitorCategory.Alignment, - Type = MonitorType.Information, - Method = MethodBase.GetCurrentMethod()?.Name, - Thread = Thread.CurrentThread.ManagedThreadId, - Message = $"Alignment point added: Mount axis = {mountAxes[0]}/{mountAxes[1]}, observed axis = {observedAxes[0]}/{observedAxes[1]}" - }; - MonitorLog.LogToMonitor(monitorItem); - } - /// - /// Returns the actual axis position that alignment says should be used for a mount calculated axis position - /// used to get the axis positions to slew to. - /// - /// Calculated axis positions - /// - /// Adjusted axis positions - private static double[] GetAdjustedAxesForSlewing(double[] calculatedAxes, PierSide pierSide) - { - // Apply alignment adjustment. - var alignedAxes = AlignmentModel.GetObservedAxes(calculatedAxes, (int)pierSide); - if (!AlignmentModel.IsAlignmentOn) return alignedAxes; - var monitorItem = new MonitorEntry + if (AlignmentModel.SyncToRaDec( + new long[] { (long)SkyServer.Steps[0], (long)SkyServer.Steps[0] }, + new double[] { TargetRa, TargetDec }, + targetSteps, + DateTime.Now)) { - Datetime = HiResDateTime.UtcNow, - Device = MonitorDevice.Server, - Category = MonitorCategory.Alignment, - Type = MonitorType.Information, - Method = MethodBase.GetCurrentMethod()?.Name, - Thread = Thread.CurrentThread.ManagedThreadId, - Message = $"Alignment applied to calculated axes: {calculatedAxes[0]}|{calculatedAxes[1]} -> {alignedAxes[0]}|{alignedAxes[1]}" - }; - MonitorLog.LogToMonitor(monitorItem); - - return alignedAxes; + var monitorItem = new MonitorEntry + { + Datetime = HiResDateTime.UtcNow, + Device = MonitorDevice.Server, + Category = MonitorCategory.Alignment, + Type = MonitorType.Information, + Method = MethodBase.GetCurrentMethod()?.Name, + Thread = Thread.CurrentThread.ManagedThreadId, + Message = $"Alignment point added: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetSteps[0]}/{targetSteps[1]}" + }; + MonitorLog.LogToMonitor(monitorItem); + } + else + { + var monitorItem = new MonitorEntry + { + Datetime = HiResDateTime.UtcNow, + Device = MonitorDevice.Server, + Category = MonitorCategory.Alignment, + Type = MonitorType.Error, + Method = MethodBase.GetCurrentMethod()?.Name, + Thread = Thread.CurrentThread.ManagedThreadId, + Message = $"Alignment point rejected: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetSteps[0]}/{targetSteps[1]}" + }; + MonitorLog.LogToMonitor(monitorItem); + } } - /// - /// Converts an actual axis position to the position the mount would calculate to get there. - /// Used when determining current position coordinate for display. - /// - /// - /// - private static double[] GetAdjustAxesForReporting(double[] actualAxes) - { - return AlignmentModel.GetMountAxes(actualAxes, (int)SideOfPier); - } #endregion @@ -4817,13 +4835,13 @@ private static void PropertyChangedAlignmentSettings(object sender, PropertyChan AlignmentModel.IsAlignmentOn = AlignmentSettings.IsAlignmentOn; break; case "ProximityLimit": - AlignmentModel.ProximityLimit = AlignmentSettings.ProximityLimit; + // AlignmentModel.ProximityLimit = AlignmentSettings.ProximityLimit; break; case "NearbyLimit": - AlignmentModel.NearbyLimit = AlignmentSettings.NearbyLimit; + // AlignmentModel.NearbyLimit = AlignmentSettings.NearbyLimit; break; case "SampleSize": - AlignmentModel.SampleSize = AlignmentSettings.SampleSize; + // AlignmentModel.SampleSize = AlignmentSettings.SampleSize; break; } } @@ -5021,17 +5039,14 @@ private static void UpdateServerEvent(object sender, EventArgs e) PecCheck(); //Convert Positions to degrees - double[] rawPositions = {ConvertStepsToDegrees(rawSteps[0], 0), ConvertStepsToDegrees(rawSteps[1], 1)}; - - //Apply any alignment adjustments - var calculatedAxes = GetAdjustAxesForReporting(rawPositions); + double[] rawPositions = { ConvertStepsToDegrees(rawSteps[0], 0), ConvertStepsToDegrees(rawSteps[1], 1) }; // UI diagnostics in degrees ActualAxisX = rawPositions[0]; ActualAxisY = rawPositions[1]; // convert positions to local - var axes = Axes.AxesMountToApp(calculatedAxes); + var axes = Axes.AxesMountToApp(rawPositions); // local to track positions _mountAxes.X = axes[0]; @@ -5050,7 +5065,7 @@ private static void UpdateServerEvent(object sender, EventArgs e) var radec = Axes.AxesXYToRaDec(axes); RightAscension = radec[0]; Declination = radec[1]; - + Lha = Coordinate.Ra2Ha12(RightAscensionXForm, SiderealTime); // Track slewing state @@ -5127,7 +5142,7 @@ public static bool CanPolarLed get => _canPolarLed; private set { - if (_canPolarLed == value) {return;} + if (_canPolarLed == value) { return; } _canPolarLed = value; OnStaticPropertyChanged(); } @@ -5138,12 +5153,12 @@ public static bool CanAdvancedCmdSupport get => _canAdvancedCmdSupport; private set { - if (_canAdvancedCmdSupport == value) {return;} + if (_canAdvancedCmdSupport == value) { return; } _canAdvancedCmdSupport = value; OnStaticPropertyChanged(); } } - + /// /// Turn on/off mount PPec @@ -5282,6 +5297,7 @@ private static void CheckPecTraining() case MountType.Simulator: break; case MountType.SkyWatcher: + case MountType.AstroEQ: if (!PecTraining) { PecTrainInProgress = false; @@ -5353,7 +5369,7 @@ private static void PecCheck() { var mi = Tuple.Create(0.0, 0); var masterResult = Pec360Master != null && Pec360Master.TryGetValue(i, out mi); - if (masterResult ) PecBinsSubs.Add(i, mi); + if (masterResult) PecBinsSubs.Add(i, mi); } count++; diff --git a/GS.Server/SkyTelescope/SkyTelescopeVM.cs b/GS.Server/SkyTelescope/SkyTelescopeVM.cs index 7d2e45b3..ea093f47 100644 --- a/GS.Server/SkyTelescope/SkyTelescopeVM.cs +++ b/GS.Server/SkyTelescope/SkyTelescopeVM.cs @@ -1228,7 +1228,7 @@ public int PolarLedLevel { case MountType.Simulator: break; - case MountType.SkyWatcher: + case MountType.SkyWatcher: case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.PolarLedLevel); break; default: @@ -4709,7 +4709,7 @@ private void HomePositionCheck() //msg += Environment.NewLine + Application.Current.Resources["skyHome3"]; OpenDialog(msg); break; - case MountType.SkyWatcher: + case MountType.SkyWatcher: case MountType.AstroEQ: switch (SkySettings.AlignmentMode) { case AlignmentModes.algAltAz: diff --git a/GS.Server/Snap/SnapVM.cs b/GS.Server/Snap/SnapVM.cs index 3c268bf5..f4681d1f 100644 --- a/GS.Server/Snap/SnapVM.cs +++ b/GS.Server/Snap/SnapVM.cs @@ -446,7 +446,7 @@ private void Snap1Trigger(bool on) case MountType.Simulator: SkyServer.SimTasks(MountTaskName.SetSnapPort1); break; - case MountType.SkyWatcher: + case MountType.SkyWatcher: case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort1); break; default: @@ -813,7 +813,7 @@ private void Snap2Trigger(bool on) case MountType.Simulator: SkyServer.SimTasks(MountTaskName.SetSnapPort2); break; - case MountType.SkyWatcher: + case MountType.SkyWatcher: case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort2); break; default: diff --git a/GS.Shared/Model3D.cs b/GS.Shared/Model3D.cs index 03868769..1cd71a92 100644 --- a/GS.Shared/Model3D.cs +++ b/GS.Shared/Model3D.cs @@ -62,7 +62,7 @@ public static string GetCompassFile(bool southernHemisphere) } public static double[] RotateModel(string mountType, double ax, double ay, bool southernHemisphere) { - var axes = new[] {0.0, 0.0}; + var axes = new[] { 0.0, 0.0 }; switch (mountType) { case "Simulator": @@ -70,6 +70,7 @@ public static double[] RotateModel(string mountType, double ax, double ay, bool axes[1] = southernHemisphere ? Math.Round(ay - 180, 3) : Math.Round(ay * -1.0, 3); break; case "SkyWatcher": + case "AstroEQ": axes[0] = Math.Round(ax, 3); axes[1] = Math.Round(ay - 180, 3); break; diff --git a/GS.SkyWatcher/Commands.cs b/GS.SkyWatcher/Commands.cs index 88782f34..d71a6f1e 100644 --- a/GS.SkyWatcher/Commands.cs +++ b/GS.SkyWatcher/Commands.cs @@ -1537,7 +1537,7 @@ internal double StepToAngle(AxisId axis, long steps) /// AxisId.Axis1 or AxisId.Axis2 /// /// - internal long AngleToStep(AxisId axis, double angleInRad) + public long AngleToStep(AxisId axis, double angleInRad) { //var a = (long)(angleInRad * _factorRadToStep[(int)axis]); var a = (long)Math.Floor(angleInRad * _factorRadToStep[(int)axis]); diff --git a/GSSolution.sln b/GSSolution.sln index c8001357..78be6ac7 100644 --- a/GSSolution.sln +++ b/GSSolution.sln @@ -43,6 +43,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GS.FitsImageManager", "GS.F EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NINA", "NINA\NINA.csproj", "{6770B884-0C92-4615-BE0D-7FBE55D2D0EE}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EqmodNStarAlignment", "EQMODAlignment\EqmodNStarAlignment.csproj", "{B2375CA6-17AE-4875-B33D-B276781CC1DA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment.Tests", "EqmodNStarAlignment.Tests\EqmodNStarAlignment.Tests.csproj", "{A546006B-D866-41B9-B378-F0666F18618C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution AppVeyor|Any CPU = AppVeyor|Any CPU @@ -326,6 +330,42 @@ Global {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x64.Build.0 = Release|Any CPU {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x86.ActiveCfg = Release|Any CPU {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x86.Build.0 = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x64.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x64.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x86.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x86.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x64.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x64.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x86.ActiveCfg = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x86.Build.0 = Debug|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|Any CPU.Build.0 = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x64.ActiveCfg = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x64.Build.0 = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x86.ActiveCfg = Release|Any CPU + {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x86.Build.0 = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x64.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x64.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x86.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x86.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x64.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x64.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x86.ActiveCfg = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x86.Build.0 = Debug|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|Any CPU.Build.0 = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|x64.ActiveCfg = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|x64.Build.0 = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|x86.ActiveCfg = Release|Any CPU + {A546006B-D866-41B9-B378-F0666F18618C}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 82ebfa5b3280f9deb6b6a7803573316e8ecefdaf Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Sat, 26 Nov 2022 16:51:04 +0000 Subject: [PATCH 02/18] Removing code to allow a mount type of AstroEQ that was put in prior to Robs Advanced Command check box. --- GS.Ascom.SkyTelescope/CommandStrings.cs | 2 -- GS.Ascom.SkyTelescope/Telescope.cs | 1 - GS.Server/SkyTelescope/Axes.cs | 2 -- GS.Server/SkyTelescope/Enums.cs | 3 +-- GS.Server/SkyTelescope/SkyServer.cs | 30 ------------------------ GS.Server/SkyTelescope/SkyTelescopeVM.cs | 4 ++-- GS.Server/Snap/SnapVM.cs | 4 ++-- GS.Shared/Model3D.cs | 1 - 8 files changed, 5 insertions(+), 42 deletions(-) diff --git a/GS.Ascom.SkyTelescope/CommandStrings.cs b/GS.Ascom.SkyTelescope/CommandStrings.cs index 1f9932ca..f1c91e38 100644 --- a/GS.Ascom.SkyTelescope/CommandStrings.cs +++ b/GS.Ascom.SkyTelescope/CommandStrings.cs @@ -37,7 +37,6 @@ public static string ProcessCommand(string command, bool raw) SkyServer.SimTasks(MountTaskName.SetSnapPort1); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort1); break; default: @@ -62,7 +61,6 @@ public static string ProcessCommand(string command, bool raw) SkyServer.SimTasks(MountTaskName.SetSnapPort2); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyServer.SkyTasks(MountTaskName.SetSnapPort2); break; default: diff --git a/GS.Ascom.SkyTelescope/Telescope.cs b/GS.Ascom.SkyTelescope/Telescope.cs index e8bc6e19..938314c3 100644 --- a/GS.Ascom.SkyTelescope/Telescope.cs +++ b/GS.Ascom.SkyTelescope/Telescope.cs @@ -1851,7 +1851,6 @@ private static void DelayInterval(int additional = 0) delay += SkySettings.DisplayInterval; break; case MountType.SkyWatcher: - case MountType.AstroEQ: delay += 20; // some go tos have been off .10 to .70 seconds, not sure exactly why delay += SkySettings.DisplayInterval; break; diff --git a/GS.Server/SkyTelescope/Axes.cs b/GS.Server/SkyTelescope/Axes.cs index 0404bc74..b1d945e2 100644 --- a/GS.Server/SkyTelescope/Axes.cs +++ b/GS.Server/SkyTelescope/Axes.cs @@ -69,7 +69,6 @@ internal static double[] AxesAppToMount(double[] axes) } break; case MountType.SkyWatcher: - case MountType.AstroEQ: if (SkyServer.SouthernHemisphere) { a[0] = 180 - a[0]; @@ -114,7 +113,6 @@ internal static double[] AxesMountToApp(double[] axes) break; case MountType.SkyWatcher: - case MountType.AstroEQ: if (SkyServer.SouthernHemisphere) { a[0] = a[0] * -1.0; diff --git a/GS.Server/SkyTelescope/Enums.cs b/GS.Server/SkyTelescope/Enums.cs index d098bbbe..2c4b6292 100644 --- a/GS.Server/SkyTelescope/Enums.cs +++ b/GS.Server/SkyTelescope/Enums.cs @@ -119,8 +119,7 @@ public enum MountTaskName public enum MountType { Simulator, - SkyWatcher, - AstroEQ + SkyWatcher } public enum ErrorCode diff --git a/GS.Server/SkyTelescope/SkyServer.cs b/GS.Server/SkyTelescope/SkyServer.cs index 564415e7..075d30a4 100644 --- a/GS.Server/SkyTelescope/SkyServer.cs +++ b/GS.Server/SkyTelescope/SkyServer.cs @@ -438,7 +438,6 @@ public static double RateRa _ = new CmdRate(0, Axis.Axis1, _rateRaDec.X); break; case MountType.SkyWatcher: - case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -564,7 +563,6 @@ public static bool IsMountRunning _mountRunning = MountQueue.IsRunning; break; case MountType.SkyWatcher: - case MountType.AstroEQ: _mountRunning = SkyQueue.IsRunning; break; } @@ -822,7 +820,6 @@ public static double RateAxisDec _ = new CmdRateAxis(0, Axis.Axis2, _rateAxes.Y); break; case MountType.SkyWatcher: - case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis2, rate.Y); break; @@ -875,7 +872,6 @@ public static double RateAxisRa _ = new CmdRateAxis(0, Axis.Axis1, _rateAxes.X); break; case MountType.SkyWatcher: - case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -913,7 +909,6 @@ public static double RateDec _ = new CmdRate(0, Axis.Axis2, _rateRaDec.Y); break; case MountType.SkyWatcher: - case MountType.AstroEQ: var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); break; @@ -1451,7 +1446,6 @@ public static void SimTasks(MountTaskName taskName) switch (SkySettings.Mount) { case MountType.SkyWatcher: - case MountType.AstroEQ: break; case MountType.Simulator: switch (taskName) @@ -1921,7 +1915,6 @@ public static void SkyTasks(MountTaskName taskName) case MountType.Simulator: break; case MountType.SkyWatcher: - case MountType.AstroEQ: switch (taskName) { case MountTaskName.AllowAdvancedCommandSet: @@ -2230,7 +2223,6 @@ public static void AbortSlew(bool speak) SimTasks(MountTaskName.StopAxes); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); break; default: @@ -2284,7 +2276,6 @@ public static async void AutoHomeAsync(int degreeLimit = 100, int offSetDec = 0) returncode2 = await Task.Run(() => autosim.StartAutoHome(Axis.Axis2, degreeLimit, offSetDec)); break; case MountType.SkyWatcher: - case MountType.AstroEQ: var autossky = new AutoHomeSky(); returncode1 = await Task.Run(() => autossky.StartAutoHome(AxisId.Axis1, degreeLimit)); AutoHomeProgressBar = 50; @@ -2440,7 +2431,6 @@ private static bool AxesStopValidate() } return false; case MountType.SkyWatcher: - case MountType.AstroEQ: stopwatch = Stopwatch.StartNew(); while (stopwatch.Elapsed.TotalMilliseconds <= 5000) { @@ -2826,7 +2816,6 @@ private static double[] GetRawDegrees() actualDegrees = (double[])MountQueue.GetCommandResult(simPositions).Result; break; case MountType.SkyWatcher: - case MountType.AstroEQ: var skyPositions = new SkyGetPositionsInDegrees(SkyQueue.NewId); actualDegrees = (double[])SkyQueue.GetCommandResult(skyPositions).Result; return CheckSkyErrors(skyPositions) ? null : actualDegrees; @@ -2851,7 +2840,6 @@ private static double ConvertStepsToDegrees(double steps, int axis) degrees = steps / FactorStep[axis]; break; case MountType.SkyWatcher: - case MountType.AstroEQ: degrees = Principles.Units.Rad2Deg1(steps * FactorStep[axis]); break; default: @@ -2877,7 +2865,6 @@ private static double[] GetRawSteps() steps[1] *= FactorStep[1]; break; case MountType.SkyWatcher: - case MountType.AstroEQ: var skySteps = new SkyGetSteps(SkyQueue.NewId); steps = (double[])SkyQueue.GetCommandResult(skySteps).Result; return CheckSkyErrors(skySteps) ? new[] { double.NaN, double.NaN } : steps; @@ -2910,7 +2897,6 @@ private static double[] GetRawSteps() return null; } case MountType.SkyWatcher: - case MountType.AstroEQ: switch (axis) { case 0: @@ -2945,7 +2931,6 @@ private static double[] GetRawSteps() return null; } case MountType.SkyWatcher: - case MountType.AstroEQ: switch (axis) { case 0: @@ -3036,7 +3021,6 @@ private static async void GoToAsync(double[] target, SlewType slewState) returncode = await Task.Run(() => SimGoTo(target, trackingState)); break; case MountType.SkyWatcher: - case MountType.AstroEQ: returncode = await Task.Run(() => SkyGoTo(target, trackingState)); break; default: @@ -3281,7 +3265,6 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo change[1] = SideOfPier == PierSide.pierEast ? delta : -delta; break; case MountType.SkyWatcher: - case MountType.AstroEQ: change[1] = SideOfPier == PierSide.pierEast ? -delta : delta; break; default: @@ -3296,7 +3279,6 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo change[1] = SideOfPier == PierSide.pierWest ? delta : -delta; break; case MountType.SkyWatcher: - case MountType.AstroEQ: change[1] = SideOfPier == PierSide.pierWest ? -delta : delta; break; default: @@ -3534,7 +3516,6 @@ public static void HcMoves(SlewSpeed speed, SlewDirection direction, HCMode HcMo break; case MountType.SkyWatcher: - case MountType.AstroEQ: // implement anti-backlash if (Math.Abs(stepsNeededDec) > 0) { @@ -3678,7 +3659,6 @@ private static bool MountConnect() break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyHCRate = new Vector(0, 0); SkyTrackingRate = new Vector(0, 0); @@ -3841,7 +3821,6 @@ private static void MountStart() if (!MountQueue.IsRunning) { throw new Exception("Failed to start simulator queue"); } break; case MountType.SkyWatcher: - case MountType.AstroEQ: // open serial port SkySystem.ConnectSerial = false; SkySystem.ConnectSerial = true; @@ -3957,7 +3936,6 @@ public static void PulseGuide(GuideDirections direction, int duration) _ = new CmdAxisPulse(0, Axis.Axis2, decGuideRate, duration); break; case MountType.SkyWatcher: - case MountType.AstroEQ: _ = new SkyAxisPulse(0, AxisId.Axis2, decGuideRate, duration, decbacklashamount); break; default: @@ -3989,7 +3967,6 @@ public static void PulseGuide(GuideDirections direction, int duration) _ = new CmdAxisPulse(0, Axis.Axis1, raGuideRate, duration); break; case MountType.SkyWatcher: - case MountType.AstroEQ: _ = new SkyAxisPulse(0, AxisId.Axis1, raGuideRate, duration); break; default: @@ -4047,7 +4024,6 @@ public static void ReSyncAxes(ParkPosition parkPosition = null) _ = new CmdAxisToDegrees(0, Axis.Axis2, position[1]); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); _ = new SkySetAxisPosition(0, AxisId.Axis1, position[0]); _ = new SkySetAxisPosition(0, AxisId.Axis2, position[1]); @@ -4205,7 +4181,6 @@ private static void SetTracking() _ = new CmdAxisTracking(0, Axis.Axis1, rateChange); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTrackingRate.X = rateChange; var rate = GetSlewRate(); _ = new SkyAxisSlew(0, AxisId.Axis1, rate.X); @@ -4375,7 +4350,6 @@ public static double[] CheckAlternatePosition(double[] position) if (SouthernHemisphere) { alt[0] = 180 - alt[0]; } break; case MountType.SkyWatcher: - case MountType.AstroEQ: if (SouthernHemisphere) { alt[0] = 180 - alt[0]; @@ -4518,7 +4492,6 @@ public static void StopAxes() SimTasks(MountTaskName.StopAxes); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); break; default: @@ -4561,7 +4534,6 @@ public static void SyncToAltAzm(double targetAzimuth, double targetAltitude) SimTasks(MountTaskName.SyncAltAz); break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); SkyTasks(MountTaskName.SyncAltAz); break; @@ -4613,7 +4585,6 @@ public static void SyncToTargetRaDec() } break; case MountType.SkyWatcher: - case MountType.AstroEQ: SkyTasks(MountTaskName.StopAxes); if (AlignmentModel.IsAlignmentOn) { @@ -5297,7 +5268,6 @@ private static void CheckPecTraining() case MountType.Simulator: break; case MountType.SkyWatcher: - case MountType.AstroEQ: if (!PecTraining) { PecTrainInProgress = false; diff --git a/GS.Server/SkyTelescope/SkyTelescopeVM.cs b/GS.Server/SkyTelescope/SkyTelescopeVM.cs index cabc826b..d2216367 100644 --- a/GS.Server/SkyTelescope/SkyTelescopeVM.cs +++ b/GS.Server/SkyTelescope/SkyTelescopeVM.cs @@ -1238,7 +1238,7 @@ public int PolarLedLevel { case MountType.Simulator: break; - case MountType.SkyWatcher: case MountType.AstroEQ: + case MountType.SkyWatcher: SkyServer.SkyTasks(MountTaskName.PolarLedLevel); break; default: @@ -4719,7 +4719,7 @@ private void HomePositionCheck() //msg += Environment.NewLine + Application.Current.Resources["skyHome3"]; OpenDialog(msg); break; - case MountType.SkyWatcher: case MountType.AstroEQ: + case MountType.SkyWatcher: switch (SkySettings.AlignmentMode) { case AlignmentModes.algAltAz: diff --git a/GS.Server/Snap/SnapVM.cs b/GS.Server/Snap/SnapVM.cs index f4681d1f..3c268bf5 100644 --- a/GS.Server/Snap/SnapVM.cs +++ b/GS.Server/Snap/SnapVM.cs @@ -446,7 +446,7 @@ private void Snap1Trigger(bool on) case MountType.Simulator: SkyServer.SimTasks(MountTaskName.SetSnapPort1); break; - case MountType.SkyWatcher: case MountType.AstroEQ: + case MountType.SkyWatcher: SkyServer.SkyTasks(MountTaskName.SetSnapPort1); break; default: @@ -813,7 +813,7 @@ private void Snap2Trigger(bool on) case MountType.Simulator: SkyServer.SimTasks(MountTaskName.SetSnapPort2); break; - case MountType.SkyWatcher: case MountType.AstroEQ: + case MountType.SkyWatcher: SkyServer.SkyTasks(MountTaskName.SetSnapPort2); break; default: diff --git a/GS.Shared/Model3D.cs b/GS.Shared/Model3D.cs index 1cd71a92..ea13468c 100644 --- a/GS.Shared/Model3D.cs +++ b/GS.Shared/Model3D.cs @@ -70,7 +70,6 @@ public static double[] RotateModel(string mountType, double ax, double ay, bool axes[1] = southernHemisphere ? Math.Round(ay - 180, 3) : Math.Round(ay * -1.0, 3); break; case "SkyWatcher": - case "AstroEQ": axes[0] = Math.Round(ax, 3); axes[1] = Math.Round(ay - 180, 3); break; From 044c5402293fd02e8edd4102e5fc6976ebe80ddb Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Mon, 28 Nov 2022 21:38:11 +0000 Subject: [PATCH 03/18] WIP Check in, working on unit tests for save and loading alignment points and building Taki and Affine matrices compared to Eqmod values. --- EQMODAlignment/Model/AlignmentModel.cs | 9 +- .../Model/AlignmentModel_EqModVector.cs | 4 +- .../Model/AlignmentModel_EqmodAlignment.cs | 1 + EQMODAlignment/Model/AlignmentModel_Math.cs | 2 +- EQMODAlignment/Model/AlignmentPoint.cs | 9 +- .../AlignmentModelTests.cs | 102 ++++++++++++++++++ .../Data/AlignmentPointsIn.json | 80 ++++++++++++++ .../EqmodNStarAlignment.Tests.csproj | 12 ++- EqmodNStarAlignment.Tests/EqmodVectorTests.cs | 90 ++++++++++++++++ EqmodNStarAlignment.Tests/UnitTest1.cs | 14 --- 10 files changed, 301 insertions(+), 22 deletions(-) create mode 100644 EqmodNStarAlignment.Tests/AlignmentModelTests.cs create mode 100644 EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json create mode 100644 EqmodNStarAlignment.Tests/EqmodVectorTests.cs delete mode 100644 EqmodNStarAlignment.Tests/UnitTest1.cs diff --git a/EQMODAlignment/Model/AlignmentModel.cs b/EQMODAlignment/Model/AlignmentModel.cs index 29a83153..9c1b5191 100644 --- a/EQMODAlignment/Model/AlignmentModel.cs +++ b/EQMODAlignment/Model/AlignmentModel.cs @@ -8,6 +8,7 @@ using System.Reflection; using System.Text; using System.Threading; +using System.Linq; namespace EqmodNStarAlignment.Model { @@ -145,7 +146,7 @@ public double SiteLatitude public bool PolarEnable { get => _polarEnable; - set + set { if (_polarEnable == value) return; _polarEnable = value; @@ -311,8 +312,12 @@ public void LoadAlignmentPoints(string filename) foreach (var alignmentPoint in loaded) { AlignmentPoints.Add(alignmentPoint); + _oneStarAdjustment = alignmentPoint.Delta; + } + if (AlignmentPoints.Count >= 3) + { + SendToMatrix(); // Updates the cartesean values. } - SendToMatrix(); // Updates the cartesean values. } } catch (Exception ex) diff --git a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs index e154cee0..39858b48 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs @@ -341,7 +341,7 @@ private int EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coo //Function to convert spherical coordinates to Cartesian using the Coord structure - internal Coord EQ_sp2Cs(EncoderPosition pos) + public Coord EQ_sp2Cs(EncoderPosition pos) { Coord result = new Coord(); @@ -1276,7 +1276,7 @@ private int EQ_CheckPoint_in_Triangle(double px, double py, double px1, double p //} - private SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) + public SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) { SphericalCoord result = new SphericalCoord(); diff --git a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs index a56dc3e2..a2c872cb 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs +++ b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs @@ -22,6 +22,7 @@ public bool EQ_NPointAppend(AlignmentPoint data) { if (AlignmentPoints.Count == 3) { + AlignmentPoints.Add(data); // Update the matrices SendToMatrix(); } diff --git a/EQMODAlignment/Model/AlignmentModel_Math.cs b/EQMODAlignment/Model/AlignmentModel_Math.cs index c7acce79..12eb9998 100644 --- a/EQMODAlignment/Model/AlignmentModel_Math.cs +++ b/EQMODAlignment/Model/AlignmentModel_Math.cs @@ -279,7 +279,7 @@ partial class AlignmentModel - private double Get_EncoderHours(double RAencoderPosition) + public double Get_EncoderHours(double RAencoderPosition) { double hours; diff --git a/EQMODAlignment/Model/AlignmentPoint.cs b/EQMODAlignment/Model/AlignmentPoint.cs index 933bdafa..f39b3a21 100644 --- a/EQMODAlignment/Model/AlignmentPoint.cs +++ b/EQMODAlignment/Model/AlignmentPoint.cs @@ -45,17 +45,22 @@ public class AlignmentPoint /// /// The cartesean version of the unadjusted encoder positions /// - [JsonIgnore] public Coord TargetCartesian { get; set;} + [JsonIgnore] public EncoderPosition Delta => (Target - Encoder); + public AlignmentPoint() + { + + } + public AlignmentPoint(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) { Encoder = new EncoderPosition(encoder); OrigRaDec = new AxisPosition(origRaDec); Target = new EncoderPosition(target); - + AlignTime = syncTime; } } diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs new file mode 100644 index 00000000..3ce6ee4d --- /dev/null +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -0,0 +1,102 @@ +using System; +using System.IO; +using EqmodNStarAlignment.DataTypes; +using EqmodNStarAlignment.Model; +using EqmodNStarAlignment.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; + +namespace EqmodNStarAlignment.Tests +{ + [TestClass] + public class AlignmentModelTests + { + const double siteLatitude = 52.6683333333333; + const double siteLongitude = -1.33888888888889; + const double siteElevation = 200d; + const long decHomePos = 9003008; + const long raHomePos = 8388608; + const double doubleDelta = 0.00000001; + + const HemisphereEnum hemisphere = HemisphereEnum.Northern; + + private EncoderPosition stepsPerRev = new EncoderPosition(2457601, 2457601); + + private AlignmentModel AlignmentModel; + + [TestInitialize] + public void Initialize() + { + AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); + AlignmentModel.SetHomePosition(raHomePos, decHomePos); + AlignmentModel.PolarEnable = true; + } + + + [TestMethod] + public void SavePointsTest() + { + string outputFile = Path.Combine(Directory.GetCurrentDirectory(), "AlignmentPointsOut.json"); + if (File.Exists(outputFile)) + { + File.Delete(outputFile); + } + + AlignmentPoint pt1 = new AlignmentPoint(new EncoderPosition(8987817, 8919464), new double[] { 23.6715774536133, 77.7643051147461 }, new EncoderPosition(8987821, 8919479), new DateTime(2022, 11, 28, 19, 06, 06)); + AlignmentPoint pt2 = new AlignmentPoint(new EncoderPosition(7985357, 9135000), new double[] { 21.481803894043, 70.6648559570313 }, new EncoderPosition(7985268, 9135003), new DateTime(2022, 11, 28, 19, 07, 17)); + AlignmentPoint pt3 = new AlignmentPoint(new EncoderPosition(7847708, 9164640), new double[] { 22.8413619995117, 66.3250198364258 }, new EncoderPosition(7847528, 9164630), new DateTime(2022, 11, 28, 19, 08, 09)); + + AlignmentModel.EQ_NPointAppend(pt1); + AlignmentModel.EQ_NPointAppend(pt2); + AlignmentModel.EQ_NPointAppend(pt3); + + AlignmentModel.SaveAlignmentPoints(outputFile); + + Assert.IsTrue(File.Exists(outputFile)); + } + + [TestMethod] + public void LoadPointsTest() + { + string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); + + Matrix ExpectedTaki = Matrix.CreateInstance(); + ExpectedTaki.Element[0, 0] = 0.999962437601123; + ExpectedTaki.Element[0, 1] = -1.03237679560398E-03; + ExpectedTaki.Element[0, 2] = 0; + ExpectedTaki.Element[1, 0] = 4.1772366345733E-04; + ExpectedTaki.Element[1, 1] = 0.999904533164291; + ExpectedTaki.Element[1, 2] = 0; + ExpectedTaki.Element[2, 0] = 0; + ExpectedTaki.Element[2, 1] = 0; + ExpectedTaki.Element[2, 2] = 1; + + Matrix ExpectedAffine = Matrix.CreateInstance(); + ExpectedAffine.Element[0, 0] = 1.00003713248826; + ExpectedAffine.Element[0, 1] = 1.03251370113913E-03; + ExpectedAffine.Element[1, 0] = -4.17779058621084E-04; + ExpectedAffine.Element[1, 1] = 1.00009504460391; + + AlignmentModel.ClearAlignmentPoints(); + + AlignmentModel.LoadAlignmentPoints(inputFile); + + Assert.IsTrue(AlignmentModel.AlignmentPoints.Count == 3); + + Assert.AreEqual(ExpectedTaki.Element[0, 0], AlignmentModel.EQMT.Element[0, 0], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[0, 1], AlignmentModel.EQMT.Element[0, 1], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[0, 2], AlignmentModel.EQMT.Element[0, 2], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[1, 0], AlignmentModel.EQMT.Element[1, 0], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[1, 1], AlignmentModel.EQMT.Element[1, 1], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[1, 2], AlignmentModel.EQMT.Element[1, 2], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[2, 0], AlignmentModel.EQMT.Element[2, 0], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[2, 1], AlignmentModel.EQMT.Element[2, 1], 0.00000001); + Assert.AreEqual(ExpectedTaki.Element[2, 2], AlignmentModel.EQMT.Element[2, 2], 0.00000001); + + Assert.AreEqual(ExpectedAffine.Element[0, 0], AlignmentModel.EQMM.Element[0, 0], 0.00000001); + Assert.AreEqual(ExpectedAffine.Element[0, 1], AlignmentModel.EQMM.Element[0, 1], 0.00000001); + Assert.AreEqual(ExpectedAffine.Element[1, 0], AlignmentModel.EQMM.Element[1, 0], 0.00000001); + Assert.AreEqual(ExpectedAffine.Element[1, 1], AlignmentModel.EQMM.Element[1, 1], 0.00000001); + + } + } +} diff --git a/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json b/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json new file mode 100644 index 00000000..b1bf1ca9 --- /dev/null +++ b/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json @@ -0,0 +1,80 @@ +[ + { + "Id": 1, + "AlignTime": "2022-11-28T19:06:06", + "Encoder": { + "RA": 8987817, + "Dec": 8919464 + }, + "EncoderCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "OrigRaDec": { + "RA": 23.6715774536133, + "Dec": 77.7643051147461 + }, + "Target": { + "RA": 8987821, + "Dec": 8919479 + }, + "TargetCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + }, + { + "Id": 2, + "AlignTime": "2022-11-28T19:07:17", + "Encoder": { + "RA": 7985357, + "Dec": 9135000 + }, + "EncoderCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "OrigRaDec": { + "RA": 21.481803894043, + "Dec": 70.6648559570313 + }, + "Target": { + "RA": 7985268, + "Dec": 9135003 + }, + "TargetCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + }, + { + "Id": 3, + "AlignTime": "2022-11-28T19:08:09", + "Encoder": { + "RA": 7847708, + "Dec": 9164640 + }, + "EncoderCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + }, + "OrigRaDec": { + "RA": 22.8413619995117, + "Dec": 66.3250198364258 + }, + "Target": { + "RA": 7847528, + "Dec": 9164630 + }, + "TargetCartesian": { + "x": 0.0, + "y": 0.0, + "z": 0.0 + } + } +] \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj index 571a88cf..45b55d0a 100644 --- a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj +++ b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj @@ -50,12 +50,22 @@ - + + + + PreserveNewest + + + + {b2375ca6-17ae-4875-b33d-b276781cc1da} + EqmodNStarAlignment + + diff --git a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs new file mode 100644 index 00000000..49a1ab93 --- /dev/null +++ b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs @@ -0,0 +1,90 @@ +using EqmodNStarAlignment.DataTypes; +using EqmodNStarAlignment.Model; +using EqmodNStarAlignment.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace EqmodNStarAlignment.Tests +{ + + [TestClass] + public class EqmodVectorTests + { + const double siteLatitude = 52.6683333333333; + const double siteLongitude = -1.33888888888889; + const double siteElevation = 200d; + const long decHomePos = 9003008; + const long raHomePos = 8388608; + const double doubleDelta = 0.00000001; + + const HemisphereEnum hemisphere = HemisphereEnum.Northern; + + private EncoderPosition stepsPerRev = new EncoderPosition(2457601, 2457601); + + private AlignmentModel AlignmentModel; + + [TestInitialize] + public void Initialize() + { + AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); + AlignmentModel.SetHomePosition(raHomePos, decHomePos); + AlignmentModel.PolarEnable = true; + } + + [TestMethod] + public void TestEQ_sp2Cs_1() + { + EncoderPosition encoder = new EncoderPosition(8619721, 8850776); + Coord expected = new Coord() + { + x = 322188.53833622788, + y = -258342.03199652123, + z = 1 + }; + Coord result = AlignmentModel.EQ_sp2Cs(encoder); + Assert.AreEqual(expected.x, result.x, 1.0); + Assert.AreEqual(expected.y, result.y, 1.0); + Assert.AreEqual(expected.z, result.z); + } + + [TestMethod] + public void TestEQ_sp2Cs_2() + { + EncoderPosition encoder = new EncoderPosition(8487504, 8913867); + Coord expected = new Coord() + { + x = 456444.627886648, + y = -182935.356983078, + z = 1 + }; + Coord result = AlignmentModel.EQ_sp2Cs(encoder); + Assert.AreEqual(expected.x, result.x, 1.0); + Assert.AreEqual(expected.y, result.y, 1.0); + Assert.AreEqual(expected.z, result.z); + } + + [TestMethod] + public void TestHaDec2AltAz() + { + double ha = 4.48782288093145; + double dec = 269.701135375515; + + double[] expected = new double[] { -52.7827108032482, 179.544092452796 }; + double[] result = AstroConvert.HaDec2AltAz(ha, dec, siteLatitude); + + Assert.AreEqual(expected[0], result[0], doubleDelta); + Assert.AreEqual(expected[1], result[1], doubleDelta); + + } + + [TestMethod] + public void TestGet_EncoderHours() + { + double expected = 1.4054315570346851; + double result = AlignmentModel.Get_EncoderHours(8859092); + Assert.AreEqual(expected, result, doubleDelta); + } + + + } +} diff --git a/EqmodNStarAlignment.Tests/UnitTest1.cs b/EqmodNStarAlignment.Tests/UnitTest1.cs deleted file mode 100644 index e30b9044..00000000 --- a/EqmodNStarAlignment.Tests/UnitTest1.cs +++ /dev/null @@ -1,14 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; - -namespace EqmodNStarAlignment.Tests -{ - [TestClass] - public class UnitTest1 - { - [TestMethod] - public void TestMethod1() - { - } - } -} From 41efbb15b25606bcbcb31dbe7c75b5edc80c3a35 Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Mon, 12 Dec 2022 21:47:08 +0000 Subject: [PATCH 04/18] WIP check-in. The coordinate type (PolarSpherical, Cartes2Polar etc) seem to be producing the same results as EQMOD (tests with one point in each quadrant). Matrix mapping is not working yet. --- EQMODAlignment/DataTypes/EqascomDataTypes.cs | 43 +- EQMODAlignment/EqmodNStarAlignment.csproj | 3 +- EQMODAlignment/Model/AlignmentModel.cs | 15 + .../Model/AlignmentModel_EqModVector.cs | 1060 ++++++++--------- .../Model/AlignmentModel_EqmodAlignment.cs | 9 +- EQMODAlignment/Model/AlignmentModel_Math.cs | 424 ++++--- EQMODAlignment/Utilities/AstroConvert.cs | 216 ++-- EQMODAlignment/Utilities/Range.cs | 19 + .../AlignmentModelTests.cs | 318 ++++- .../AstroConvertTests.cs | 113 ++ .../Data/AlignmentPointsIn.json | 556 ++++++++- .../EqmodNStarAlignment.Tests.csproj | 8 + EqmodNStarAlignment.Tests/EqmodVectorTests.cs | 28 +- EqmodNStarAlignment.Tests/Legacy.cs | 92 ++ EqmodNStarAlignment.Tests/RangeTests.cs | 21 + EqmodNStarAlignment.Tests/astro32.dll | Bin 0 -> 28672 bytes 16 files changed, 1915 insertions(+), 1010 deletions(-) create mode 100644 EqmodNStarAlignment.Tests/AstroConvertTests.cs create mode 100644 EqmodNStarAlignment.Tests/Legacy.cs create mode 100644 EqmodNStarAlignment.Tests/RangeTests.cs create mode 100644 EqmodNStarAlignment.Tests/astro32.dll diff --git a/EQMODAlignment/DataTypes/EqascomDataTypes.cs b/EQMODAlignment/DataTypes/EqascomDataTypes.cs index 3dca2d0b..0db167b2 100644 --- a/EQMODAlignment/DataTypes/EqascomDataTypes.cs +++ b/EQMODAlignment/DataTypes/EqascomDataTypes.cs @@ -94,14 +94,13 @@ public static Matrix CreateInstance() // } //} - //[Serializable] - //public struct Coordt - //{ - // public double x; //x = X Coordinate - // public double y; //y = Y Coordinate - // public double z; - // public short f; - //} + public struct Coordt + { + public double x; //x = X Coordinate + public double y; //y = Y Coordinate + public double z; + public short f; + } public struct CartesCoord { @@ -109,6 +108,14 @@ public struct CartesCoord public double y; //y = Y Coordinate public double r; // Radius Sign public double ra; // Radius Alpha + + public CartesCoord(double xValue, double yValue, double rValue, double raValue) + { + x = xValue; + y = yValue; + r = rValue; + ra = raValue; + } } public struct SphericalCoord @@ -116,15 +123,21 @@ public struct SphericalCoord public double x; //x = X Coordinate public double y; //y = Y Coordinate public double r; //r = RA Range Flag + + public SphericalCoord(double xValue, double yValue, double rValue) + { + x = xValue; + y = yValue; + r = rValue; + } } - //[Serializable] - //public struct TriangleCoord - //{ - // public double i; // Offset 1 - // public double j; // Offset 2 - // public double k; // offset 3 + public struct TriangleCoord + { + public double i; // Offset 1 + public double j; // Offset 2 + public double k; // offset 3 - //} + } } diff --git a/EQMODAlignment/EqmodNStarAlignment.csproj b/EQMODAlignment/EqmodNStarAlignment.csproj index cd7fa4a7..37bf423a 100644 --- a/EQMODAlignment/EqmodNStarAlignment.csproj +++ b/EQMODAlignment/EqmodNStarAlignment.csproj @@ -1,4 +1,4 @@ - + netstandard2.0 @@ -23,5 +23,4 @@ - diff --git a/EQMODAlignment/Model/AlignmentModel.cs b/EQMODAlignment/Model/AlignmentModel.cs index 9c1b5191..c1d04e22 100644 --- a/EQMODAlignment/Model/AlignmentModel.cs +++ b/EQMODAlignment/Model/AlignmentModel.cs @@ -42,6 +42,15 @@ public enum ActivePointsEnum LocalQuadrant } + [TypeConverter(typeof(EnumTypeConverter))] + public enum ThreePointAlgorithmEnum + { + [Description("Best Centre")] + BestCentre, + [Description("Closest Points")] + ClosestPoints + } + public enum HemisphereEnum { Northern, @@ -156,6 +165,8 @@ public bool PolarEnable public bool CheckLocalPier { get; set; } + public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set;} = ThreePointAlgorithmEnum.BestCentre; + public EncoderPosition HomeEncoder { get; private set; } public void SetHomePosition(long RAEncoder, long decEncoder) @@ -179,8 +190,12 @@ public void SetHomePosition(long RAEncoder, long decEncoder) public AlignmentPointCollection AlignmentPoints { get; } = new AlignmentPointCollection(); + public AlignmentPoint SelectedAlignmentPoint {get; private set; } + public DateTime? LastAccessDateTime { get; private set; } + public int NStarMaxCombinationCount { get; set; } = 50; + // String builder for building more detailed messages. private readonly StringBuilder _stringBuilder = new StringBuilder(); diff --git a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs index 39858b48..7a853d30 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs @@ -76,6 +76,8 @@ You should have received a copy of the GNU General Public License using EqmodNStarAlignment.Utilities; using System; using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; using System.Text; namespace EqmodNStarAlignment.Model @@ -169,7 +171,7 @@ private Matrix GETPQ(Coord p1, Coord p2, Coord p3) // Subroutine to draw the Transformation Matrix (Taki Method) - private int EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + private bool EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) { @@ -243,7 +245,7 @@ private int EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord if ((x + Y) == 0) { - return 0; + return false; } else { @@ -272,7 +274,7 @@ private int EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord // Subroutine to draw the Transformation Matrix (Affine Mapping Method) - private int EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + private bool EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) { double Det = 0; @@ -315,7 +317,7 @@ private int EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coo if ((x + Y) == 0) { - return 0; + return false; } else { @@ -325,19 +327,18 @@ private int EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coo } - ////Function to transform the Coordinates (Affine Mapping) using the M Matrix and Offset Vector - - //private Coord EQ_Transform_Affine(Coord ob) - //{ - - // // CoordTransform = Offset + CoordObject * Matrix M - - // Coord result = new Coord(); - // result.x = EQCO.x + ((ob.x * EQMM.Element[0, 0]) + (ob.y * EQMM.Element[1, 0])); - // result.y = EQCO.y + ((ob.x * EQMM.Element[0, 1]) + (ob.y * EQMM.Element[1, 1])); - - // return result; - //} + /// + /// Function to transform the Coordinates (Affine Mapping) using the M Matrix and Offset Vector + /// + /// + /// + private CartesCoord EQ_Transform_Affine(CartesCoord pos) + { + CartesCoord result = new CartesCoord(); + result.x = EQCO.x + ((pos.x * EQMM.Element[0, 0]) + (pos.y * EQMM.Element[1, 0])); + result.y = EQCO.y + ((pos.x * EQMM.Element[0, 1]) + (pos.y * EQMM.Element[1, 1])); + return result; + } //Function to convert spherical coordinates to Cartesian using the Coord structure @@ -431,52 +432,42 @@ public Coord EQ_sp2Cs(EncoderPosition pos) // return result; //} - ////Implement an Affine transformation on a Polar coordinate system - ////This is done by converting the Polar Data to Cartesian, Apply affine transformation - ////Then restore the transformed Cartesian Coordinates back to polar - - - //internal Coord EQ_plAffine(Coord obj) - //{ - // Coord result = new Coord(); - // double gDECEncoder_Home_pos = 0; - // double gLatitude = 0; - // double gTot_step = 0; - // object HC = null; - // double RAEncoder_Home_pos = 0; - // CartesCoord tmpobj1 = new CartesCoord(); - // Coord tmpobj2 = new Coord(); - // Coord tmpobj3 = new Coord(); - // SphericalCoord tmpobj4 = new SphericalCoord(); - - // if (PolarEnable) - // { - // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); - - // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - - // tmpobj2.x = tmpobj1.x; - // tmpobj2.y = tmpobj1.y; - // tmpobj2.z = 1; - - // tmpobj3 = EQ_Transform_Affine(tmpobj2); + /// + /// Implement an Affine transformation on a Polar coordinate system + /// This is done by converting the Polar Data to Cartesian, Apply affine transformation + /// Then restore the transformed Cartesian Coordinates back to polar + /// + /// + /// + internal EncoderPosition EQ_plAffine(EncoderPosition pos) + { + EncoderPosition result = new EncoderPosition(); + CartesCoord tmpobj1 = new CartesCoord(); + CartesCoord tmpobj3 = new CartesCoord(); + SphericalCoord tmpobj2 = new SphericalCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); - // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + if (PolarEnable) + { + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj1 = EQ_Polar2Cartes(tmpobj4); + tmpobj3 = EQ_Transform_Affine(tmpobj1); + tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); - // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); + result = EQ_PolarSpherical(tmpobj2, tmpobj4); - // } - // else - // { - // tmpobj3 = EQ_Transform_Affine(obj); - // result.x = tmpobj3.x; - // result.y = tmpobj3.y; - // result.z = 1; - // } + } + else + { + tmpobj3 = EQ_Transform_Affine(new CartesCoord() { x = pos.RA, y = pos.Dec }); + result.RA = (long)Math.Round(tmpobj3.x, 0); + result.Dec = (long)Math.Round(tmpobj3.y, 0); + // result.z = 1; + } - // return result; - //} + return result; + } //internal Coord EQ_plAffine2(Coord obj) @@ -566,8 +557,11 @@ public Coord EQ_sp2Cs(EncoderPosition pos) // return result; //} - // Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates - + /// + /// Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates + /// + /// + /// private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) { CartesCoord result = new CartesCoord(); @@ -622,78 +616,74 @@ private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) ////Function to convert the Cartesian Coordinate data back to RA/DEC polar - //private Coord EQ_Cartes2Polar(double x, double Y, double r, double RA, double TOT, double RACENTER, double DECCENTER) - //{ - // Coord result = new Coord(); - // double PI = 0; - // double RAD_DEG = 0; - - - // // Ah the famous radius formula - - // double radiusder = Math.Sqrt((x * x) + (Y * Y)) * r; + private SphericalCoord EQ_Cartes2Polar(CartesCoord cart, CartesCoord rads) + { + SphericalCoord result = new SphericalCoord(); + // Ah the famous radius formula + double radiusder = Math.Sqrt((cart.x * cart.x) + (cart.y * cart.y)) * rads.r; - // // And the nasty angle compute routine (any simpler way to impelent this ?) - // double angle = 0; - // if (x > 0) - // { - // angle = Math.Atan(Y / x); - // } - // if (x < 0) - // { - // if (Y >= 0) - // { - // angle = Math.Atan(Y / x) + PI; + // And the nasty angle compute routine (any simpler way to impelent this ?) - // } - // else - // { - // angle = Math.Atan(Y / x) - PI; - // } - // } - // if (x == 0) - // { - // if (Y > 0) - // { - // angle = PI / 2d; - // } - // else - // { - // angle = -1 * (PI / 2d); - // } - // } + double angle = 0; + if (cart.x > 0) + { + angle = Math.Atan(cart.y / cart.x); + } + if (cart.x < 0) + { + if (cart.y >= 0) + { + angle = Math.Atan(cart.y / cart.x) + Math.PI; + + } + else + { + angle = Math.Atan(cart.y / cart.x) - Math.PI; + } + } + if (cart.x == 0) + { + if (cart.y > 0) + { + angle = Math.PI / 2d; + } + else + { + angle = -1 * (Math.PI / 2d); + } + } - // // Convert angle to degrees + // Convert angle to degrees - // angle *= RAD_DEG; + angle = AstroConvert.RadToDeg(angle); - // if (angle < 0) - // { - // angle = 360 + angle; - // } + if (angle < 0) + { + angle = 360 + angle; + } - // if (r < 0) - // { - // angle = Range.Range360((angle + 180)); - // } + if (rads.r < 0) + { + angle = Range.Range360((angle + 180)); + } - // if (angle > 180) - // { - // result.x = RACENTER - (((360 - angle) / 360d) * TOT); - // } - // else - // { - // result.x = ((angle / 360d) * TOT) + RACENTER; - // } + if (angle > 180) + { + result.x = this.HomeEncoder.RA - (((360 - angle) / 360d) * this.StepsPerRev.RA); + } + else + { + result.x = ((angle / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; + } - // //treat y as the polar coordinate radius (ra var not used - always 0) + //treat y as the polar coordinate radius (ra var not used - always 0) - // result.y = radiusder + DECCENTER + RA; + result.y = radiusder + this.HomeEncoder.Dec + rads.ra; - // return result; - //} + return result; + } //internal int EQ_UpdateTaki(double x, double Y) //{ @@ -738,53 +728,45 @@ private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) //} - //internal int EQ_UpdateAffine(AxisPosition encoder) - //{ - // int result = 0; - // int g3PointAlgorithm = 0; - // int gAlignmentStars_count = 0; - - // TriangleCoord tr = new TriangleCoord(); + internal bool EQ_UpdateAffine(EncoderPosition pos) + { + bool result = false; - // if (gAlignmentStars_count < 3) - // { - // return result; - // } + List nearestPoints = new List(); - // switch (g3PointAlgorithm) - // { - // case 1: - // // find the 50 nearest points - then find the nearest enclosing triangle - // tr = EQ_ChooseNearest3Points(encoder); - // break; - // default: - // // find the 50 nearest points - then find the enclosing triangle with the nearest centre point - // tr = EQ_Choose_3Points(encoder); - // break; - // } - - // double gAffine1 = tr.i; - // double gAffine2 = tr.j; - // double gAffine3 = tr.k; + if (this.AlignmentPoints.Count < 3) + { + return result; + } - // if (gAffine1 == 0 || gAffine1 == 0 || gAffine1 == 0) - // { - // return 0; - // } + switch (this.ThreePointAlgorithm) + { + case ThreePointAlgorithmEnum.BestCentre: + // find the 50 nearest points - then find the nearest enclosing triangle + nearestPoints = EQ_ChooseNearest3Points(pos); + break; + default: + // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + nearestPoints = EQ_Choose_3Points(pos); + break; + } - // Coord tmpcoord = EQ_sp2Cs(encoder); - // result = EQ_AssembleMatrix_Affine(tmpcoord.x, tmpcoord.y, EQASCOM.my_PointsC[Convert.ToInt32(gAffine1)], EQASCOM.my_PointsC[Convert.ToInt32(gAffine2)], EQASCOM.my_PointsC[Convert.ToInt32(gAffine3)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine1)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine2)], EQASCOM.ct_PointsC[Convert.ToInt32(gAffine3)]); + if (nearestPoints.Count < 3) + { + return false; + } - // if (result == 0) - // { - // gAffine1 = 0; - // gAffine2 = 0; - // gAffine3 = 0; - // } + Coord tmpcoord = EQ_sp2Cs(pos); - // return result; - //} + return EQ_AssembleMatrix_Affine(tmpcoord.x, tmpcoord.y, + nearestPoints[0].EncoderCartesian, + nearestPoints[1].EncoderCartesian, + nearestPoints[2].EncoderCartesian, + nearestPoints[0].TargetCartesian, + nearestPoints[1].TargetCartesian, + nearestPoints[1].TargetCartesian); + } //// Subroutine to implement find Array index with the lowest value //private int EQ_FindLowest(double[] List, int min, int max) @@ -1166,7 +1148,7 @@ private double EQ_Triangle_Area(double px1, double py1, double px2, double py2, // Function to check if a point is inside the triangle. Computed based sum of areas method - private int EQ_CheckPoint_in_Triangle(double px, double py, double px1, double py1, double px2, double py2, double px3, double py3) + private bool EQ_CheckPoint_in_Triangle(double px, double py, double px1, double py1, double px2, double py2, double px3, double py3) { @@ -1178,113 +1160,120 @@ private int EQ_CheckPoint_in_Triangle(double px, double py, double px1, double p if (Math.Abs(ta - t1 - t2 - t3) < 2) { - return 1; + return true; } else { - return 0; + return false; } } + /// + /// Returns the centroid of a triangle. + /// + /// + /// + /// + /// + private Coord EQ_GetCenterPoint(Coord p1, Coord p2, Coord p3) + { - //private Coord EQ_GetCenterPoint(Coord p1, Coord p2, Coord p3) - //{ - - // Coord result = new Coord(); - // double p2x = 0; - // double p2y = 0; - // double p4x = 0; - // double p4y = 0; - - - - + Coord result = new Coord(); + double p2x = 0d; + double p2y = 0d; + double p4x = 0d; + double p4y = 0d; - // // Get the two line 4 point data + // Get the two line 4 point data - // double p1x = p1.x; - // double p1y = p1.y; + double p1x = p1.x; + double p1y = p1.y; - // if (p3.x > p2.x) - // { - // p2x = ((p3.x - p2.x) / 2d) + p2.x; - // } - // else - // { - // p2x = ((p2.x - p3.x) / 2d) + p3.x; - // } + if (p3.x > p2.x) + { + p2x = ((p3.x - p2.x) / 2d) + p2.x; + } + else + { + p2x = ((p2.x - p3.x) / 2d) + p3.x; + } - // if (p3.y > p2.y) - // { - // p2y = ((p3.y - p2.y) / 2d) + p2.y; - // } - // else - // { - // p2y = ((p2.y - p3.y) / 2d) + p3.y; - // } + if (p3.y > p2.y) + { + p2y = ((p3.y - p2.y) / 2d) + p2.y; + } + else + { + p2y = ((p2.y - p3.y) / 2d) + p3.y; + } - // double p3x = p2.x; - // double p3y = p2.y; + double p3x = p2.x; + double p3y = p2.y; - // if (p1.x > p3.x) - // { - // p4x = ((p1.x - p3.x) / 2d) + p3.x; - // } - // else - // { - // p4x = ((p3.x - p1.x) / 2d) + p1.x; - // } + if (p1.x > p3.x) + { + p4x = ((p1.x - p3.x) / 2d) + p3.x; + } + else + { + p4x = ((p3.x - p1.x) / 2d) + p1.x; + } - // if (p1.y > p3.y) - // { - // p4y = ((p1.y - p3.y) / 2d) + p3.y; - // } - // else - // { - // p4y = ((p3.y - p1.y) / 2d) + p1.y; - // } + if (p1.y > p3.y) + { + p4y = ((p1.y - p3.y) / 2d) + p3.y; + } + else + { + p4y = ((p3.y - p1.y) / 2d) + p1.y; + } - // double XD1 = p2x - p1x; - // double XD2 = p4x - p3x; - // double YD1 = p2y - p1y; - // double YD2 = p4y - p3y; - // double XD3 = p1x - p3x; - // double YD3 = p1y - p3y; + double XD1 = p2x - p1x; + double XD2 = p4x - p3x; + double YD1 = p2y - p1y; + double YD2 = p4y - p3y; + double XD3 = p1x - p3x; + double YD3 = p1y - p3y; - // double dv = (YD2 * XD1) - (XD2 * YD1); + double dv = (YD2 * XD1) - (XD2 * YD1); - // if (dv == 0) - // { - // dv = 0.00000001d; - // } //avoid div 0 errors + if (dv == 0) + { + dv = 0.00000001d; + } //avoid div 0 errors - // double ua = ((XD2 * YD3) - (YD2 * XD3)) / dv; - // double ub = ((XD1 * YD3) - (YD1 * XD3)) / dv; + double ua = ((XD2 * YD3) - (YD2 * XD3)) / dv; + double ub = ((XD1 * YD3) - (YD1 * XD3)) / dv; - // result.x = p1x + (ua * XD1); - // result.y = p1y + (ub * YD1); + result.x = p1x + (ua * XD1); + result.y = p1y + (ub * YD1); - // return result; - //} + return result; + } - public SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) + private SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) { + //Debug.WriteLine($"Spherical -> Polar"); + //Debug.WriteLine($"Input = {spherical.RA}/{spherical.Dec}"); SphericalCoord result = new SphericalCoord(); - double ha = Get_EncoderHours(spherical.RA); - double dec = Range.Range360(Get_EncoderDegrees(spherical.Dec) + 270); - - double[] altAz = AstroConvert.HaDec2AltAz(ha, dec, SiteLatitude); - + double haRad = AstroConvert.HrsToRad(Get_EncoderHours(spherical.RA)); + double decRad = AstroConvert.DegToRad(Range.Range360(Get_EncoderDegrees(spherical.Dec) + 270)); + double latRad = AstroConvert.DegToRad(this.SiteLatitude); + //Debug.WriteLine($"lat/ha/dec (Radians) = {latRad}/{haRad}/{decRad}"); + double[] altAzRad = AstroConvert.GetAltAz(latRad, haRad, decRad); + //Debug.WriteLine($"alt/Az (Radians) = {altAzRad[0]}/{altAzRad[1]}"); + double[] altAz = new double[] { AstroConvert.RadToDeg(altAzRad[0]), AstroConvert.RadToDeg(altAzRad[1])}; + //Debug.WriteLine($"alt/Az = {altAz[0]}/{altAz[1]}"); result.x = (((altAz[1] - 180) / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; result.y = (((altAz[0] + 90) / 180d) * this.StepsPerRev.Dec) + this.HomeEncoder.Dec; @@ -1299,69 +1288,76 @@ public SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) { result.r = 0; } - + //Debug.WriteLine($"Output = {result.x}/{result.y}/{result.r}"); return result; } - //private Coord EQ_PolarSpherical(double RA, double DEC, double TOT, double RACENTER, double DECCENTER, double Latitude, double range) - //{ - // Coord result = new Coord(); - // double x = 0; - // double y = 0; - - - // double i = (((RA - RACENTER) / TOT) * 360) + 180; - // double j = (((DEC - DECCENTER) / TOT) * 180) - 90; - - // object tempAuxVar = aa_hadec[Convert.ToInt32(Latitude * DEG_RAD), Convert.ToInt32(j * DEG_RAD), Convert.ToInt32(i * DEG_RAD), Convert.ToInt32(x), Convert.ToInt32(y)]; - - // if (i > 180) - // { - // if (range == 0) - // { - // y = Range.Range360(180 - AstroConvert.RadToDeg(y)); - // } - // else - // { - // y = Range.Range360(AstroConvert.RadToDeg(y)); - // } - // } - // else - // { - // if (range == 0) - // { - // y = Range.Range360(AstroConvert.RadToDeg(y)); - // } - // else - // { - // y = Range.Range360(180 - AstroConvert.RadToDeg(y)); - // } - // } + private EncoderPosition EQ_PolarSpherical(SphericalCoord pos, SphericalCoord range) + { + //Debug.WriteLine($"Polar -> Spherical"); + //Debug.WriteLine($"Input = {pos.x}/{pos.y}/{range.r}"); + EncoderPosition result = new EncoderPosition(); + double az = (((pos.x - this.HomeEncoder.RA) / this.StepsPerRev.RA) * 360) + 180; + double azRad = AstroConvert.DegToRad(az); + double alt = (((pos.y - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 180) - 90; + double altRad = AstroConvert.DegToRad(alt); + double latRad = AstroConvert.DegToRad(this.SiteLatitude); + //Debug.WriteLine($"az/alt (Degrees) = {az}/{alt}"); + //Debug.WriteLine($"lat/alt/Az (Radians) = {latRad}/{altRad}/{azRad}"); + double[] haDecRad = AstroConvert.GetHaDec(latRad, altRad, azRad); + //Debug.WriteLine($"ha/dec (Radians) = {haDecRad[0]}/{haDecRad[1]}"); + double[] haDec = new double[] { AstroConvert.RadToHrs(haDecRad[0]), AstroConvert.RadToDeg(haDecRad[1]) }; + //Debug.WriteLine($"ha/dec = {haDec[0]}/{haDec[1]}"); + + if (az > 180) + { + if (range.r == 0) + { + haDec[1] = Range.Range360(180 - haDec[1]); + } + else + { + haDec[1] = Range.Range360(haDec[1]); + } + } + else + { + if (range.r == 0) + { + haDec[1] = Range.Range360(haDec[1]); + } + else + { + haDec[1] = Range.Range360(180 - haDec[1]); + } + } - // j = Range.Range360(y + 90); + alt = Range.Range360(haDec[1] + 90); - // if (j < 180) - // { - // if (range == 1) - // { - // x = Range.Range24(AstroConvert.RadToHrs(x)); - // } - // else - // { - // x = Range.Range24(24 + AstroConvert.RadToHrs(x)); - // } - // } - // else - // { - // x = Range.Range24(12 + AstroConvert.RadToHrs(x)); - // } + if (alt < 180) + { + if (range.r == 1) + { + haDec[0] = Range.Range24(haDec[0]); + } + else + { + haDec[0] = Range.Range24(24 + haDec[0]); + } + } + else + { + haDec[0] = Range.Range24(12 + haDec[0]); + } + //Debug.WriteLine($"X/Y = {haDec[0]}/{haDec[1]}"); - // result.x = Get_EncoderfromHours(this.HomeEncoder.RA, x, this.StepsPerRev.RA, 0); - // result.y = Get_EncoderfromDegrees(this.HomeEncoder.Dec, y + 90, this.StepsPerRev.Dec, 0, 0); + result.RA = Get_EncoderfromHours(haDec[0]); + result.Dec = Get_EncoderfromDegrees(haDec[1] + 90); - // return result; - //} + //Debug.WriteLine($"Output = {result.RA}/{result.Dec}"); + return result; + } //private CartesCoord EQ_Spherical2Cartes(double RA, double DEC, double TOT, double RACENTER, double DECCENTER) @@ -1394,314 +1390,226 @@ public SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) //} + /// + /// Returns the 3 points making up at triangle with the centre nearest the position + /// + /// + /// List of 3 points or an empty list + internal List EQ_Choose_3Points(EncoderPosition pos) + { + Dictionary distances = new Dictionary(); + List results = new List(); + // Adjust only if there are three alignment stars - //internal TriangleCoord EQ_Choose_3Points(AxisPosition encoder) - //{ - // TriangleCoord result = new TriangleCoord(); - // Coord tmpcoords = new Coord(); - // Coord p1 = new Coord(); - // Coord p2 = new Coord(); - // Coord p3 = new Coord(); - // Coord pc = new Coord(); - - // Tdatholder[] datholder = new Tdatholder[EQASCOM.MAX_STARS]; - // double combi_cnt = 0; - // double tmp1 = 0; - // int tmp2 = 0; - // bool first = false; - // double last_dist = 0; - // double new_dist = 0; - - // // Adjust only if there are three alignment stars - - // if (AlignmentPoints.Count < 3) - // { - // result.i = 1; - // result.j = 2; - // result.k = 3; - // return result; - // } - - // Coord tmpcoord = EQ_sp2Cs(encoder); - - // int Count = 0; - // for (int i = 0; i < EQASCOM.gAlignmentStars_count; i++) - // { - - // datholder[Count].cc = EQASCOM.my_PointsC[i]; - // switch (ActivePoints) - // { - // case ActivePointsEnum.All: - // // all points - - // break; - // case ActivePointsEnum.PierSide: - // // only consider points on this side of the meridian - // if (datholder[Count].cc.y * tmpcoord.y < 0) - // { - // goto NextPoint; - // } - - // break; - // case ActivePointsEnum.LocalQuadrant: - // // local quadrant - // if (!GetQuadrant(tmpcoord).Equals(GetQuadrant(datholder[Count].cc))) - // { - // goto NextPoint; - // } - - // break; - // } - - // if (CheckLocalPier) - // { - // // calculate polar distance - // datholder[Count].dat = Math.Pow(EQASCOM.my_Points[i].x - x, 2) + Math.Pow(EQASCOM.my_Points[i].y - Y, 2); - // } - // else - // { - // // calculate cartesian disatnce - // datholder[Count].dat = Math.Pow(datholder[Count].cc.x - tmpcoord.x, 2) + Math.Pow(datholder[Count].cc.y - tmpcoord.y, 2); - // } - - // // Also save the reference star id for this particular reference star - // datholder[Count].idx = Convert.ToInt16(i); - - // Count++; - // NextPoint:; - // } - - // if (Count < 3) - // { - // // not enough points to do 3-point - // result.i = 0; - // result.j = 0; - // result.k = 0; - // return result; - // } - - // // now sort the disatnces so the closest stars are at the top - // EQ_Quicksort2(datholder, 1, Count); - - // //Just use the nearest 50 stars (max) - saves processing time - // if (Count > EQASCOM.gMaxCombinationCount - 1) - // { - // combi_cnt = EQASCOM.gMaxCombinationCount; - // } - // else - // { - // combi_cnt = Count; - // } - - // // combi_offset = 1 - // tmp1 = combi_cnt - 1; - // tmp2 = Convert.ToInt32(combi_cnt - 2); - // first = true; - // // iterate through all the triangles posible using the nearest alignment points - // int l = 1; - // int m = 2; - // int n = 3; - // int tempForEndVar2 = (tmp2); - // for (int i = 1; i <= tempForEndVar2; i++) - // { - // p1 = datholder[Convert.ToInt32(i) - 1].cc; - // double tempForEndVar3 = (tmp1); - // for (int j = i + 1; j <= tempForEndVar3; j++) - // { - // p2 = datholder[Convert.ToInt32(j) - 1].cc; - // double tempForEndVar4 = combi_cnt; - // for (int k = (j + 1); k <= tempForEndVar4; k++) - // { - // p3 = datholder[Convert.ToInt32(k) - 1].cc; - - // if (EQ_CheckPoint_in_Triangle(tmpcoord.x, tmpcoord.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y) == 1) - // { - // // Compute for the center point - // pc = EQ_GetCenterPoint(p1, p2, p3); - // // don't need full pythagoras - sum of squares is good enough - // new_dist = Math.Pow(pc.x - tmpcoord.x, 2) + Math.Pow(pc.y - tmpcoord.y, 2); - - // if (first) - // { - // // first time through - // last_dist = new_dist; - // first = false; - // l = i; - // m = j; - // n = Convert.ToInt32(k); - // } - // else - // { - // if (new_dist < last_dist) - // { - // l = i; - // m = j; - // n = Convert.ToInt32(k); - // last_dist = new_dist; - // } - // } - // } - // } - // } - // } - - // if (first) - // { - // result.i = 0; - // result.j = 0; - // result.k = 0; - // } - // else - // { - // result.i = datholder[Convert.ToInt32(l) - 1].idx; - // result.j = datholder[Convert.ToInt32(m) - 1].idx; - // result.k = datholder[n - 1].idx; - // } - - // return result; - //} - - //internal TriangleCoord EQ_ChooseNearest3Points(AxisPosition encoder) - //{ - // TriangleCoord result = new TriangleCoord(); - // Coord p1 = new Coord(); - // Coord p2 = new Coord(); - // Coord p3 = new Coord(); - // Coord pc = new Coord(); - - // Tdatholder[] datholder = new Tdatholder[EQASCOM.MAX_STARS]; - // double combi_cnt = 0; - // double tmp1 = 0; - // int tmp2 = 0; - // bool first = false; + if (AlignmentPoints.Count <= 3) + { + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + results.Add(pt); + } + return results; + } - // // Adjust only if there are three alignment stars + Coord posCartesean = EQ_sp2Cs(pos); - // if (AlignmentPoints.Count <= 3) - // { - // result.i = 1; - // result.j = 2; - // result.k = 3; - // return result; - // } + // first find out the distances to the alignment stars + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + switch (this.ActivePoints) + { + case ActivePointsEnum.All: + // all points + + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.EncoderCartesian.y * posCartesean.y < 0) + { + continue; + } + + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.EncoderCartesian))) + { + continue; + } + + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); + } + } - // Coord tmpcoord = EQ_sp2Cs(encoder); + if (distances.Count < 3) + { + return results; // Empty list. + } - // int Count = 0; - // // first find out the distances to the alignment stars - // for (int i = 1; i <= EQASCOM.gAlignmentStars_count; i++) - // { + // now sort the distances so the closest stars are at the top + //Just use the nearest 50 stars (or max) - saves processing time + List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); - // datholder[Count].cc = EQASCOM.my_PointsC[Convert.ToInt32(i)]; + var tmp1 = sortedIds.Count - 1; + var tmp2 = tmp1 - 1; - // switch (ActivePoints) - // { - // case ActivePointsEnum.All: - // // all points + // iterate through all the triangles posible using the nearest alignment points + double minCentreDistance = double.MaxValue; + double centreDistance; + Coord triangleCentre; + for (int i = 0; i <= tmp2; i++) + { + var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); + for (int j = i + 1; j < tmp1; j++) + { + var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); + for (int k = (j + 1); k < sortedIds.Count; k++) + { + var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); + + + if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, + p1.EncoderCartesian.x, p1.EncoderCartesian.y, + p2.EncoderCartesian.x, p2.EncoderCartesian.y, + p3.EncoderCartesian.x, p3.EncoderCartesian.y)) + { + // Compute for the center point + triangleCentre = EQ_GetCenterPoint(p1.EncoderCartesian, p2.EncoderCartesian, p3.EncoderCartesian); + // don't need full pythagoras - sum of squares is good enough + centreDistance = Math.Pow(triangleCentre.x - posCartesean.x, 2) + Math.Pow(triangleCentre.y - posCartesean.y, 2); + if (centreDistance < minCentreDistance) + { + results = new List { p1, p2, p3 }; + minCentreDistance = centreDistance; + } + } + } + } + } - // break; - // case ActivePointsEnum.PierSide: - // // only consider points on this side of the meridian - // if (datholder[Count].cc.y * tmpcoord.y < 0) - // { - // goto NextPoint; - // } + return results; - // break; - // case ActivePointsEnum.LocalQuadrant: - // // local quadrant - // if (!GetQuadrant(tmpcoord).Equals(GetQuadrant(datholder[Count].cc))) - // { - // goto NextPoint; - // } + } - // break; - // } - // if (CheckLocalPier) - // { - // // calculate polar distance - // datholder[Count].dat = Math.Pow(EQASCOM.my_Points[i].x - x, 2) + Math.Pow(EQASCOM.my_Points[i].y - Y, 2); - // } - // else - // { - // // calculate cartesian disatnce - // datholder[Count].dat = Math.Pow(datholder[Count].cc.x - tmpcoord.x, 2) + Math.Pow(datholder[Count].cc.y - tmpcoord.y, 2); - // } - // // Also save the reference star id for this particular reference star - // datholder[Count].idx = Convert.ToInt16(i); + /// + /// Returns the nearest 3 alignment points that form and enclosing triangle around a position. + /// + /// + /// List of 3 points or an empty list. + internal List EQ_ChooseNearest3Points(EncoderPosition pos) + { + Dictionary distances = new Dictionary(); + List results = new List(); + // Adjust only if there are three alignment stars - // Count++; - // NextPoint:; - // } + if (AlignmentPoints.Count <= 3) + { + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + results.Add(pt); + } + return results; + } - // if (Count < 3) - // { - // // not enough points to do 3-point - // result.i = 0; - // result.j = 0; - // result.k = 0; - // return result; - // } + Coord posCartesean = EQ_sp2Cs(pos); - // // now sort the disatnces so the closest stars are at the top - // EQ_Quicksort2(datholder, 1, Count); + // first find out the distances to the alignment stars + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + switch (ActivePoints) + { + case ActivePointsEnum.All: + // all points + + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.EncoderCartesian.y * posCartesean.y < 0) + { + continue; + } + + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.EncoderCartesian))) + { + continue; + } + + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); + } + } - // //Just use the nearest 50 stars (max) - saves processing time - // if (Count > EQASCOM.gMaxCombinationCount - 1) - // { - // combi_cnt = EQASCOM.gMaxCombinationCount; - // } - // else - // { - // combi_cnt = Count; - // } + if (distances.Count < 3) + { + return results; // Empty list. + } - // tmp1 = combi_cnt - 1; - // tmp2 = Convert.ToInt32(combi_cnt - 2); - // first = true; + // now sort the distances so the closest stars are at the top + //Just use the nearest 50 stars (or max) - saves processing time + List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); - // // iterate through all the triangles posible using the nearest alignment points - // int l = 1; - // int m = 2; - // int n = 3; - // int tempForEndVar2 = (tmp2); - // for (int i = 1; i <= tempForEndVar2; i++) - // { - // p1 = datholder[Convert.ToInt32(i) - 1].cc; - // double tempForEndVar3 = (tmp1); - // for (int j = i + 1; j <= tempForEndVar3; j++) - // { - // p2 = datholder[Convert.ToInt32(j) - 1].cc; - // double tempForEndVar4 = combi_cnt; - // for (int k = (j + 1); k <= tempForEndVar4; k++) - // { - // p3 = datholder[Convert.ToInt32(k) - 1].cc; + var tmp1 = sortedIds.Count - 1; + var tmp2 = tmp1 - 1; + bool done = false; - // if (EQ_CheckPoint_in_Triangle(tmpcoord.x, tmpcoord.y, p1.x, p1.y, p2.x, p2.y, p3.x, p3.y) == 1) - // { - // l = i; - // m = j; - // n = Convert.ToInt32(k); - // goto alldone; - // } - // } - // } - // } - // result.i = 0; - // result.j = 0; - // result.k = 0; - // return result; + // iterate through all the triangles posible using the nearest alignment points + for (int i = 0; i <= tmp2; i++) + { + var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); + for (int j = i + 1; j < tmp1; j++) + { + var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); + for (int k = (j + 1); k < sortedIds.Count; k++) + { + var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); + + + if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, + p1.EncoderCartesian.x, p1.EncoderCartesian.y, + p2.EncoderCartesian.x, p2.EncoderCartesian.y, + p3.EncoderCartesian.x, p3.EncoderCartesian.y)) + { + results.Add(p1); + results.Add(p2); + results.Add(p3); + done = true; + } + if (done) break; + } + if (done) break; + } + if (done) break; + } - //alldone: - // result.i = datholder[Convert.ToInt32(l) - 1].idx; - // result.j = datholder[Convert.ToInt32(m) - 1].idx; - // result.k = datholder[n - 1].idx; + return results; - // return result; - //} + } //public static float GetRnd() //{ diff --git a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs index a2c872cb..48055227 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs +++ b/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs @@ -63,12 +63,13 @@ private void ActivateMatrix() if (AlignmentPoints.Count >= 3) { - _ =EQ_AssembleMatrix_Taki(0, 0, - AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian, - AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian,AlignmentPoints[2].EncoderCartesian); - _ =EQ_AssembleMatrix_Affine(0, 0, + _ = EQ_AssembleMatrix_Taki(0, 0, + AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian, + AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian, AlignmentPoints[2].EncoderCartesian); + _ = EQ_AssembleMatrix_Affine(0, 0, AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian, AlignmentPoints[2].EncoderCartesian, AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian); + _threeStarEnabled = true; } } // /pec /showalignment diff --git a/EQMODAlignment/Model/AlignmentModel_Math.cs b/EQMODAlignment/Model/AlignmentModel_Math.cs index 12eb9998..9753ef17 100644 --- a/EQMODAlignment/Model/AlignmentModel_Math.cs +++ b/EQMODAlignment/Model/AlignmentModel_Math.cs @@ -61,6 +61,7 @@ You should have received a copy of the GNU General Public License using EqmodNStarAlignment.Utilities; using System; using System.Collections.Generic; +using System.Linq; using System.Text; namespace EqmodNStarAlignment.Model @@ -279,22 +280,22 @@ partial class AlignmentModel - public double Get_EncoderHours(double RAencoderPosition) + private double Get_EncoderHours(long encoderPosition) { - + double pos = encoderPosition * 1d; double hours; // Compute in Hours the encoder value based on 0 position value (RAOffset0) // and Total 360 degree rotation microstep count (Tot_Enc - if (RAencoderPosition > this.HomeEncoder.RA) + if (pos > this.HomeEncoder.RA) { - hours = ((RAencoderPosition - this.HomeEncoder.RA) / StepsPerRev.RA) * 24; + hours = ((pos - this.HomeEncoder.RA) / StepsPerRev.RA) * 24d; hours = 24 - hours; } else { - hours = ((this.HomeEncoder.RA - RAencoderPosition) / StepsPerRev.RA) * 24; + hours = ((this.HomeEncoder.RA - pos) / StepsPerRev.RA) * 24d; } if (Hemisphere == HemisphereEnum.Northern) @@ -308,69 +309,69 @@ public double Get_EncoderHours(double RAencoderPosition) } - //private int Get_EncoderfromHours(double encOffset0, double hourval, double Tot_enc, int hmspr) - //{ - - // hourval = Range24(hourval - 6d); // Re-normalize from a perpendicular position - // if (hmspr == 0) - // { - // if (hourval < 12) - // { - // return Convert.ToInt32(encOffset0 - ((hourval / 24d) * Tot_enc)); - // } - // else - // { - // return Convert.ToInt32((((24 - hourval) / 24d) * Tot_enc) + encOffset0); - // } - // } - // else - // { - // if (hourval < 12) - // { - // return Convert.ToInt32(((hourval / 24d) * Tot_enc) + encOffset0); - // } - // else - // { - // return Convert.ToInt32(encOffset0 - (((24 - hourval) / 24d) * Tot_enc)); - // } - // } + private long Get_EncoderfromHours(double hourval) + { - //} + hourval = Range.Range24(hourval - 6d); // Re-normalize from a perpendicular position + if (this.Hemisphere == HemisphereEnum.Northern) + { + if (hourval < 12) + { + return (long)Math.Round(this.HomeEncoder.RA - ((hourval / 24d) * this.StepsPerRev.RA)); + } + else + { + return (long)Math.Round((((24 - hourval) / 24d) * this.StepsPerRev.RA) + this.HomeEncoder.RA); + } + } + else + { + if (hourval < 12) + { + return (long)Math.Round(((hourval / 24d) * this.StepsPerRev.RA) + this.HomeEncoder.RA); + } + else + { + return (long)Math.Round(this.HomeEncoder.RA - (((24 - hourval) / 24d) * this.StepsPerRev.RA)); + } + } - //private int Get_EncoderfromDegrees(double encOffset0, double degval, double Tot_enc, double Pier, int hmspr) - //{ + } - // if (hmspr == 1) - // { - // degval = 360 - degval; - // } - // if ((degval > 180) && (Pier == 0)) - // { - // return Convert.ToInt32(encOffset0 - (((360 - degval) / 360d) * Tot_enc)); - // } - // else - // { - // return Convert.ToInt32(((degval / 360d) * Tot_enc) + encOffset0); - // } + private long Get_EncoderfromDegrees(double degval) + { - //} + if (this.Hemisphere == HemisphereEnum.Southern) + { + degval = 360 - degval; + } + if ((degval > 180)) // && (Pier == 0)) + { + return (long)Math.Round(this.HomeEncoder.Dec - (((360 - degval) / 360d) * this.StepsPerRev.Dec)); + } + else + { + return (long)Math.Round(((degval / 360d) * this.StepsPerRev.Dec) + this.HomeEncoder.Dec); + } + } - private double Get_EncoderDegrees(double DecEncoderPosition) - { + private double Get_EncoderDegrees(long encoderPosition) + { + double pos = encoderPosition * 1.0d;// Convert to double to prevent truncation double decDegrees = 0; // Compute in Hours the encoder value based on 0 position value (EncOffset0) // and Total 360 degree rotation microstep count (Tot_Enc - if (DecEncoderPosition > this.HomeEncoder.Dec) + if (pos > this.HomeEncoder.Dec) { - decDegrees = ((DecEncoderPosition - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 360; + decDegrees = ((pos - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 360d; } else { - decDegrees = ((this.HomeEncoder.Dec - DecEncoderPosition) / this.StepsPerRev.Dec) * 360; + decDegrees = ((double)(this.HomeEncoder.Dec - pos) / this.StepsPerRev.Dec) * 360d; decDegrees = 360 - decDegrees; } @@ -746,19 +747,19 @@ private double Get_EncoderDegrees(double DecEncoderPosition) //} - //private double Delta_RA_Map(double RAENCODER) - //{ + private double Delta_RA_Map(double raEncoder) + { - // return RAENCODER + gRA1Star + gRASync01; + return raEncoder + this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) - //} + } - //private double Delta_DEC_Map(double DecEncoder) - //{ + private double Delta_DEC_Map(double decEncoder) + { - // return DecEncoder + gDEC1Star + gDECSync01; + return decEncoder + this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) - //} + } //private Coordt Delta_Matrix_Map(double RA, double DEC) @@ -793,72 +794,70 @@ private double Get_EncoderDegrees(double DecEncoderPosition) //} - //private Coordt Delta_Matrix_Reverse_Map(double RA, double DEC) - //{ + private EncoderPosition Delta_Matrix_Reverse_Map(EncoderPosition pos) + { - // Coordt result = new Coordt(); - // Coord obtmp = new Coord(); + EncoderPosition result = new EncoderPosition(); - // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) - // { - // result.x = RA; - // result.y = DEC; - // result.z = 1; - // result.f = 0; - // return result; - // } + if ((pos.RA >= 0x1000000) || (pos.Dec >= 0x1000000)) + { + result.RA = pos.RA; + result.Dec = pos.Dec; + //result.z = 1; + //result.f = 0; + return result; + } - // obtmp.x = RA + gRASync01; - // obtmp.y = DEC + gDECSync01; - // obtmp.z = 1; - // // re transform using the 3 nearest stars - // int i = EQ_UpdateAffine(obtmp.x, obtmp.y); - // Coord obtmp2 = EQ_plAffine(obtmp); - - // result.x = obtmp2.x; - // result.y = obtmp2.y; - // result.z = 1; - // result.f = (short)i; + // re transform using the 3 nearest stars + _=EQ_UpdateAffine(pos); + EncoderPosition obtmp2 = EQ_plAffine(pos); + result.RA = obtmp2.RA; + result.Dec = obtmp2.Dec; + //result.z = 1; + //result.f = (short)i; - // return result; - //} + return result; + } - //private Coordt DeltaSync_Matrix_Map(double RA, double DEC) - //{ - // Coordt result = new Coordt(); - // int i = 0; + /// + /// Maps an encoder position to the calculate target position + /// + /// + /// + private EncoderPosition DeltaSync_Matrix_Map(EncoderPosition encoderPosition) + { + EncoderPosition result = new EncoderPosition(); - // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) - // { - // result.x = RA; - // result.y = DEC; - // result.z = 0; - // result.f = 0; - // } - // else - // { - // i = GetNearest(RA, DEC); - // if (i != -1) - // { - // EQASCOM.gSelectStar = i; - // result.x = RA + (EQASCOM.ct_Points[i].x - EQASCOM.my_Points[i].x) + gRASync01; - // result.y = DEC + (EQASCOM.ct_Points[i].y - EQASCOM.my_Points[i].y) + gDECSync01; - // result.z = 1; - // result.f = 0; - // } - // else - // { - // result.x = RA; - // result.y = DEC; - // result.z = 0; - // result.f = 0; - // } - // } - // return result; - //} + if ((encoderPosition.RA >= 0x1000000) || (encoderPosition.Dec >= 0x1000000)) + { + result.RA = encoderPosition.RA; + result.Dec = encoderPosition.Dec; + // result.z = 0; + // result.f = 0; + } + else + { + this.SelectedAlignmentPoint = GetNearest(encoderPosition); + if (this.SelectedAlignmentPoint != null) + { + result.RA = encoderPosition.RA + (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA); // + gRASync01; + result.Dec = encoderPosition.Dec + (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec); // + gDecSync01; + // result.z = 1; + // result.f = 0; + } + else + { + result.RA = encoderPosition.RA; + result.Dec = encoderPosition.Dec; + // result.z = 0; + // result.f = 0; + } + } + return result; + } //private Coordt DeltaSyncReverse_Matrix_Map(double RA, double DEC) @@ -895,117 +894,104 @@ private double Get_EncoderDegrees(double DecEncoderPosition) // } // return result; //} - //private int GetQuadrant(Coord tmpcoord) - //{ - // int ret = 0; - - // if (tmpcoord.x >= 0) - // { - // if (tmpcoord.y >= 0) - // { - // ret = 0; - // } - // else - // { - // ret = 1; - // } - // } - // else - // { - // if (tmpcoord.y >= 0) - // { - // ret = 2; - // } - // else - // { - // ret = 3; - // } - // } - - // return ret; - - //} - - - //private int GetNearest(double RA, double DEC) - //{ - // int i = 0; - // Coord tmpcoord = new Coord(); - // Coord tmpcoord2 = new Coord(); - // double[] datholder = new double[EQASCOM.MAX_STARS]; - // int[] datholder2 = new int[EQASCOM.MAX_STARS]; - - // tmpcoord.x = RA; - // tmpcoord.y = DEC; - // tmpcoord = EQ_sp2Cs(tmpcoord); + + //TODO: Improve GetQuadrant to return an Enum value (NW, NE, SW or SE) instead of an int. + + /// + /// Returns a quadrant based on a cartesean coordinate + /// + /// + /// + private int GetQuadrant(Coord tmpcoord) + { + int ret = 0; - // int Count = 0; + if (tmpcoord.x >= 0) + { + if (tmpcoord.y >= 0) + { + ret = 0; + } + else + { + ret = 1; + } + } + else + { + if (tmpcoord.y >= 0) + { + ret = 2; + } + else + { + ret = 3; + } + } - // for (i = 1; i <= EQASCOM.gAlignmentStars_count; i++) - // { + return ret; - // tmpcoord2 = EQASCOM.my_PointsC[i]; + } - // switch (ActivePoints) - // { - // case ActivePointsEnum.All: - // // all points - - // break; - // case ActivePointsEnum.PierSide: - // // only consider points on this side of the meridian - // if (tmpcoord2.y * tmpcoord.y < 0) - // { - // goto NextPoint; - // } - - // break; - // case ActivePointsEnum.LocalQuadrant: - // // local quadrant - // if (GetQuadrant(tmpcoord) != GetQuadrant(tmpcoord2)) - // { - // goto NextPoint; - // } - - // break; - // } - // Count++; - // if (CheckLocalPier) - // { - // // calculate polar distance - // datholder[Count - 1] = Math.Pow(EQASCOM.my_Points[i].x - RA, 2) + Math.Pow(EQASCOM.my_Points[i].y - DEC, 2); - // } - // else - // { - // // calculate cartesian disatnce - // datholder[Count - 1] = Math.Pow(tmpcoord2.x - tmpcoord.x, 2) + Math.Pow(tmpcoord2.y - tmpcoord.y, 2); - // } + /// + /// Return the nearest alignment point to an encoder position + /// + /// + /// + private AlignmentPoint GetNearest(EncoderPosition pos) + { + Dictionary distances = new Dictionary(); + int[] datholder2 = new int[this.AlignmentPoints.Count]; - // datholder2[Count - 1] = i; + Coord posCartesean = EQ_sp2Cs(pos); - // NextPoint:; - // } + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + switch (ActivePoints) + { + case ActivePointsEnum.All: + // all points + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.EncoderCartesian.y * posCartesean.y < 0) + { + continue; + } + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (GetQuadrant(posCartesean) != GetQuadrant(pt.EncoderCartesian)) + { + continue; + } + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); + } + } - // if (Count == 0) - // { - // return -1; - // } - // else - // { - // // i = EQ_FindLowest(datholder(), 1, gAlignmentStars_count) - // i = EQ_FindLowest(datholder, 1, Count); - // if (i == -1) - // { - // return -1; - // } - // else - // { - // return datholder2[i - 1]; - // } - // } + if (distances.Count == 0) + { + return null; + } + else + { + int nearestId = distances.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key).First(); + return AlignmentPoints.FirstOrDefault(pt => pt.Id == nearestId); + } - //} + } } diff --git a/EQMODAlignment/Utilities/AstroConvert.cs b/EQMODAlignment/Utilities/AstroConvert.cs index 66cdcfc0..14a4feea 100644 --- a/EQMODAlignment/Utilities/AstroConvert.cs +++ b/EQMODAlignment/Utilities/AstroConvert.cs @@ -40,11 +40,13 @@ You should have received a copy of the GNU General Public License */ using System; +using System.Diagnostics; +using System.Runtime.InteropServices; namespace EqmodNStarAlignment.Utilities { - public class AstroConvert + public static class AstroConvert { /// /// Radians per degree @@ -71,138 +73,112 @@ public class AstroConvert #endregion - /// - /// Right Ascension to Local 12 Hour Angles - /// - /// - /// The hour angle (HA) of an object is equal to the difference between - /// the current local sidereal time (LST) and the right ascension of that object. - /// Adopted from ASCOM - /// - /// In decimal hours - /// In decimal hours - /// Local Hour Angles in decimal hours - public static double Ra2Ha12(double rightAscension, double localSiderealTime) - { - var a = localSiderealTime - rightAscension; - var ra2Ha = Range.Range12(a); - return ra2Ha; - } + #region Astro32.dll functions ... + /* + * The methods in this region are created using the code that I believe was originally used + * to create the astro32.dll that was shipped with EQMOD. + * Source: http://mmto.org/~dclark/Reports/MountDoxygen/html/aa__hadec_8c_source.html + */ + static double lastLatitide; + static double sinLatitude = 0.0; + static double cosLatitude = 0.0; - /// - /// Right Ascension and Declination to Altitude and Azimuth - /// Adopted from ASCOM - /// - /// In decimal hours - /// In decimal degrees - /// In decimal hours - /// In decimal degrees - /// Array of Azimuth, Altitude in decimal degrees - public static double[] RaDec2AltAz(double rightAscension, double declination, double localSiderealTime, double latitude) - { - var a = Ra2Ha12(rightAscension, localSiderealTime); - var raDec2AltAz = HaDec2AltAz(a, declination, latitude); - return raDec2AltAz; - } - /// - /// Hour Angles and Declination to Altitude and Azimuth - /// Adopted from ASCOM - /// - /// Local Hour angle - /// In decimal degrees - /// In decimal degrees - /// Array of Azimuth, Altitude in decimal degrees - public static double[] HaDec2AltAz(double hourAngle, double declination, double latitude) + /* given geographical latitude (n+, radians), lt, altitude (up+, radians), + * alt, and azimuth (angle round to the east from north+, radians), + * return hour angle (radians), ha, and declination (radians), dec. + * Originally called aa_hadec + */ + + public static double[] GetHaDec(double lt, double alt, double az) { - double a = HrsToRad(hourAngle); - double b = DegToRad(declination); - double c = DegToRad(latitude); - double d = Math.Sin(a); - double e = Math.Cos(a); - double f = Math.Sin(b); - double g = Math.Cos(b); - double h = Math.Sin(c); - double i = Math.Cos(c); - double j = f * i - e * g * h; - double k = -(d * g); - double l = e * g * i + f * h; - double m = Math.Sqrt(j * j + k * k); - double n = RadToDeg(Math.Atan2(k, j)); - double o = RadToDeg(Math.Atan2(l, m)); - double p = Range.Range360(n); - double q = Range.Range90(o); - double[] altAz = { q, p }; - return altAz; + double ha = 0d, dec = 0d; + aaha_aux(lt, az, alt, ref ha, ref dec); + if (ha > Math.PI) + ha -= 2 * Math.PI; + return new double[] { ha, dec }; } - /// - /// Azimuth and Altitude to Right Ascension and Declination - /// - /// In decimal degrees - /// In decimal degrees - /// In decimal degrees - /// In decimal hours - /// Ra in decimal hours, Dec in decimal degrees - public static double[] AltAz2RaDec(double altitude, double azimuth, double latitude, double lst) + /* given geographical (n+, radians), lt, hour angle (radians), ha, and + * declination (radians), dec, return altitude (up+, radians), alt, and + * azimuth (angle round to the east from north+, radians), + * Originally caled hadec_aa + */ + public static double[] GetAltAz(double lt, double ha, double dec) { - var a = AltAz2Ra(altitude, azimuth, latitude, lst); - var b = AltAz2Dec(altitude, azimuth, latitude); - var altAz2RaDec = new[] { a, b }; - return altAz2RaDec; + double alt = 0d, az = 0d; + aaha_aux(lt, ha, dec, ref az, ref alt); + return new double[] { alt, az }; } - /// - /// Azimuth and Altitude to Declination - /// Adopted from ASCOM - /// - /// In decimal degrees - /// In decimal degrees - /// In decimal degrees - /// Declination in decimal degrees - public static double AltAz2Dec(double altitude, double azimuth, double latitude) + static void aaha_aux(double latitude, double x, double y, ref double p, ref double q) { - var a = DegToRad(azimuth); - var b = DegToRad(altitude); - var c = DegToRad(latitude); - //var d = Math.Sin(a); - var e = Math.Cos(a); - var f = Math.Sin(b); - var g = Math.Cos(b); - var h = Math.Sin(c); - var i = Math.Cos(c); - var j = e * i * g + h * f; - var k = RadToDeg(Math.Asin(j)); - var altAz2Dec = Range.Range90(k); - return altAz2Dec; + lastLatitide = double.MinValue; + double cap = 0.0; + double B = 0.0; + + if (latitude != lastLatitide) + { + sinLatitude = Math.Sin(latitude); + cosLatitude = Math.Cos(latitude); + lastLatitide = latitude; + } + + solve_sphere(-x, Math.PI / 2 - y, sinLatitude, cosLatitude, ref cap, ref B); + p = B; + q = Math.PI / 2 - Math.Acos(cap); } - /// - /// Azimuth and Altitude to Right Ascension - /// Adopted from ASCOM - /// - /// In decimal degrees - /// In decimal degrees - /// In decimal degrees - /// In decimal hours - /// Right Ascension in decimal hours - public static double AltAz2Ra(double altitude, double azimuth, double latitude, double lst) + /* solve a spherical triangle: + * A + * / \ + * / \ + * c / \ b + * / \ + * / \ + * B ____________ C + * a + * + * given A, b, c find B and a in range 0..B..2PI and 0..a..PI, respectively.. + * cap and Bp may be NULL if not interested in either one. + * N.B. we pass in cos(c) and sin(c) because in many problems one of the sides + * remains constant for many values of A and b. + */ + static void solve_sphere(double A, double b, double cc, double sc, ref double cap, ref double Bp) { - var a = DegToRad(azimuth); - var b = DegToRad(altitude); - var c = DegToRad(latitude); - var d = Math.Sin(a); - var e = Math.Cos(a); - var f = Math.Sin(b); - var g = Math.Cos(b); - var h = Math.Sin(c); - var i = Math.Cos(c); - var j = -d * g; - var k = -e * h * g + f * i; - var l = RadToHrs(Math.Atan2(j, k)); - var altAz2Ra = Range.Range24(lst - l); - return altAz2Ra; + double cb = Math.Cos(b), sb = Math.Sin(b); + double sA, cA = Math.Cos(A); + double x, y; + double ca; + double B; + + ca = cb * cc + sb * sc * cA; + if (ca > 1.0) + { + ca = 1.0; + } + if (ca < -1.0) + { + ca = -1.0; + } + cap = ca; + + if (sc < 1e-7) + { + B = cc < 0 ? A : Math.PI - A; + } + else + { + sA = Math.Sin(A); + y = sA * sb * sc; + x = cb - ca * cc; + B = Math.Atan2(y, x); + } + + Bp = Range.ZeroToValue(B, Math.PI * 2); } + #endregion + } } diff --git a/EQMODAlignment/Utilities/Range.cs b/EQMODAlignment/Utilities/Range.cs index ee5b27d8..ab816ebc 100644 --- a/EQMODAlignment/Utilities/Range.cs +++ b/EQMODAlignment/Utilities/Range.cs @@ -14,6 +14,8 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the You should have received a copy of the GNU General Public License along with this program. If not, see . */ +using System; + namespace EqmodNStarAlignment.Utilities { /// @@ -22,6 +24,23 @@ namespace EqmodNStarAlignment.Utilities /// Attention to the order of parameters (AltAz vs AzAlt) in the method names public static class Range { + ///* insure 0 <= *v < r. + // 233 void + // 234 range(double* v, double r) + // 235 { + // 236 *v -= r* floor(*v/r); + // 237 } + public static double ZeroToValue(double d, double range) + { + while ((d >= range) || (d < 0.0)) + { + if (d < 0.0) d += range; + if (d >= range) d -= range; + } + return d; + + } + /// /// Returns double in the range -12 to +12 /// diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index 3ce6ee4d..eee1117c 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -1,5 +1,7 @@ using System; +using System.Diagnostics; using System.IO; +using System.Reflection; using EqmodNStarAlignment.DataTypes; using EqmodNStarAlignment.Model; using EqmodNStarAlignment.Utilities; @@ -13,22 +15,51 @@ public class AlignmentModelTests const double siteLatitude = 52.6683333333333; const double siteLongitude = -1.33888888888889; const double siteElevation = 200d; + const double siteTemperatire = 15d; const long decHomePos = 9003008; const long raHomePos = 8388608; - const double doubleDelta = 0.00000001; + const double doubleDelta = 0.0001; + const double deltaEncoder = 10; // 1/16 arcsecond + AlignmentPoint[] points = new AlignmentPoint[] { + new AlignmentPoint(new EncoderPosition(8987817, 8919464), new double[] { 23.6715774536133, 77.7643051147461 }, new EncoderPosition(8987821, 8919479), new DateTime(2022, 11, 28, 19, 06, 06)), + new AlignmentPoint(new EncoderPosition(7985357, 9135000), new double[] { 21.481803894043, 70.6648559570313 }, new EncoderPosition(7985268, 9135003), new DateTime(2022, 11, 28, 19, 07, 17)), + new AlignmentPoint(new EncoderPosition(7847708, 9164640), new double[] { 22.8413619995117, 66.3250198364258 }, new EncoderPosition(7847528, 9164630), new DateTime(2022, 11, 28, 19, 08, 09)), + new AlignmentPoint(new EncoderPosition(8200354, 9412632), new double[] { 21.2521438598633, 29.9979152679443 }, new EncoderPosition(8200185, 9412623), new DateTime(2022, 11, 30, 20, 51, 15)), + new AlignmentPoint(new EncoderPosition(8380206, 9263912), new double[] { 19.5041027069092, 51.7807502746582 }, new EncoderPosition(8380039, 9263918), new DateTime(2022, 11, 30, 20, 51, 45)), + new AlignmentPoint(new EncoderPosition(8421824, 9522552), new double[] { 19.107213973999, 13.8985624313354 }, new EncoderPosition(8421625, 9522528), new DateTime(2022, 11, 30, 20, 52, 18)), + new AlignmentPoint(new EncoderPosition(7887790, 9676808), new double[] { 0.343226462602615, -8.69821166992188 }, new EncoderPosition(7887531, 9676788), new DateTime(2022, 11, 30, 20, 53, 31)), + new AlignmentPoint(new EncoderPosition(7907761, 9417944), new double[] { 0.159508779644966, 29.2189121246338 }, new EncoderPosition(7907519, 9417941), new DateTime(2022, 11, 30, 20, 54, 12)), + new AlignmentPoint(new EncoderPosition(8155121, 9549296), new double[] { 21.7548809051514, 9.98066520690918 }, new EncoderPosition(8154849, 9549274), new DateTime(2022, 11, 30, 20, 54, 51)), + new AlignmentPoint(new EncoderPosition(8964653, 8318792), new double[] { 1.87664878368378, -10.2228670120239 }, new EncoderPosition(8964648, 8318820), new DateTime(2022, 11, 30, 20, 56, 38)), + new AlignmentPoint(new EncoderPosition(8549669, 8439192), new double[] { 5.94036722183228, 7.41184711456299 }, new EncoderPosition(8549590, 8439206), new DateTime(2022, 11, 30, 20, 57, 16)), + new AlignmentPoint(new EncoderPosition(8836220, 8668816), new double[] { 3.16128063201904, 41.0447845458984 }, new EncoderPosition(8836045, 8668807), new DateTime(2022, 11, 30, 20, 58, 21)), + new AlignmentPoint(new EncoderPosition(8810409, 8729584), new double[] { 3.43303275108337, 49.9433364868164 }, new EncoderPosition(8810306, 8729555), new DateTime(2022, 11, 30, 20, 59, 35)), + new AlignmentPoint(new EncoderPosition(8028636, 8809304), new double[] { 11.0852670669556, 61.624095916748 }, new EncoderPosition(8028459, 8809295), new DateTime(2022, 11, 30, 21, 00, 36)), + new AlignmentPoint(new EncoderPosition(8378814, 8423856), new double[] { 7.6750659942627, 5.16721248626709 }, new EncoderPosition(8378754, 8423883), new DateTime(2022, 11, 30, 21, 01, 14)), + new AlignmentPoint(new EncoderPosition(8387315, 8605928), new double[] { 7.60103368759155, 31.8366107940674 }, new EncoderPosition(8387210, 8605946), new DateTime(2022, 11, 30, 21, 01, 45)), + new AlignmentPoint(new EncoderPosition(8206767, 8622712), new double[] { 9.37405490875244, 34.2941551208496 }, new EncoderPosition(8206583, 8622723), new DateTime(2022, 11, 30, 21, 02, 17)), + new AlignmentPoint(new EncoderPosition(8661869, 8841768), new double[] { 4.93953990936279, 66.3796844482422 }, new EncoderPosition(8661823, 8841760), new DateTime(2022, 11, 30, 21, 02, 58)), + new AlignmentPoint(new EncoderPosition(8625168, 8702760), new double[] { 5.30665588378906, 46.0202331542969 }, new EncoderPosition(8624972, 8702773), new DateTime(2022, 11, 30, 21, 03, 24)), + new AlignmentPoint(new EncoderPosition(8696329, 8501640), new double[] { 4.62079238891602, 16.5555591583252 }, new EncoderPosition(8696186, 8501627), new DateTime(2022, 11, 30, 21, 03, 58)), + new AlignmentPoint(new EncoderPosition(8959119, 9178696), new double[] { 14.0829401016235, 64.2641220092773 }, new EncoderPosition(8959093, 9178699), new DateTime(2022, 11, 30, 21, 05, 44)), + new AlignmentPoint(new EncoderPosition(8912307, 9356584), new double[] { 14.549503326416, 38.2075653076172 }, new EncoderPosition(8912190, 9356578), new DateTime(2022, 11, 30, 21, 06, 15)), + new AlignmentPoint(new EncoderPosition(8412924, 9595864), new double[] { 19.4437313079834, 3.1609582901001 }, new EncoderPosition(8412645, 9595830), new DateTime(2022, 11, 30, 21, 07, 12)) + }; - const HemisphereEnum hemisphere = HemisphereEnum.Northern; private EncoderPosition stepsPerRev = new EncoderPosition(2457601, 2457601); - private AlignmentModel AlignmentModel; + private AlignmentModel _alignmentModel; [TestInitialize] public void Initialize() { - AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); - AlignmentModel.SetHomePosition(raHomePos, decHomePos); - AlignmentModel.PolarEnable = true; + _alignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); + _alignmentModel.SetHomePosition(raHomePos, decHomePos); + _alignmentModel.PolarEnable = true; + string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); + _alignmentModel.LoadAlignmentPoints(inputFile); + } @@ -40,16 +71,11 @@ public void SavePointsTest() { File.Delete(outputFile); } - - AlignmentPoint pt1 = new AlignmentPoint(new EncoderPosition(8987817, 8919464), new double[] { 23.6715774536133, 77.7643051147461 }, new EncoderPosition(8987821, 8919479), new DateTime(2022, 11, 28, 19, 06, 06)); - AlignmentPoint pt2 = new AlignmentPoint(new EncoderPosition(7985357, 9135000), new double[] { 21.481803894043, 70.6648559570313 }, new EncoderPosition(7985268, 9135003), new DateTime(2022, 11, 28, 19, 07, 17)); - AlignmentPoint pt3 = new AlignmentPoint(new EncoderPosition(7847708, 9164640), new double[] { 22.8413619995117, 66.3250198364258 }, new EncoderPosition(7847528, 9164630), new DateTime(2022, 11, 28, 19, 08, 09)); - - AlignmentModel.EQ_NPointAppend(pt1); - AlignmentModel.EQ_NPointAppend(pt2); - AlignmentModel.EQ_NPointAppend(pt3); - - AlignmentModel.SaveAlignmentPoints(outputFile); + foreach (AlignmentPoint pt in points) + { + _alignmentModel.EQ_NPointAppend(pt); + } + _alignmentModel.SaveAlignmentPoints(outputFile); Assert.IsTrue(File.Exists(outputFile)); } @@ -58,6 +84,17 @@ public void SavePointsTest() public void LoadPointsTest() { string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); + _alignmentModel.ClearAlignmentPoints(); + + _alignmentModel.LoadAlignmentPoints(inputFile); + + Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 23); + + } + + [TestMethod] + public void TestMatrices() + { Matrix ExpectedTaki = Matrix.CreateInstance(); ExpectedTaki.Element[0, 0] = 0.999962437601123; @@ -76,27 +113,244 @@ public void LoadPointsTest() ExpectedAffine.Element[1, 0] = -4.17779058621084E-04; ExpectedAffine.Element[1, 1] = 1.00009504460391; - AlignmentModel.ClearAlignmentPoints(); + // Clear points and reload first three + _alignmentModel.ClearAlignmentPoints(); + + for (int i = 0; i < 3; i++) + { + _alignmentModel.EQ_NPointAppend(points[i]); + } - AlignmentModel.LoadAlignmentPoints(inputFile); + Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 23); - Assert.IsTrue(AlignmentModel.AlignmentPoints.Count == 3); + Assert.AreEqual(ExpectedTaki.Element[0, 0], AlignmentModel.EQMT.Element[0, 0], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[0, 1], AlignmentModel.EQMT.Element[0, 1], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[0, 2], AlignmentModel.EQMT.Element[0, 2], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[1, 0], AlignmentModel.EQMT.Element[1, 0], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[1, 1], AlignmentModel.EQMT.Element[1, 1], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[1, 2], AlignmentModel.EQMT.Element[1, 2], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[2, 0], AlignmentModel.EQMT.Element[2, 0], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[2, 1], AlignmentModel.EQMT.Element[2, 1], doubleDelta); + Assert.AreEqual(ExpectedTaki.Element[2, 2], AlignmentModel.EQMT.Element[2, 2], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[0, 0], AlignmentModel.EQMT.Element[0, 0], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[0, 1], AlignmentModel.EQMT.Element[0, 1], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[0, 2], AlignmentModel.EQMT.Element[0, 2], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[1, 0], AlignmentModel.EQMT.Element[1, 0], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[1, 1], AlignmentModel.EQMT.Element[1, 1], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[1, 2], AlignmentModel.EQMT.Element[1, 2], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[2, 0], AlignmentModel.EQMT.Element[2, 0], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[2, 1], AlignmentModel.EQMT.Element[2, 1], 0.00000001); - Assert.AreEqual(ExpectedTaki.Element[2, 2], AlignmentModel.EQMT.Element[2, 2], 0.00000001); + Assert.AreEqual(ExpectedAffine.Element[0, 0], AlignmentModel.EQMM.Element[0, 0], doubleDelta); + Assert.AreEqual(ExpectedAffine.Element[0, 1], AlignmentModel.EQMM.Element[0, 1], doubleDelta); + Assert.AreEqual(ExpectedAffine.Element[1, 0], AlignmentModel.EQMM.Element[1, 0], doubleDelta); + Assert.AreEqual(ExpectedAffine.Element[1, 1], AlignmentModel.EQMM.Element[1, 1], doubleDelta); - Assert.AreEqual(ExpectedAffine.Element[0, 0], AlignmentModel.EQMM.Element[0, 0], 0.00000001); - Assert.AreEqual(ExpectedAffine.Element[0, 1], AlignmentModel.EQMM.Element[0, 1], 0.00000001); - Assert.AreEqual(ExpectedAffine.Element[1, 0], AlignmentModel.EQMM.Element[1, 0], 0.00000001); - Assert.AreEqual(ExpectedAffine.Element[1, 1], AlignmentModel.EQMM.Element[1, 1], 0.00000001); + } + + [DataRow(8230673, 8846876, 8230828, 8846880)] + [DataRow(8224190, 8840364, 8224348, 8840368)] + [DataRow(8218188, 8834403, 8218348, 8834408)] + [DataRow(8212194, 8828474, 8212404, 8828464)] + [DataRow(8206462, 8822595, 8206588, 8822600)] + [DataRow(8200335, 8816551, 8200468, 8816552)] + [DataRow(8194520, 8810698, 8194660, 8810696)] + [DataRow(8188449, 8804653, 8188596, 8804648)] + [DataRow(8182274, 8798512, 8182428, 8798504)] + [DataRow(8176361, 8792548, 8176548, 8792552)] + [DataRow(8170243, 8786429, 8170364, 8786408)] + [DataRow(8164092, 8780291, 8164220, 8780272)] + [DataRow(8157949, 8774145, 8158084, 8774128)] + [DataRow(8152079, 8768280, 8152220, 8768264)] + [DataRow(8145665, 8761853, 8145812, 8761840)] + [DataRow(8139500, 8755707, 8139652, 8755696)] + [DataRow(8133279, 8749473, 8133436, 8749464)] + [DataRow(8126858, 8743046, 8127020, 8743040)] + [DataRow(8120654, 8736900, 8120820, 8736896)] + [DataRow(8052366, 8698287, 8052543, 8698296)] + [DataRow(8052373, 8698287, 8052550, 8698296)] + [DataRow(8052380, 8698287, 8052557, 8698296)] + [DataRow(8052387, 8698287, 8052564, 8698296)] + [DataRow(8114850, 8731041, 8115020, 8731040)] + [DataRow(8108318, 8724510, 8108492, 8724512)] + [DataRow(8102251, 8718452, 8102428, 8718456)] + [DataTestMethod] + public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long testRA, long testDec) + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + EncoderPosition test = new EncoderPosition(testRA, testDec); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Reverse_Map", BindingFlags.NonPublic | BindingFlags.Instance); + EncoderPosition result = (EncoderPosition)methodInfo.Invoke(_alignmentModel, new object[] { test }); + // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); + Assert.AreEqual(expectedRa, result.RA, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.Dec, "Dec result is incorrect"); + } + + /* + Get_EncoderHours [DataRow( 6.00557616960605 , 8388608 , 8388037 , 2457601 )] // (EQ_SphericalPolar) + Get_EncoderDegrees [DataRow( 298.381592455407 , 9003008.25 , 9196760 , 2457601 )] // (EQ_SphericalPolar) + Range360 [DataRow( 298.381592455407 )] // (EQ_SphericalPolar) + hadec_aa [DataRow( 0.919235827154167 , 1.57225616639081 , 5.20774120974001 ,-0.775376033155811 , 3.86988561836677 )] // (EQ_SphericalPolar) + [DataRow( 8388037 , 9196760 , 8673472.03453868 , 9625248.59910099 , 1 )] // (EQ_SphericalPolar) + + * + Get_EncoderHours [DataRow( 7.3038666569553 , 8388608 , 8255092 , 2457601 )] // (EQ_SphericalPolar) + Get_EncoderDegrees [DataRow( 596.661305069456 , 9003008.25 , 8775416 , 2457601 )] // (EQ_SphericalPolar) + Range360 [DataRow( 236.661305069456 )] // (EQ_SphericalPolar) + hadec_aa [DataRow( 0.919235827154167 , 1.91214782155489 , 4.13051898080895 ,-0.585620724448854 , 2.47103051434048 )] // (EQ_SphericalPolar) + [DataRow( 8255092 , 8775416 , 8126324.76231087 , 9773690.13425487 , 1 )] // (EQ_SphericalPolar) + + Get_EncoderHours [DataRow( 2.10939611434078 , 8388608 , 8787006 , 2457601 )] // (EQ_SphericalPolar) + Get_EncoderDegrees [DataRow( 544.180076424122 , 9003008.25 , 8417144 , 2457601 )] // (EQ_SphericalPolar) + Range360 [DataRow( 184.180076424122 )] // (EQ_SphericalPolar) + hadec_aa [DataRow( 0.919235827154167 , 0.552238611994933 , 3.21454874650256 ,-0.610002127045004 , 0.692316929152782 )] // (EQ_SphericalPolar) + [DataRow( 8787006 , 8417144 , 7430599.89173006 , 9754617.08246391 , 1 )] // (EQ_SphericalPolar) + + Get_EncoderHours [DataRow( 9.09690303674193 , 8388608 , 8071485 , 2457601 )] // (EQ_SphericalPolar) + Get_EncoderDegrees [DataRow( 360.214379795581 , 9003008.25 , 9618872 , 2457601 )] // (EQ_SphericalPolar) + Range360 [DataRow( 0.214379795581124 )] // (EQ_SphericalPolar) + hadec_aa [DataRow( 0.919235827154167 , 2.38156364862407 , 3.74163327836756E-03 ,-0.45178319762006 , 5.41095216511199 )] // (EQ_SphericalPolar) + [DataRow( 8071485 , 9618872 , 9276243.79763711 , 9878388.38000644 , 1 )] // (EQ_SphericalPolar) + */ + + [DataRow(8388037, 9196760, 8673472.03453868, 9625248.59910099, 1)] + [DataRow(8255092, 8775416, 8126324.76231087, 9773690.13425487, 1)] // (EQ_SphericalPolar) + [DataRow(8787006, 8417144, 7430599.89173006, 9754617.08246391, 1)] // (EQ_SphericalPolar) + [DataRow(8071485, 9618872, 9276243.79763711, 9878388.38000644, 1)] // (EQ_SphericalPolar) + [DataTestMethod] + public void Test_EQ_SphericalPolar(long ra, long dec, double expectedX, double expectedY, double expectedR) + + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + EncoderPosition test = new EncoderPosition(ra, dec); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("EQ_SphericalPolar", BindingFlags.NonPublic | BindingFlags.Instance); + SphericalCoord result = (SphericalCoord)methodInfo.Invoke(_alignmentModel, new object[] { test }); + Assert.AreEqual(expectedX, result.x, 1d, "x result is incorrect"); + Assert.AreEqual(expectedY, result.y, 1d, "y result is incorrect"); + Assert.AreEqual(expectedR, result.r, 1d, "r result is incorrect"); + } + + [DataRow(509702.147272839, -0.545762684044915, 8388607.58399624, 9512710.14727313)] // 2457601 8388608 9003008.25 (EQ_plAffine) + [DataTestMethod] + public void Test_EQ_Polar2Cartes(double expectedRa, double expectedDec, double testX, double testY) + + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + SphericalCoord test = new SphericalCoord(testX, testY, 0); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("EQ_Polar2Cartes", BindingFlags.NonPublic | BindingFlags.Instance); + CartesCoord result = (CartesCoord)methodInfo.Invoke(_alignmentModel, new object[] { test }); + Assert.AreEqual(expectedRa, result.x, doubleDelta, "x result is incorrect"); + Assert.AreEqual(expectedDec, result.y, doubleDelta, "y result is incorrect"); } + + + + + // EQ_Transform_Affine[DataRow(509688.110229567, 43.3535014036799, 509701.89727284, -0.545762684044915, 1)] // (EQ_plAffine) + + + [DataRow(8388641.26987594, 9512696.11207337, 0, 509688.110229567, 43.3535014036799, 1, 0)] // 2457601 8388608 9003008.25 (EQ_plAffine) + [DataTestMethod] + public void Test_EQ_Cartes2Polar(double expectedX, double expectedY, double expectedR, double testX, double testY, double testR,double testRa) + { + // EQ_Cartes2Polar(tmpobj3.X, tmpobj3.Y, tmpobj1.r, tmpobj1.RA, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos) + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + CartesCoord test = new CartesCoord(testX, testY, 0d, 0d); + CartesCoord rads = new CartesCoord(0d, 0d, testR, testRa); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("EQ_Cartes2Polar", BindingFlags.NonPublic | BindingFlags.Instance); + SphericalCoord result = (SphericalCoord)methodInfo.Invoke(_alignmentModel, new object[] { test, rads }); + Assert.AreEqual(expectedX, result.x, doubleDelta, "x result is incorrect"); + Assert.AreEqual(expectedY, result.y, doubleDelta, "y result is incorrect"); + } + + /* + i / j = 45.6245611530248 /-35.8465499073082 + aa_hadec [DataRow( 0.919235827154167 ,-0.625640320648098 , 0.796298810987879 ,-2.51826869952598 ,-0.122171513161253 )]// (EQ_PolarSpherical) + X/Y = 2.38092213307473 / 186.999912079268 + [DataRow( 7471271.29753954 , 9742383.65611805 , 1 , 8759202 , 8436394 )] // (EQ_PolarSpherical) + + i / j = 293.182350156892 /-35.2779827906899 + aa_hadec [DataRow( 0.919235827154167 ,-0.615716952455876 , 5.11699731312566 , 2.24992160190372 ,-0.267520981472236 )]// (EQ_PolarSpherical) + X/Y = 8.59406745883108 / 344.672176833943 + [DataRow( 9161266.49146647 , 9750146.49564232 , 1 , 8122975 , 9512771 )] // (EQ_PolarSpherical) + + i / j = 225.266546243132 /-15.7592732434377 + aa_hadec [DataRow( 0.919235827154167 ,-0.275051205505143 , 3.93164292204616 , 1.07035991069787 ,-0.677340930938018 )]// (EQ_PolarSpherical) + X/Y = 4.08847369169778 / 321.191223374651 + [DataRow( 8697627.74809352 , 10016642.0517647 , 1 , 8584348 , 9352474 )] // (EQ_PolarSpherical) + + i / j = 135.229150634789 /-31.6026716503086 + aa_hadec [DataRow( 0.919235827154167 ,-0.551570672094294 , 2.36019392055553 ,-1.30546762821246 ,-0.900034929862018 )]// (EQ_PolarSpherical) + X/Y = 7.01348097965497 / 231.568202883672 + [DataRow( 8082972.21063669 , 9800326.76416405 , 1 , 8284828 , 8740647 )] // (EQ_PolarSpherical) + + */ + + [DataRow(7471271.29753954, 9742383.65611805, 1, 8759202, 8436394)] // (EQ_PolarSpherical) + [DataRow(9161266.49146647, 9750146.49564232, 1, 8122975, 9512771)] // (EQ_PolarSpherical) + [DataRow(8697627.74809352, 10016642.0517647, 1, 8584348, 9352474)] // (EQ_PolarSpherical) + [DataRow(8082972.21063669, 9800326.76416405, 1, 8284828, 8740647)] // (EQ_PolarSpherical) + [DataTestMethod] + public void Test_EQ_PolarSpherical(double ra, double dec, long range, double testX, double testY) + + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + SphericalCoord test = new SphericalCoord(ra, dec, 0d); + SphericalCoord rads = new SphericalCoord(0d, 0d, range); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("EQ_PolarSpherical", BindingFlags.NonPublic | BindingFlags.Instance); + EncoderPosition result = (EncoderPosition)methodInfo.Invoke(_alignmentModel, new object[] { test, rads }); + Assert.AreEqual(testX, result.RA, 1d, "x result is incorrect"); + Assert.AreEqual(testY, result.Dec, 1d, "y result is incorrect"); + } + + + + [DataRow(7.17370069429496, 8388608, 8268421, 2457601)] // (EQ_SphericalPolar) + [DataRow(6.00557616960605, 8388608, 8388037, 2457601)] + [DataRow(7.3038666569553, 8388608, 8255092, 2457601)] + [DataRow(9.09690303674193, 8388608, 8071485, 2457601)] + [DataRow(2.10939611434078, 8388608, 8787006, 2457601)] + [DataTestMethod] + public void Test_Get_EncoderHours(double expectedHrs, long raCentre, long encoderRa, long stepsPerRev) + { + // Get_EncoderHours(RACENTER, RA, TOT, 0) + Assert.AreEqual(_alignmentModel.HomeEncoder.RA, raCentre, "RA Home position is incorrect."); + Assert.AreEqual(_alignmentModel.StepsPerRev.RA, stepsPerRev, "RA Steps Per 360 is incorrect"); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("Get_EncoderHours", BindingFlags.NonPublic | BindingFlags.Instance); + double result = (double)methodInfo.Invoke(_alignmentModel, new object[] { encoderRa }); + Assert.AreEqual(expectedHrs, result, doubleDelta, "Resultant hours are incorrect"); + } + + [DataRow(246.372629242908, 9003008, 8841712, 2457601)] // (EQ_SphericalPolar) + [DataRow(298.381592455407, 9003008, 9196760, 2457601)] + [DataRow(236.661305069456, 9003008, 8775416, 2457601)] + [DataRow(184.180076424122, 9003008, 8417144, 2457601)] + [DataRow(0.214379795581124, 9003008, 9618872, 2457601)] + [DataTestMethod] + public void Test_Get_EncoderDegrees(double expectedDegrees, long decCentre, long encoderDec, long stepsPerRev) + { + // j = Get_EncoderDegrees(DECCENTER, DEC, TOT, 0) + 270 + Assert.AreEqual(_alignmentModel.HomeEncoder.Dec, decCentre, "Dec Home position is incorrect."); + Assert.AreEqual(_alignmentModel.StepsPerRev.Dec, stepsPerRev, "Dec Steps Per 360 is incorrect"); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("Get_EncoderDegrees", BindingFlags.NonPublic | BindingFlags.Instance); + double result = (double)methodInfo.Invoke(_alignmentModel, new object[] { encoderDec }); + result = Range.Range360(result + 270d); + Assert.AreEqual(expectedDegrees, result, doubleDelta, "Resultant degrees are incorrect"); + } + + + } } + + + diff --git a/EqmodNStarAlignment.Tests/AstroConvertTests.cs b/EqmodNStarAlignment.Tests/AstroConvertTests.cs new file mode 100644 index 00000000..ca9bbe05 --- /dev/null +++ b/EqmodNStarAlignment.Tests/AstroConvertTests.cs @@ -0,0 +1,113 @@ +using EqmodNStarAlignment.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; +using System.Diagnostics; + +namespace EqmodNStarAlignment.Tests +{ + [TestClass] + public class AstroConvertTests + { + [DataRow(52.6683333333333, 0, 51.5)] + [DataRow(52.6683333333333, 3.5, 51.5)] + [DataRow(52.6683333333333, 9.5, 51.5)] + [DataRow(52.6683333333333, 12.0, 51.5)] + [DataRow(52.6683333333333, 15.5, 51.5)] + [DataRow(52.6683333333333, 21.5, 51.5)] + [DataRow(52.6683333333333, 0, -51.5)] + [DataRow(52.6683333333333, 3.5, -51.5)] + [DataRow(52.6683333333333, 9.5, -51.5)] + [DataRow(52.6683333333333, 12.0, -51.5)] + [DataRow(52.6683333333333, 15.5, -51.5)] + [DataRow(52.6683333333333, 21.5, -51.5)] + [DataTestMethod] + public void CompareHaDec_aa2GetAltAz(double lat, double ha, double dec) + { + double haRad = AstroConvert.HrsToRad(Range.Range24(ha)); + double decRad = AstroConvert.DegToRad(Range.Range360(dec)); + double latRad = AstroConvert.DegToRad(lat); + Debug.WriteLine($"HA/Dec (Radians) = {haRad}/{decRad}"); + + + double[] altAzRad1 = AstroConvert.GetAltAz(latRad, haRad, decRad); + Debug.WriteLine($"Alt/Az 1 (Radians) = {altAzRad1[0]}/{altAzRad1[1]}"); + + double altOut = 0d; + double azOut = 0d; + Legacy.hadec_aa(latRad, haRad, decRad, ref altOut, ref azOut); + + Debug.WriteLine($"Alt/Az 2 (Radians) = {altOut}/{azOut}"); + + Assert.AreEqual(altOut, altAzRad1[0], 0.0001); + Assert.AreEqual(azOut, altAzRad1[1], 0.0001); + + } + + [DataRow(52.6683333333333, 51.5, 35.0)] + [DataRow(52.6683333333333, 51.5, 125.0)] + [DataRow(52.6683333333333, 51.5, 180.0)] + [DataRow(52.6683333333333, 51.5, 215.0)] + [DataRow(52.6683333333333, 51.5, 305.0)] + [DataRow(52.6683333333333, -51.5, 35.0)] + [DataRow(52.6683333333333, -51.5, 125.0)] + [DataRow(52.6683333333333, -51.5, 180.0)] + [DataRow(52.6683333333333, -51.5, 215.0)] + [DataRow(52.6683333333333, -51.5, 305.0)] + [DataTestMethod] + public void CompareAa_hadec2GetHaDec(double lat, double alt, double az) + { + double altRad = AstroConvert.DegToRad(Range.Range90(alt)); + double azRad = AstroConvert.DegToRad(Range.Range360(az)); + double latRad = AstroConvert.DegToRad(lat); + Debug.WriteLine($"\nAlt/Az (Radians) = {altRad}/{azRad}"); + + + double[] haDecRad1 = AstroConvert.GetHaDec(latRad, altRad, azRad); + Debug.WriteLine($"HA/Dec 1 (Radians) = {haDecRad1[0]}/{haDecRad1[1]}"); + + double haOut = 0d; + double decOut = 0d; + Legacy.aa_hadec(latRad, altRad, azRad, ref haOut, ref decOut); + + Debug.WriteLine($"HA/Dec 2 (Radians) = {haOut}/{decOut}"); + + Assert.AreEqual(haOut, haDecRad1[0], 0.0001); + Assert.AreEqual(decOut, haDecRad1[1], 0.0001); + + } + + /* + \\ hadec_aa( 0.919235827154167 , 1.38444074819784 , 5.38324899333645 , -0.585928494201069 , 3.96459956111439 ) + hadec_aa [DataRow(-33.5712298065115 , 227.154822259407 , 5.28817411776769 , 308.437447738669 , 52.6683333333333 )] // (EQ_SphericalPolar) + \\ aa_hadec( 0.919235827154167 , -0.586184018473869 , 3.96475101882834 , 1.38487663513127 , -0.9000246120113 ) + aa_hadec [DataRow( 79.3475863211831 ,-51.5676117143725 ,-33.5858703149488 , 227.163500458629 , 52.6683333333333 )]// (EQ_PolarSpherical) + + \\ hadec_aa( 0.919235827154167 , 1.56557568277018 , 4.71760386839224 , -0.919190774841039 , 3.15019144835534 ) + hadec_aa [DataRow(-52.6657519537263 , 180.492674607753 , 5.98005860186418 , 270.298791382328 , 52.6683333333333 )] // (EQ_SphericalPolar) + \\ aa_hadec( 0.919235827154167 , -0.919213641878334 , 3.15024659248481 , 1.5707963267949 , -1.56554822344537 ) + aa_hadec [DataRow( 89.9999999794503 ,-89.6993058071428 ,-52.6670622106594 , 180.495834381095 , 52.6683333333333 )]// (EQ_PolarSpherical) + + */ + + [DataRow(0.919235827154167, 1.38444074819784, 5.38324899333645, -0.585928494201069, 3.96459956111439)] + [DataRow(0.919235827154167, 1.56557568277018, 4.71760386839224, -0.919190774841039, 3.15019144835534)] + [DataTestMethod] + public void TestGetAltAz(double latRad, double haRad, double decRad, double altRad, double azRad) + { + double[] altAzRad = AstroConvert.GetAltAz(latRad, haRad, decRad); + Assert.AreEqual(altRad, altAzRad[0], 0.001, "Alt is wrong value"); + Assert.AreEqual(azRad, altAzRad[1], 0.001, "Az is wrong value"); + } + + [DataRow(0.919235827154167, -0.586184018473869, 3.96475101882834, 1.38487663513127, -0.9000246120113)] + [DataRow(0.919235827154167, -0.919213641878334, 3.15024659248481, 1.5707963267949, -1.56554822344537)] + [DataTestMethod] + public void TestGetHaDec(double latRad, double altRad, double azRad, double haRad, double decRad) + { + double[] haDecRad = AstroConvert.GetHaDec(latRad, altRad, azRad); + Assert.AreEqual(haRad, haDecRad[0], 0.001, "HA is wrong value"); + Assert.AreEqual(decRad, haDecRad[1], 0.001, "Dec is wrong value"); + } + + } +} diff --git a/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json b/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json index b1bf1ca9..ae7ed0ac 100644 --- a/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json +++ b/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json @@ -7,9 +7,9 @@ "Dec": 8919464 }, "EncoderCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 342728.16089956538, + "y": -6649.3588683929838, + "z": 1.0 }, "OrigRaDec": { "RA": 23.6715774536133, @@ -20,9 +20,9 @@ "Dec": 8919479 }, "TargetCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 342758.08223162079, + "y": -6646.4711006996022, + "z": 1.0 } }, { @@ -33,9 +33,9 @@ "Dec": 9135000 }, "EncoderCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 278206.08853135124, + "y": 136673.20035502975, + "z": 1.0 }, "OrigRaDec": { "RA": 21.481803894043, @@ -46,9 +46,9 @@ "Dec": 9135003 }, "TargetCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 278173.736918419, + "y": 136623.09109976405, + "z": 1.0 } }, { @@ -59,9 +59,9 @@ "Dec": 9164640 }, "EncoderCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 191153.88419931807, + "y": 59329.821460311192, + "z": 1.0 }, "OrigRaDec": { "RA": 22.8413619995117, @@ -72,9 +72,529 @@ "Dec": 9164630 }, "TargetCartesian": { - "x": 0.0, - "y": 0.0, - "z": 0.0 + "x": 191150.61251677698, + "y": 59182.4784978333, + "z": 1.0 + } + }, + { + "Id": 4, + "AlignTime": "2022-11-30T20:51:15", + "Encoder": { + "RA": 8200354, + "Dec": 9412632 + }, + "EncoderCartesian": { + "x": -13919.881744680215, + "y": 684697.9981491986, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 21.2521438598633, + "Dec": 29.9979152679443 + }, + "Target": { + "RA": 8200185, + "Dec": 9412623 + }, + "TargetCartesian": { + "x": -14139.317224949669, + "y": 684475.672556519, + "z": 1.0 + } + }, + { + "Id": 5, + "AlignTime": "2022-11-30T20:51:45", + "Encoder": { + "RA": 8380206, + "Dec": 9263912 + }, + "EncoderCartesian": { + "x": 416846.96845720615, + "y": 553420.05401999969, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 19.5041027069092, + "Dec": 51.7807502746582 + }, + "Target": { + "RA": 8380039, + "Dec": 9263918 + }, + "TargetCartesian": { + "x": 416628.11493296688, + "y": 553391.65624300111, + "z": 1.0 + } + }, + { + "Id": 6, + "AlignTime": "2022-11-30T20:52:18", + "Encoder": { + "RA": 8421824, + "Dec": 9522552 + }, + "EncoderCartesian": { + "x": 238415.57011894978, + "y": 1092404.25300819, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 19.107213973999, + "Dec": 13.8985624313354 + }, + "Target": { + "RA": 8421625, + "Dec": 9522528 + }, + "TargetCartesian": { + "x": 237966.90363106574, + "y": 1092221.8164167311, + "z": 1.0 + } + }, + { + "Id": 7, + "AlignTime": "2022-11-30T20:53:31", + "Encoder": { + "RA": 7887790, + "Dec": 9676808 + }, + "EncoderCartesian": { + "x": -815547.06846760714, + "y": 273221.7218742111, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 0.343226462602615, + "Dec": -8.69821166992188 + }, + "Target": { + "RA": 7887531, + "Dec": 9676788 + }, + "TargetCartesian": { + "x": -815608.9485487903, + "y": 272599.02581901528, + "z": 1.0 + } + }, + { + "Id": 8, + "AlignTime": "2022-11-30T20:54:12", + "Encoder": { + "RA": 7907761, + "Dec": 9417944 + }, + "EncoderCartesian": { + "x": -291027.75380665145, + "y": 237650.45582203756, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 0.159508779644966, + "Dec": 29.2189121246338 + }, + "Target": { + "RA": 7907519, + "Dec": 9417941 + }, + "TargetCartesian": { + "x": -291127.43161888863, + "y": 237226.22113095695, + "z": 1.0 + } + }, + { + "Id": 9, + "AlignTime": "2022-11-30T20:54:51", + "Encoder": { + "RA": 8155121, + "Dec": 9549296 + }, + "EncoderCartesian": { + "x": -320725.98442469758, + "y": 779540.8161398056, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 21.7548809051514, + "Dec": 9.98066520690918 + }, + "Target": { + "RA": 8154849, + "Dec": 9549274 + }, + "TargetCartesian": { + "x": -321065.92753720423, + "y": 779031.81836311787, + "z": 1.0 + } + }, + { + "Id": 10, + "AlignTime": "2022-11-30T20:56:38", + "Encoder": { + "RA": 8964653, + "Dec": 8318792 + }, + "EncoderCartesian": { + "x": -856204.6769207156, + "y": -93064.025504266756, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 1.87664878368378, + "Dec": -10.2228670120239 + }, + "Target": { + "RA": 8964648, + "Dec": 8318820 + }, + "TargetCartesian": { + "x": -856147.97213822755, + "y": -93074.688817985909, + "z": 1.0 + } + }, + { + "Id": 11, + "AlignTime": "2022-11-30T20:57:16", + "Encoder": { + "RA": 8549669, + "Dec": 8439192 + }, + "EncoderCartesian": { + "x": -241287.73550525878, + "y": -923730.87958620174, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 5.94036722183228, + "Dec": 7.41184711456299 + }, + "Target": { + "RA": 8549590, + "Dec": 8439206 + }, + "TargetCartesian": { + "x": -241125.82207367822, + "y": -923845.64256972133, + "z": 1.0 + } + }, + { + "Id": 12, + "AlignTime": "2022-11-30T20:58:21", + "Encoder": { + "RA": 8836220, + "Dec": 8668816 + }, + "EncoderCartesian": { + "x": -118016.3137986113, + "y": -249147.29470023135, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 3.16128063201904, + "Dec": 41.0447845458984 + }, + "Target": { + "RA": 8836045, + "Dec": 8668807 + }, + "TargetCartesian": { + "x": -117948.42381812769, + "y": -249405.35522428833, + "z": 1.0 + } + }, + { + "Id": 13, + "AlignTime": "2022-11-30T20:59:35", + "Encoder": { + "RA": 8810409, + "Dec": 8729584 + }, + "EncoderCartesian": { + "x": 10587.822495838014, + "y": -241814.3121508582, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 3.43303275108337, + "Dec": 49.9433364868164 + }, + "Target": { + "RA": 8810306, + "Dec": 8729555 + }, + "TargetCartesian": { + "x": 10584.066870398241, + "y": -241958.97158849737, + "z": 1.0 + } + }, + { + "Id": 14, + "AlignTime": "2022-11-30T21:00:36", + "Encoder": { + "RA": 8028636, + "Dec": 8809304 + }, + "EncoderCartesian": { + "x": 799568.8135243149, + "y": -275811.9765455196, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 11.0852670669556, + "Dec": 61.624095916748 + }, + "Target": { + "RA": 8028459, + "Dec": 8809295 + }, + "TargetCartesian": { + "x": 799708.560806113, + "y": -275671.60279076087, + "z": 1.0 + } + }, + { + "Id": 15, + "AlignTime": "2022-11-30T21:01:14", + "Encoder": { + "RA": 8378814, + "Dec": 8423856 + }, + "EncoderCartesian": { + "x": 88280.058254589487, + "y": -1181333.7144075404, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 7.6750659942627, + "Dec": 5.16721248626709 + }, + "Target": { + "RA": 8378754, + "Dec": 8423883 + }, + "TargetCartesian": { + "x": 88475.4938693466, + "y": -1181348.8395656894, + "z": 1.0 + } + }, + { + "Id": 16, + "AlignTime": "2022-11-30T21:01:45", + "Encoder": { + "RA": 8387315, + "Dec": 8605928 + }, + "EncoderCartesian": { + "x": 316116.1919223427, + "y": -833792.92244761018, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 7.60103368759155, + "Dec": 31.8366107940674 + }, + "Target": { + "RA": 8387210, + "Dec": 8605946 + }, + "TargetCartesian": { + "x": 316332.94734941737, + "y": -833809.39461784938, + "z": 1.0 + } + }, + { + "Id": 17, + "AlignTime": "2022-11-30T21:02:17", + "Encoder": { + "RA": 8206767, + "Dec": 8622712 + }, + "EncoderCartesian": { + "x": 686997.790061526, + "y": -797459.83996625361, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 9.37405490875244, + "Dec": 34.2941551208496 + }, + "Target": { + "RA": 8206583, + "Dec": 8622723 + }, + "TargetCartesian": { + "x": 687373.25458370347, + "y": -797335.29697127256, + "z": 1.0 + } + }, + { + "Id": 18, + "AlignTime": "2022-11-30T21:02:58", + "Encoder": { + "RA": 8661869, + "Dec": 8841768 + }, + "EncoderCartesian": { + "x": 285414.38366064249, + "y": -249659.318428496, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 4.93953990936279, + "Dec": 66.3796844482422 + }, + "Target": { + "RA": 8661823, + "Dec": 8841760 + }, + "TargetCartesian": { + "x": 285428.00986361125, + "y": -249697.51210656876, + "z": 1.0 + } + }, + { + "Id": 19, + "AlignTime": "2022-11-30T21:03:24", + "Encoder": { + "RA": 8625168, + "Dec": 8702760 + }, + "EncoderCartesian": { + "x": 102260.38822977719, + "y": -477240.57892356854, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 5.30665588378906, + "Dec": 46.0202331542969 + }, + "Target": { + "RA": 8624972, + "Dec": 8702773 + }, + "TargetCartesian": { + "x": 102477.42021589061, + "y": -477417.913543929, + "z": 1.0 + } + }, + { + "Id": 20, + "AlignTime": "2022-11-30T21:03:58", + "Encoder": { + "RA": 8696329, + "Dec": 8501640 + }, + "EncoderCartesian": { + "x": -327512.345605439, + "y": -604327.76189749048, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 4.62079238891602, + "Dec": 16.5555591583252 + }, + "Target": { + "RA": 8696186, + "Dec": 8501627 + }, + "TargetCartesian": { + "x": -327381.17138699419, + "y": -604596.83183397341, + "z": 1.0 + } + }, + { + "Id": 21, + "AlignTime": "2022-11-30T21:05:44", + "Encoder": { + "RA": 8959119, + "Dec": 9178696 + }, + "EncoderCartesian": { + "x": 858342.46155537292, + "y": 46924.7693590433, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 14.0829401016235, + "Dec": 64.2641220092773 + }, + "Target": { + "RA": 8959093, + "Dec": 9178699 + }, + "TargetCartesian": { + "x": 858345.16833731206, + "y": 46953.300017825939, + "z": 1.0 + } + }, + { + "Id": 22, + "AlignTime": "2022-11-30T21:06:15", + "Encoder": { + "RA": 8912307, + "Dec": 9356584 + }, + "EncoderCartesian": { + "x": 1187015.8701597615, + "y": 218031.25275041172, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 14.549503326416, + "Dec": 38.2075653076172 + }, + "Target": { + "RA": 8912190, + "Dec": 9356578 + }, + "TargetCartesian": { + "x": 1186928.6231936759, + "y": 218298.30140286568, + "z": 1.0 + } + }, + { + "Id": 23, + "AlignTime": "2022-11-30T21:07:12", + "Encoder": { + "RA": 8412924, + "Dec": 9595864 + }, + "EncoderCartesian": { + "x": 101238.08335319124, + "y": 1219790.59552515, + "z": 1.0 + }, + "OrigRaDec": { + "RA": 19.4437313079834, + "Dec": 3.1609582901001 + }, + "Target": { + "RA": 8412645, + "Dec": 9595830 + }, + "TargetCartesian": { + "x": 100578.5267699728, + "y": 1219452.4650133308, + "z": 1.0 } } ] \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj index 45b55d0a..ebf61ddf 100644 --- a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj +++ b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj @@ -50,9 +50,12 @@ + + + @@ -66,6 +69,11 @@ EqmodNStarAlignment + + + Always + + diff --git a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs index 49a1ab93..e137e57b 100644 --- a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs +++ b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs @@ -6,13 +6,15 @@ namespace EqmodNStarAlignment.Tests { - + //TODO: Set methods back to private and invoke using reflection. [TestClass] public class EqmodVectorTests { const double siteLatitude = 52.6683333333333; const double siteLongitude = -1.33888888888889; const double siteElevation = 200d; + const double siteTemperatire = 15d; + const long decHomePos = 9003008; const long raHomePos = 8388608; const double doubleDelta = 0.00000001; @@ -29,6 +31,7 @@ public void Initialize() AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); AlignmentModel.SetHomePosition(raHomePos, decHomePos); AlignmentModel.PolarEnable = true; + } [TestMethod] @@ -63,28 +66,5 @@ public void TestEQ_sp2Cs_2() Assert.AreEqual(expected.z, result.z); } - [TestMethod] - public void TestHaDec2AltAz() - { - double ha = 4.48782288093145; - double dec = 269.701135375515; - - double[] expected = new double[] { -52.7827108032482, 179.544092452796 }; - double[] result = AstroConvert.HaDec2AltAz(ha, dec, siteLatitude); - - Assert.AreEqual(expected[0], result[0], doubleDelta); - Assert.AreEqual(expected[1], result[1], doubleDelta); - - } - - [TestMethod] - public void TestGet_EncoderHours() - { - double expected = 1.4054315570346851; - double result = AlignmentModel.Get_EncoderHours(8859092); - Assert.AreEqual(expected, result, doubleDelta); - } - - } } diff --git a/EqmodNStarAlignment.Tests/Legacy.cs b/EqmodNStarAlignment.Tests/Legacy.cs new file mode 100644 index 00000000..6199e517 --- /dev/null +++ b/EqmodNStarAlignment.Tests/Legacy.cs @@ -0,0 +1,92 @@ +/* +MIT License + +Copyright (c) 2017 Phil Crompton + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. + + Portions + Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +*/ + +using System; +using System.Diagnostics; +using System.Runtime.InteropServices; + +namespace EqmodNStarAlignment.Tests +{ + + public static class Legacy + { + #region Astro32.dll ... + /// + /// ================= + /// LIBRARY FUNCTIONS + /// ================= + /// + /// NOTES: + /// + /// (1) For whatever reason, the authors of the original C functions chose + /// to pass back and forth via parameters only for most functions. + /// + /// (2) The descriptive comments below were lifted straight out of the C + /// functions. Some variables are listed with the C dereferening ///*///. + /// Note that these are passed ByRef in the declarations, then forget + /// about the ///*///. + /// + /// (3) Modified Julian Dates (number of days elapsed since 1900 jan 0.5,) + /// are used for most times. Several functions are provided for converting + /// between mjd and other time systems (C runtime, VB, Win32). + /// + /// + /// given latitude (n+, radians), lat, altitude (up+, radians), alt, and + /// azimuth (angle around to the east from north+, radians), + /// return hour angle (radians), ha, and declination (radians), dec. + /// + [DllImport("astro32.dll")] + public static extern void aa_hadec(double lat, double alt, double az, ref double ha, ref double dec); + // Declare Sub aa_hadec Lib "astro32" (ByVal lat As Double, ByVal Alt As Double, ByVal Az As Double, ByRef ha As Double, ByRef DEC As Double) + + /// + /// given latitude (n+, radians), lat, hour angle (radians), ha, and declination + /// (radians), dec, return altitude (up+, radians), alt, and azimuth (angle + /// round to the east from north+, radians), + /// + + [DllImport("astro32.dll")] + public static extern void hadec_aa(double lat, double ha, double dec, ref double alt, ref double az); + // Declare Sub hadec_aa Lib "astro32" (ByVal lat As Double, ByVal ha As Double, ByVal DEC As Double, ByRef Alt As Double, ByRef Az As Double) + + #endregion + } +} diff --git a/EqmodNStarAlignment.Tests/RangeTests.cs b/EqmodNStarAlignment.Tests/RangeTests.cs new file mode 100644 index 00000000..bb2661a1 --- /dev/null +++ b/EqmodNStarAlignment.Tests/RangeTests.cs @@ -0,0 +1,21 @@ +using EqmodNStarAlignment.Utilities; +using Microsoft.VisualStudio.TestTools.UnitTesting; +using System; + +namespace EqmodNStarAlignment.Tests +{ + [TestClass] + public class RangeTests + { + [DataRow(3d, 3d, 6d)] + [DataRow(3d, 9d, 6d)] + [DataRow(0d, 0d, 6d)] + [DataRow(3d, -3d, 6d)] + [DataRow(3d, -9d, 6d)] + [DataTestMethod] + public void TestRangeValue(double expectedValue, double testValue, double range) + { + Assert.AreEqual(expectedValue, Range.ZeroToValue(testValue, range)); + } + } +} diff --git a/EqmodNStarAlignment.Tests/astro32.dll b/EqmodNStarAlignment.Tests/astro32.dll new file mode 100644 index 0000000000000000000000000000000000000000..61780dcd54fccd7d30898f8202942f366464fb83 GIT binary patch literal 28672 zcmeHv4|vnnx&KL;loXOSK%yzM7+vZrl$ti_f10G)LUok2r4-OgDYT_!rR~}T0YQtQ zUP@rr4L9}bMBOHH-i6GH1A)DG_g6QBb*s3UsMQL+C?>YIl1^Kz(eV*U% zcc0($Na=C#_qV^!qB{DTKSi_Wqh7yu zzii>_*Ot}Qw;G#Un%1;btuwB!YHVzB8dudATU?FC`bJ~^_ZJ)2HC5LnYc!KhA<@o< z?pkKPpr0baA5PDll7e#Oe_k`i%G0S+QhB{@${eIej;p6wkX9d0n399^%iwfQ|CfQO zJT0wXT}QJ1SC$tSFt$*pWGTyMIV75sEc)6hvPi~^z=W_P$;fK~W&q_V41GPW|grMk*l#n?+KU?G#!Qaa&rz)Q)3jP+_z0R*R`bi(6c%$wZO z+Oirr-qvDdNH?Vu9tX*5scC2e;b+wLl>nlnbi(6c?4}9Da5n6Lum{2(2zwyxfv^X{ z9te9N?18Wc!X5~F;J@JkPrk|MS!mLF%1r8VkJDr%d8WoGEZ92IhmC4D^#0UBD5~m~So#Ba8j9)Pg0RA@`|a z_s~3lfyx(ezL{wkmoMd}ZHnUd=~5t3?My$^d!>Dg(>@i9PpxAa}+tB z^6)o_;IkySD6zQ2-yhVgi2(iSOCUSky{f>-OvYlmbOi=<UA=m`ZdC?p+&WaGtjCj-1M`ln9e472#&3oTyH!fjTMbDMe28yyR`nH}z7 zxn#~BQc8v?xnX56EZ<~4(HB7>!p-n$9s&&+b)xS?_rwqZU!pI*6SX2b$dE)|0wD&x z2n5Y`(F0pFa+RNSZ!odkVCkBEu_84UwJ#-782Kd&Qw(ZFa{ivL8%h zta1g-EIK~3C@Fksa6pL;j?9 zdM~Vzd{l_=Mv?cxK4ivR;#2OWB9FfQZWxdl8VFM7_!>-!q60{~O3Za!&Yp>KP={eb z-Re_5G_eBwKy?y|jMr?RSP4{ONcWk*udc@Y%zNLnMcXlH+(bz56zPN!T7N8g!>4S6 zoIopBP&8thLeb+gbVN!mp33nF%|x~kWF3>@SQvQ!D%@_qh|XmXe|Z7@sBS;jq1~d0 zc(X&xhl~iDvA26jjWv#8WmD{ed&`^@VvS81FWQN z8&XVO{0f8JLo_&O%V8)lE)gSy+`d*%0~=L&#i^DMb;Hq1gw#!t=w6&i3qoT65-RqiBn-%HO zzq>%;enr=R z-Ey}#>QV>nFj13hqI=D?x;*Re6LFgcKWgXapdM|lmH z;{GGZy*|*>{}%*Jg=rb`-TkkhID`C3)VzwcuD{QJ+~1GV5z^WJ8n0~*m5y+}4e)ip zXN%6`qGN*!hT{mbfF>hTi6^GiQ?3ZjNX4E=I^b-@S`T3=^uz|F6y42WQk5*_v71Qc za`%vd3)g}o$+y$A4NgLK9x69;vV7#6oP;7j38jWmef3y<1#&o&6q7=ns6?R9cAm~t zN(y!VEV1N_^^-KfAxq)Y8_-XDTE1(EUzvy?=s!bCOK4;&9S9d}_YyKgsad3&M5I2Y zk=~)u=`4b-euNMN`jxz7!2Ez2M-8+<#7>+rpkL?HZ-)pewC8e@G;Kg3$Umdmm_NW&I`ug8T0QUF9F~71INc5hv4k;1S0c9n}VK0aj9#afpTU$(dWg*oZ5xW{F znjkdPgn=7&k{p90vMgIUWzC##v-LF^(@iy(6!LeDxldNX7|63O*J$j zvS=bR0{B9N_%-n02ZDC5Snue?1$>6pjkqBMt;5{b|3Uu+7;oUgY`~HQK{U`iAvm-N zaXte=92SijkbE4*N#k%r|EdRq+P&7{?TMKNIGGa zBiE~S4=194k+5Zw+gpvS0W-4#3%>~-XQe^C33A-MisFC)%Z}Jq2X;}mH<53pcpGug z0|OWgU}ON?jL1>ou%^Pot$we84k#z#L|;Nb-cUQ<6wWWr7id*rA595#;=;~}_8Gio zz;8GY2lH(`3OQqifEQa6S~fM!5RH|>SW=F?8S+apK6H?z3lx2Yoi0Kdq70?9gzf}8 z`q=;qBbJ{`2l&)$Sqa|&ScNDdWK6~lf<+}(go&F^v;cM?V%2aP|3wPi$k1qPm}uYW zQ=a9GR*m}$y0QNxwAil(@+RZ>J}$H*a2vc&V)*`7h(Qng5{ALEd;+Biv68^-Z_<<3 zl~<+@%mI13*E#J8EA^MgOmF6y8qsseqvr+rB|TIU>Rk#ixJrR7ekQRL8ZF1#`(hsK z@$|TR)#EJg%_dcZYbt!A@MsdTs&%Mv%u+G9{`a(>9BvOfr+D-ZlF_0Vob&|GnFH0R z+!2j-Yq#~emSSUg6=F&4(UXYwU}eYDmIMc3$ zQFBV_j9@|d&Vvefug>BH`wDP_89Zvw%X8k|q1vvNJD}+N#9Ho9^bbzzv?Ex&MC`P}5aC8oE?J1NNV6RVM#QIEN3_wno?79wxku(XuirYd3>y?z zrRUI#h!HwMmKN7-0Jj*wl`HPJ9d{Lr>zXB$I)nlP{lrNyR7O{~bO%Fs817!s7%XEOA!jr1 zyLc@}(VB8S4#jLK+q-ps?4vLxnpC9F8PkVczAJZ`E}FWQMo6)7(F<&-+p3ynHBhvEjyt%H(muPU$_vGeNM`9?J)cp+(;bTmV`zI%Dg=kdA zVL>xvg0k+2+~#%8oIfwydDXldozv#!IHTt!IVaDX>x`r-*XcIfm{KxXFD|VL6u5<4SA$8t%&Z%xNBsYWv#gyb0MjxQF7m5cK|vi%Hmqypn$)j(W;+ zeu3rKV0_MJxN9p?@tGOB4YElM16+zA4c#JD-nMr;ic~S}t7y?FGPr{>mpuzKG532R z#C<^))4l^4?ugJ#!^eJ1`<^khg9q37-n^I{9w0s4b9!R7T|}-hX4~(1(tZO>g4j4` z6iLEV<~N{dbVj3S4%A>~#I)8SLvu`6rnY@0WM>AxM>R`y9rBRRbudZpdh8qKxby;* zIcAE-MJ*Z|PJz3I#MH8c#u=^~Fk9dZB);$~DGdw-f>{3eH)c9vDVdfSI0C~Z(~Q^; zko{(y&HOWjtxnoDX9k|)WV#O7m1NvUmDC8ZkPOl2<_VI~Xf8REOCFOkHoHjox&0V% z;yg`<4(Y;eA9*W&FV<4Dm!>&Yhn^^(^5F&ZaNaJ2Ur?drTe-EY81pfms0{%p+(KUp zfDHG=C$A{Kn9JXDiF~4b>Xalufhy@r&k#~j?w=Kig=o5NEQW5n&Xc}+;H~2N`2AvF z4a8%3(=A7)1A7O$#!(3y5!OC_t0&zUG(#4)7IW)Fs$3aLmmv)eS@f>IKk(=vUmg|G zMlhIQfUsbKmcNa7lb^5=iOy2)gYkDK2Q`#>G}WlXeCCPj&^!->%U;(81B3dNz_)vs zKXrhR3X6BJ)@@`@P^nIVZ~5vNUQg{uG4LVLbE(Uh59UHg7AHd=n>`w$DBtzNi#cao zrg@^<`<#=4Z}MvQ$BMxZF_xE+{sfZCmakYVTZUT=EG~;Zci;;u7hMo&+t0hA+__{e z8@%2Q3)6js|&Sx14|r3OA@Y4PH~ zr??_$KTl#JT-OuPNkVvC5!V)|-CNYmIaQLa;?9l#981mpu20i=iS z80fM=q*0;tg56`1Z@N!^&c^9>{@fwxz4j1asC?4Cgg>W4_@klpY$(kabZvPd`e;Wj zf0jEe^h{sw(EWD7`wS)Y zyWyrhhG*xFJf5;+KXX)-m40{6!#2V9xAh`zcuu7I9up};K=WsID4iqHXCHIe<0|f2 z_0pbDJ2pA4{``bN&I0zQcfWIM;J0T&_$0@xKmNC&9iM$-PuX0(!u`TU?k~qJ7rk6; z=yf#zL+=eGZ|pf-5D@+}d?EB;9w3rVv?J@W(kJJ?_kjIS&qL++{Phmo)`A#o)Tv+F z9(kCa7wvz|z4|}}Wu-K%H# zez{QCqy3@7G1&5y>9;z2P3zpu((a@7$L{;1@ z8t3ATt=KDH`Gv$eXpQ&QNcn>YI1c$17j(y^5$ErRyVb>CGy&arluD5 zDXXk?HZ`!fWtGlNtu;=@cFQW8UCx@u^(>R9Yw=e?>=F68A2>-I%avC-o9Y=mDi`Hr z;6ufxrp6lPWtG*f&QKmQ4>@CvLSOq~Z$Xi?SM@hB# z3mlS&^heOU+PSg0hUsOM^{pbys#s;^x>c2{T`iUCsx~lIw7C4{(lXJS74q7a8rT#A z`o?;vv!-PodqBRfs)7IY%44jus(P)f)md3vUB6!HJn3(ZsxugU8N_k`iGc0sV`n<% zOW@zZU@>-5!Y%cy32cW%9l(kc#gYw@&3OEaJ;83ImGy{(E0}^B|RA0GhAW99l)3=+)rN;Tu|3~A+92J$(gx@x0Ho9+~8^E#f^weZB%Siga1gs{qu zHB~LFvFXmrhE^v}$;L*Pv$E!glvFwEn;Kcus)qU>y6T-9SxZ&pni|$pQ`=It+R0iP zt6}cyrp9X4y1KCvetOhfb4d#}pBYO~&;e_l5NxfODQ73|oSZnhH)>_nMb$$ptLo^a zhDoYPzle0;2QVA((JA*S_9+(P6NsSCwtw;wR1@FC`|TgnaQR0E&Ep@kWc=e(PW(7v z>*b$cMEj_%2~?E%JYgL#RpgX^ef&_^uo>`E1ZgQg-LNS!W;3Uh>8ef z#K-aj^4;?F@@4XTdA8ilKiSAHlCP3C0KWsZd*#o`UzQ)0AD5q!e=HxC%Om6wYJ7AN z(Gj1?UzE4WZ!~+pmDYhyy zl`ksuBKJocC$&sEGwDWEzUud?ZdFh2Rv`)&N8OI{@~DESWloOu)CWtQpeGQ`OPR;K$ zUufn>KOX%>baBjcF?#Ji+E2ArQ+uagKdp1x7t<=IADli-SEbvhi_mB5oAi(B-_Vch z)34fc)hkySu5P^g;MLO&<%Wk0uNpovM8(dEofrFj?BUp?8J+y|`HW>V58z|Oxr{&C z4|&UO%VlM^G3@%|0JB0co-5wean^vCQ{n_cC=V_N^J%4!p2VGy?z4n0fC)>OJbc_04&)vGbM|%%n{pZ1f zJijS&>x1suUf|_({^dS9`7SG1~gruW?oT!4M3WdE%0jWhF5 ze)75dZ|g3li<>v&L;Bl7_Z;FpDjFqcqe1aMEMz#*;5H8>@urd-ry%Tx?cvWYAjw}s>pPUw||WRT5* zR`3b?1)Z=?(uUuwaLIyGNFhzcFUjCV{t|5!7LM1F4xv$S5$Qy)2tN{5Z45IzP;F}Oea<2jIFbpO-G=e-6%IuLozc<3TNp2Uk3_ydTuy z3NnbF)13!)ICw5N2{|QvM*bZMUV#2#KqQ1jqD(dsj`Cz1#R8>d8;t=pzQoDE|{0e&@?18WcuH*q3|G|NQv9?QV#e9qT=^OYcO!9>wURjJanX5;?we zO2+qA$(+{Ab&x-toURel8YWnAxoi{oWo#j6*KkU*z8PL1tJbhOND<#%PNXSAExx(} z&pM<6LtJFttBp??K0^$_Wn`iM%x6PMbM3`q_6u#o?XIsbZ4Qwwf_r>T#tFR5=r z*~R@o(Z5MNiim%_{&H^#UrD+aqpdZNQ_n4(s4JiQr5yN{u@;O+8TQD~#hCB}^?w7m zcf3!caDxMa@Duhx*aKk?ggp@UK-dFe4}?7s_CVMJVGsPzc|eQb`^y+hHQ#K$&-}3Y zm*(G?UoamsA2GjamZ!{0NltO3d@rRWWogPCDXUZNOu0K{cgmiWU!}Z|(vxyH7m#13uC>@&W?g2ju-i1dnE0*X@5>T zmNu03b($hwlRiB?Ha#IdIsNAJh3QMuE7NPz8`C$W-<$49e=z;Y^nK|^(g)H%O=lTX zGtx7PGL~nIX3WY=%6uksU*^%wg;}Lpw`Wylth=O7FbFwotB?k1}yJc&RZ^8jMmxkt5?0 ztbXg4R#}=c&7QV6?Y6X^rahnbcG`PspQT+)GsAmT>D$tOmwr5bW=3j;J)<o2?Eh{0*4lnM=+MRVeD?Pg< zdvo@&?7zcPvvS&V9?j9s`|iBR-0O19xoNrf+>+ed+ zn`DczU2VI@mSDTdR%lyftFTqu*4kXQdu=;x57{2GJ!yLyUh1;-*-qF#w4Jq0vzzQ~ s_D7|Qp#Qm%64o5{K-dFe4}?7s_CVMJVGo2o5cWXW17Q#Rf9-+)0&o2?TL1t6 literal 0 HcmV?d00001 From 1411b5f03654f7055a98252f4ad16cbd74f64f3e Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Tue, 13 Dec 2022 10:32:04 +0000 Subject: [PATCH 05/18] TestMarices and Delta_Matrix_Reverse_Map now passing unit tests comparing to EQMOD. --- EQMODAlignment/Model/AlignmentModel_EqModVector.cs | 6 +++--- EqmodNStarAlignment.Tests/AlignmentModelTests.cs | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs index 7a853d30..ce1c3301 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EQMODAlignment/Model/AlignmentModel_EqModVector.cs @@ -765,7 +765,7 @@ internal bool EQ_UpdateAffine(EncoderPosition pos) nearestPoints[2].EncoderCartesian, nearestPoints[0].TargetCartesian, nearestPoints[1].TargetCartesian, - nearestPoints[1].TargetCartesian); + nearestPoints[2].TargetCartesian); } //// Subroutine to implement find Array index with the lowest value @@ -1489,7 +1489,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) centreDistance = Math.Pow(triangleCentre.x - posCartesean.x, 2) + Math.Pow(triangleCentre.y - posCartesean.y, 2); if (centreDistance < minCentreDistance) { - results = new List { p1, p2, p3 }; + results = new List { p1, p2, p3 }; // Reversed to match EQMOD sort order minCentreDistance = centreDistance; } } @@ -1497,7 +1497,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) } } - return results; + return results.OrderBy(p => p.AlignTime).ToList(); } diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index eee1117c..46f2827c 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -121,7 +121,7 @@ public void TestMatrices() _alignmentModel.EQ_NPointAppend(points[i]); } - Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 23); + Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 3); Assert.AreEqual(ExpectedTaki.Element[0, 0], AlignmentModel.EQMT.Element[0, 0], doubleDelta); Assert.AreEqual(ExpectedTaki.Element[0, 1], AlignmentModel.EQMT.Element[0, 1], doubleDelta); @@ -177,8 +177,8 @@ public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Reverse_Map", BindingFlags.NonPublic | BindingFlags.Instance); EncoderPosition result = (EncoderPosition)methodInfo.Invoke(_alignmentModel, new object[] { test }); // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.RA, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.Dec, "Dec result is incorrect"); + Assert.AreEqual(expectedRa, result.RA, 120, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.Dec, 120, "Dec result is incorrect"); } /* From 03c7159a681d08aa48b19a77342acbe60d7585e6 Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Thu, 15 Dec 2022 11:54:44 +0000 Subject: [PATCH 06/18] WIP: Synching now records what looks like sensible encoder positions. Moved EqmodNStarAlignment from .NET Std 2.0 to .NET Framework 4,7,2 to be compatibl with GS.Principles which it references. Removed old NStarAlignment project. --- .gitignore | 2 + EQMODAlignment/EqascomAlignment.csproj | 4 - EQMODAlignment/EqmodNStarAlignment.csproj | 26 ------ .../AlignmentModelTests.cs | 9 +- .../EqmodNStarAlignment.Tests.csproj | 35 +++---- EqmodNStarAlignment.Tests/EqmodVectorTests.cs | 3 +- EqmodNStarAlignment.Tests/packages.config | 5 - .../DataTypes/AxisPosition.cs | 0 .../DataTypes/EncoderPosition.cs | 3 + .../DataTypes/EqascomDataTypes.cs | 0 EqmodNStarAlignment/DataTypes/MapResult.cs | 13 +++ .../EqmodNStarAlignment.csproj | 88 ++++++++++++++++++ .../Model/AlignmentModel.cs | 42 ++++++--- .../Model/AlignmentModel_EqModVector.cs | 16 ++-- .../Model/AlignmentModel_EqmodAlignment.cs | 4 + .../Model/AlignmentModel_Goto.cs | 62 ++++++++++++ .../Model/AlignmentModel_Math.cs | 50 +++++----- .../Model/AlignmentPoint.cs | 66 +++++++++++-- .../Properties/AssemblyInfo.cs | 36 +++++++ EqmodNStarAlignment/Resources/ASCOM.snk | Bin 0 -> 596 bytes .../Utilities/AstroConvert.cs | 0 .../Utilities/EnumTypeConverter.cs | 0 .../Utilities/Range.cs | 0 .../Utilities/SiderealTime.cs | 0 GS.Server/GS.Server.csproj | 2 +- GS.Server/Properties/launchSettings.json | 2 +- GS.Server/SkyTelescope/SkyServer.cs | 49 +++++++--- GSSolution.sln | 58 ++++-------- 28 files changed, 407 insertions(+), 168 deletions(-) delete mode 100644 EQMODAlignment/EqascomAlignment.csproj delete mode 100644 EQMODAlignment/EqmodNStarAlignment.csproj delete mode 100644 EqmodNStarAlignment.Tests/packages.config rename {EQMODAlignment => EqmodNStarAlignment}/DataTypes/AxisPosition.cs (100%) rename {EQMODAlignment => EqmodNStarAlignment}/DataTypes/EncoderPosition.cs (97%) rename {EQMODAlignment => EqmodNStarAlignment}/DataTypes/EqascomDataTypes.cs (100%) create mode 100644 EqmodNStarAlignment/DataTypes/MapResult.cs create mode 100644 EqmodNStarAlignment/EqmodNStarAlignment.csproj rename {EQMODAlignment => EqmodNStarAlignment}/Model/AlignmentModel.cs (93%) rename {EQMODAlignment => EqmodNStarAlignment}/Model/AlignmentModel_EqModVector.cs (99%) rename {EQMODAlignment => EqmodNStarAlignment}/Model/AlignmentModel_EqmodAlignment.cs (96%) create mode 100644 EqmodNStarAlignment/Model/AlignmentModel_Goto.cs rename {EQMODAlignment => EqmodNStarAlignment}/Model/AlignmentModel_Math.cs (96%) rename {EQMODAlignment => EqmodNStarAlignment}/Model/AlignmentPoint.cs (53%) create mode 100644 EqmodNStarAlignment/Properties/AssemblyInfo.cs create mode 100644 EqmodNStarAlignment/Resources/ASCOM.snk rename {EQMODAlignment => EqmodNStarAlignment}/Utilities/AstroConvert.cs (100%) rename {EQMODAlignment => EqmodNStarAlignment}/Utilities/EnumTypeConverter.cs (100%) rename {EQMODAlignment => EqmodNStarAlignment}/Utilities/Range.cs (100%) rename {EQMODAlignment => EqmodNStarAlignment}/Utilities/SiderealTime.cs (100%) diff --git a/.gitignore b/.gitignore index 3ce1f0d0..79bd6bf2 100644 --- a/.gitignore +++ b/.gitignore @@ -261,3 +261,5 @@ paket-files/ __pycache__/ *.pyc /Resources/Installer/ASCOMGSServer1048Setup.exe +/EQMODAlignment.NetStd20 +/MigrationBackup diff --git a/EQMODAlignment/EqascomAlignment.csproj b/EQMODAlignment/EqascomAlignment.csproj deleted file mode 100644 index 88a55094..00000000 --- a/EQMODAlignment/EqascomAlignment.csproj +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/EQMODAlignment/EqmodNStarAlignment.csproj b/EQMODAlignment/EqmodNStarAlignment.csproj deleted file mode 100644 index 37bf423a..00000000 --- a/EQMODAlignment/EqmodNStarAlignment.csproj +++ /dev/null @@ -1,26 +0,0 @@ - - - - netstandard2.0 - - - - ..\Builds\Debug\ - x86 - - false - - - - - - - - - - - - - - - diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index 46f2827c..b66b8c01 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -54,7 +54,8 @@ public class AlignmentModelTests [TestInitialize] public void Initialize() { - _alignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); + _alignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); + _alignmentModel.StepsPerRev = stepsPerRev; _alignmentModel.SetHomePosition(raHomePos, decHomePos); _alignmentModel.PolarEnable = true; string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); @@ -175,10 +176,10 @@ public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long EncoderPosition test = new EncoderPosition(testRA, testDec); Type type = _alignmentModel.GetType(); MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Reverse_Map", BindingFlags.NonPublic | BindingFlags.Instance); - EncoderPosition result = (EncoderPosition)methodInfo.Invoke(_alignmentModel, new object[] { test }); + MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.RA, 120, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.Dec, 120, "Dec result is incorrect"); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, 120, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, 120, "Dec result is incorrect"); } /* diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj index ebf61ddf..3d20da3c 100644 --- a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj +++ b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj @@ -1,6 +1,5 @@  - Debug @@ -30,6 +29,7 @@ DEBUG;TRACE prompt 4 + x86 pdbonly @@ -40,12 +40,6 @@ 4 - - ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\packages\MSTest.TestFramework.2.1.2\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - @@ -61,27 +55,26 @@ PreserveNewest - - - {b2375ca6-17ae-4875-b33d-b276781cc1da} + + Always + + + + + {2b12e1e9-a2bb-4fa8-9e49-4888b2874233} EqmodNStarAlignment - - Always - + + 3.0.0 + + + 3.0.0 + - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs index e137e57b..595403e0 100644 --- a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs +++ b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs @@ -28,7 +28,8 @@ public class EqmodVectorTests [TestInitialize] public void Initialize() { - AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation, stepsPerRev); + AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); + AlignmentModel.StepsPerRev = stepsPerRev; AlignmentModel.SetHomePosition(raHomePos, decHomePos); AlignmentModel.PolarEnable = true; diff --git a/EqmodNStarAlignment.Tests/packages.config b/EqmodNStarAlignment.Tests/packages.config deleted file mode 100644 index 5230bc10..00000000 --- a/EqmodNStarAlignment.Tests/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file diff --git a/EQMODAlignment/DataTypes/AxisPosition.cs b/EqmodNStarAlignment/DataTypes/AxisPosition.cs similarity index 100% rename from EQMODAlignment/DataTypes/AxisPosition.cs rename to EqmodNStarAlignment/DataTypes/AxisPosition.cs diff --git a/EQMODAlignment/DataTypes/EncoderPosition.cs b/EqmodNStarAlignment/DataTypes/EncoderPosition.cs similarity index 97% rename from EQMODAlignment/DataTypes/EncoderPosition.cs rename to EqmodNStarAlignment/DataTypes/EncoderPosition.cs index 7c3ab22a..586fbc63 100644 --- a/EQMODAlignment/DataTypes/EncoderPosition.cs +++ b/EqmodNStarAlignment/DataTypes/EncoderPosition.cs @@ -54,6 +54,9 @@ public long Dec } + public EncoderPosition(double[] axes) : this((long)Math.Round(axes[0],0), (long)Math.Round(axes[1],0)) + { } + public EncoderPosition(long[] axes) : this(axes[0], axes[1]) { } diff --git a/EQMODAlignment/DataTypes/EqascomDataTypes.cs b/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs similarity index 100% rename from EQMODAlignment/DataTypes/EqascomDataTypes.cs rename to EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs diff --git a/EqmodNStarAlignment/DataTypes/MapResult.cs b/EqmodNStarAlignment/DataTypes/MapResult.cs new file mode 100644 index 00000000..e21fb418 --- /dev/null +++ b/EqmodNStarAlignment/DataTypes/MapResult.cs @@ -0,0 +1,13 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.DataTypes +{ + public class MapResult + { + public EncoderPosition EncoderPosition { get; set;} + + public bool InTriangle { get;set;} = false; + } +} diff --git a/EqmodNStarAlignment/EqmodNStarAlignment.csproj b/EqmodNStarAlignment/EqmodNStarAlignment.csproj new file mode 100644 index 00000000..596d685d --- /dev/null +++ b/EqmodNStarAlignment/EqmodNStarAlignment.csproj @@ -0,0 +1,88 @@ + + + + + Debug + AnyCPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233} + Library + Properties + EqmodNStarAlignment + EqmodNStarAlignment + v4.7.2 + 512 + true + + + + true + full + false + ..\Builds\Debug\ + TRACE + prompt + 4 + 1701;1702 + x86 + ;NU1605 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + true + + + Resources\ASCOM.snk + + + false + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {c2bc2641-3b32-4940-b124-61adec0dac28} + GS.Principles + + + + + 13.0.1 + + + + \ No newline at end of file diff --git a/EQMODAlignment/Model/AlignmentModel.cs b/EqmodNStarAlignment/Model/AlignmentModel.cs similarity index 93% rename from EQMODAlignment/Model/AlignmentModel.cs rename to EqmodNStarAlignment/Model/AlignmentModel.cs index c1d04e22..954dbe17 100644 --- a/EQMODAlignment/Model/AlignmentModel.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel.cs @@ -151,7 +151,7 @@ public double SiteLatitude public double SiteElevation { get; set; } - private bool _polarEnable; + private bool _polarEnable = true; public bool PolarEnable { get => _polarEnable; @@ -165,12 +165,16 @@ public bool PolarEnable public bool CheckLocalPier { get; set; } - public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set;} = ThreePointAlgorithmEnum.BestCentre; + public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set; } = ThreePointAlgorithmEnum.BestCentre; public EncoderPosition HomeEncoder { get; private set; } + private long[] _reportedHomePosition = new long[]{ 0, 0 }; + public void SetHomePosition(long RAEncoder, long decEncoder) { + _reportedHomePosition[0] = RAEncoder; + _reportedHomePosition[1] = decEncoder; // EQMod expects the RA Home position to have a step value of 0x800000 (0 hours) // and the Dec Home position to be 0xA26C80 (90 degrees) @@ -181,16 +185,29 @@ public void SetHomePosition(long RAEncoder, long decEncoder) EncoderMappingOffset = new EncoderPosition(HomeEncoder.RA - RAEncoder, HomeEncoder.Dec - decEncoder); // To convert: Mount = Internal - EncoderMappingOffset // Internal = Mount + EncoderMappingOffset - + SendToMatrix(); } - public EncoderPosition StepsPerRev { get; private set; } + private EncoderPosition _stepsPerRev; + public EncoderPosition StepsPerRev + { + get => _stepsPerRev; + set + { + if (_stepsPerRev == value) + { + return; + } + _stepsPerRev = value; + SetHomePosition(_reportedHomePosition[0], _reportedHomePosition[1]); + } + } public ActivePointsEnum ActivePoints { get; set; } public AlignmentPointCollection AlignmentPoints { get; } = new AlignmentPointCollection(); - public AlignmentPoint SelectedAlignmentPoint {get; private set; } + public AlignmentPoint SelectedAlignmentPoint { get; private set; } public DateTime? LastAccessDateTime { get; private set; } @@ -217,14 +234,18 @@ public void SetHomePosition(long RAEncoder, long decEncoder) #endregion #region Constructor ... - public AlignmentModel(double siteLatitude, double siteLongitude, double siteElevation, EncoderPosition stepsPerRev, bool clearPointsOnStartup = false) + public AlignmentModel(double siteLatitude, double siteLongitude, double siteElevation) { SiteLatitude = siteLatitude; SiteLongitude = siteLongitude; SiteElevation = siteElevation; - StepsPerRev = stepsPerRev; RefreshProximitySteps(); + } + #endregion + + public void Connect(bool clearPointsOnStartup = false) + { try { // Load the last access time property. @@ -242,8 +263,6 @@ public AlignmentModel(double siteLatitude, double siteLongitude, double siteElev LogException(ex, true); } } - #endregion - #region Alignment point management ... public bool SyncToRaDec(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) @@ -329,10 +348,7 @@ public void LoadAlignmentPoints(string filename) AlignmentPoints.Add(alignmentPoint); _oneStarAdjustment = alignmentPoint.Delta; } - if (AlignmentPoints.Count >= 3) - { - SendToMatrix(); // Updates the cartesean values. - } + SendToMatrix(); // Updates the cartesean values. } } catch (Exception ex) diff --git a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs similarity index 99% rename from EQMODAlignment/Model/AlignmentModel_EqModVector.cs rename to EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs index ce1c3301..e83c16e4 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs @@ -349,7 +349,7 @@ public Coord EQ_sp2Cs(EncoderPosition pos) CartesCoord tmpobj = new CartesCoord(); SphericalCoord tmpobj4 = new SphericalCoord(); - if (PolarEnable) + if (PolarEnable) // TODO Why would this ever be false. { tmpobj4 = EQ_SphericalPolar(pos); tmpobj = EQ_Polar2Cartes(tmpobj4); @@ -1405,9 +1405,10 @@ internal List EQ_Choose_3Points(EncoderPosition pos) { foreach (AlignmentPoint pt in this.AlignmentPoints) { + pt.SelectedForGoto = true; results.Add(pt); } - return results; + return results.OrderBy(p => p.AlignTime).ToList(); } Coord posCartesean = EQ_sp2Cs(pos); @@ -1415,6 +1416,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) // first find out the distances to the alignment stars foreach (AlignmentPoint pt in this.AlignmentPoints) { + pt.SelectedForGoto = false; switch (this.ActivePoints) { case ActivePointsEnum.All: @@ -1496,7 +1498,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) } } } - + results.ForEach(p => p.SelectedForGoto = true); return results.OrderBy(p => p.AlignTime).ToList(); } @@ -1518,9 +1520,10 @@ internal List EQ_ChooseNearest3Points(EncoderPosition pos) { foreach (AlignmentPoint pt in this.AlignmentPoints) { + pt.SelectedForGoto = true; results.Add(pt); } - return results; + return results.OrderBy(p => p.AlignTime).ToList(); } Coord posCartesean = EQ_sp2Cs(pos); @@ -1528,6 +1531,7 @@ internal List EQ_ChooseNearest3Points(EncoderPosition pos) // first find out the distances to the alignment stars foreach (AlignmentPoint pt in this.AlignmentPoints) { + pt.SelectedForGoto = false; switch (ActivePoints) { case ActivePointsEnum.All: @@ -1606,8 +1610,8 @@ internal List EQ_ChooseNearest3Points(EncoderPosition pos) } if (done) break; } - - return results; + results.ForEach(p => p.SelectedForGoto = true); + return results.OrderBy(p => p.AlignTime).ToList(); } diff --git a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs similarity index 96% rename from EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs rename to EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs index 48055227..274dae03 100644 --- a/EQMODAlignment/Model/AlignmentModel_EqmodAlignment.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs @@ -47,6 +47,10 @@ public bool EQ_NPointAppend(AlignmentPoint data) } public void SendToMatrix() { + if (AlignmentPoints.Count < 3) + { + return; + } foreach (AlignmentPoint pt in AlignmentPoints) { pt.EncoderCartesian = EQ_sp2Cs(pt.Encoder); diff --git a/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs b/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs new file mode 100644 index 00000000..b6571d26 --- /dev/null +++ b/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs @@ -0,0 +1,62 @@ +using EqmodNStarAlignment.DataTypes; +using System; +using System.Collections.Generic; +using System.Text; + +namespace EqmodNStarAlignment.Model +{ + public partial class AlignmentModel + { + + /// + /// Returns the encoder steps for a given target. + /// Based on code from EQMOD's EncoderTimer.Timer event. + /// + /// + /// + public EncoderPosition GetTargetSteps(EncoderPosition encoder) + { + MapResult result; + EncoderPosition target = encoder; + if (!_threeStarEnabled) + { + SelectedAlignmentPoint = null; + result = Delta_Map(encoder); + target = result.EncoderPosition; + } + else + { + switch (this.ThreePointAlgorithm) + { + case ThreePointAlgorithmEnum.BestCentre: + result = DeltaSync_Matrix_Map(encoder); + break; + case ThreePointAlgorithmEnum.ClosestPoints: + result = Delta_Matrix_Reverse_Map(encoder); + break; + default: + result = Delta_Matrix_Reverse_Map(encoder); + if (!result.InTriangle) + { + result = DeltaSync_Matrix_Map(target); + } + target = result.EncoderPosition; + break; + } + } + return target; + } + + /// + /// Returns the target steps for a given encoder position. + /// + /// + /// + public double[] GetEncoderSteps(double[] targetSteps) + { + return targetSteps; + } + + + } +} diff --git a/EQMODAlignment/Model/AlignmentModel_Math.cs b/EqmodNStarAlignment/Model/AlignmentModel_Math.cs similarity index 96% rename from EQMODAlignment/Model/AlignmentModel_Math.cs rename to EqmodNStarAlignment/Model/AlignmentModel_Math.cs index 9753ef17..a1ec8d86 100644 --- a/EQMODAlignment/Model/AlignmentModel_Math.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_Math.cs @@ -358,7 +358,7 @@ private long Get_EncoderfromDegrees(double degval) private double Get_EncoderDegrees(long encoderPosition) - { + { double pos = encoderPosition * 1.0d;// Convert to double to prevent truncation double decDegrees = 0; @@ -747,20 +747,27 @@ private double Get_EncoderDegrees(long encoderPosition) //} - private double Delta_RA_Map(double raEncoder) + private long Delta_RA_Map(long raEncoder) { return raEncoder + this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) } - private double Delta_DEC_Map(double decEncoder) + private long Delta_DEC_Map(long decEncoder) { return decEncoder + this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) } + private MapResult Delta_Map(EncoderPosition original) + { + return new MapResult() + { + EncoderPosition = new EncoderPosition(Delta_RA_Map(original.RA), Delta_DEC_Map(original.Dec)) + }; + } //private Coordt Delta_Matrix_Map(double RA, double DEC) //{ @@ -794,29 +801,24 @@ private double Delta_DEC_Map(double decEncoder) //} - private EncoderPosition Delta_Matrix_Reverse_Map(EncoderPosition pos) + private MapResult Delta_Matrix_Reverse_Map(EncoderPosition pos) { - EncoderPosition result = new EncoderPosition(); + MapResult result = new MapResult(); if ((pos.RA >= 0x1000000) || (pos.Dec >= 0x1000000)) { - result.RA = pos.RA; - result.Dec = pos.Dec; - //result.z = 1; - //result.f = 0; + result.EncoderPosition = new EncoderPosition(pos.RA, pos.Dec); return result; } // re transform using the 3 nearest stars - _=EQ_UpdateAffine(pos); + bool inTriangle = EQ_UpdateAffine(pos); EncoderPosition obtmp2 = EQ_plAffine(pos); - result.RA = obtmp2.RA; - result.Dec = obtmp2.Dec; - //result.z = 1; - //result.f = (short)i; + result.EncoderPosition = new EncoderPosition(obtmp2.RA, obtmp2.Dec); + result.InTriangle = inTriangle; return result; @@ -827,31 +829,29 @@ private EncoderPosition Delta_Matrix_Reverse_Map(EncoderPosition pos) /// /// /// - private EncoderPosition DeltaSync_Matrix_Map(EncoderPosition encoderPosition) + private MapResult DeltaSync_Matrix_Map(EncoderPosition encoderPosition) { - EncoderPosition result = new EncoderPosition(); + MapResult result = new MapResult(); if ((encoderPosition.RA >= 0x1000000) || (encoderPosition.Dec >= 0x1000000)) { - result.RA = encoderPosition.RA; - result.Dec = encoderPosition.Dec; - // result.z = 0; - // result.f = 0; + result.EncoderPosition = encoderPosition; } else { this.SelectedAlignmentPoint = GetNearest(encoderPosition); if (this.SelectedAlignmentPoint != null) { - result.RA = encoderPosition.RA + (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA); // + gRASync01; - result.Dec = encoderPosition.Dec + (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec); // + gDecSync01; + result.EncoderPosition = new EncoderPosition( + encoderPosition.RA + (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA), // + gRASync01; + encoderPosition.Dec + (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec) + ); // + gDecSync01; // result.z = 1; // result.f = 0; } else { - result.RA = encoderPosition.RA; - result.Dec = encoderPosition.Dec; + result.EncoderPosition = encoderPosition; // result.z = 0; // result.f = 0; } @@ -894,7 +894,7 @@ private EncoderPosition DeltaSync_Matrix_Map(EncoderPosition encoderPosition) // } // return result; //} - + //TODO: Improve GetQuadrant to return an Enum value (NW, NE, SW or SE) instead of an int. /// diff --git a/EQMODAlignment/Model/AlignmentPoint.cs b/EqmodNStarAlignment/Model/AlignmentPoint.cs similarity index 53% rename from EQMODAlignment/Model/AlignmentPoint.cs rename to EqmodNStarAlignment/Model/AlignmentPoint.cs index f39b3a21..dba7304b 100644 --- a/EQMODAlignment/Model/AlignmentPoint.cs +++ b/EqmodNStarAlignment/Model/AlignmentPoint.cs @@ -3,12 +3,14 @@ using System; using System.Collections.Generic; using System.Collections.ObjectModel; +using System.ComponentModel; using System.Linq; +using System.Runtime.CompilerServices; using System.Text; namespace EqmodNStarAlignment.Model { - public class AlignmentPoint + public class AlignmentPoint : INotifyPropertyChanged { /// /// Unique ID for alignment point @@ -18,38 +20,77 @@ public class AlignmentPoint /// /// Alignment date and time of the sync /// - public DateTime AlignTime { get;set;} + public DateTime AlignTime { get; set; } /// /// The Encoder positions at sync time /// - public EncoderPosition Encoder { get;set;} + public EncoderPosition Encoder { get; set; } /// /// The Cartesian equivalent of the EncoderPosition /// - public Coord EncoderCartesian { get; set;} + public Coord EncoderCartesian { get; set; } /// /// The Target Ra/Dec in hours/degrees /// - public AxisPosition OrigRaDec { get;set;} + public AxisPosition OrigRaDec { get; set; } /// /// The unadjusted encoder positions /// - public EncoderPosition Target { get;set;} + public EncoderPosition Target { get; set; } /// /// The cartesean version of the unadjusted encoder positions /// - public Coord TargetCartesian { get; set;} + public Coord TargetCartesian { get; set; } [JsonIgnore] public EncoderPosition Delta => (Target - Encoder); + + [JsonIgnore] + public string Synched => $"{AlignTime:G}"; + + private bool _selected; + + /// + /// Selected for correcting display + /// + [JsonIgnore] + public bool Selected + { + get => _selected; + set + { + if (value == _selected) return; + _selected = value; + OnPropertyChanged(); + } + } + + private bool _selectedForGoto; + + /// + /// Selected for slew/goto calculation + /// + [JsonIgnore] + public bool SelectedForGoto + { + get => _selectedForGoto; + set + { + if (value == _selectedForGoto) return; + _selectedForGoto = value; + OnPropertyChanged(); + } + } + + public AlignmentPoint() { @@ -63,6 +104,15 @@ public AlignmentPoint(long[] encoder, double[] origRaDec, long[] target, DateTim AlignTime = syncTime; } + #region INotifyPropertyChanged interface ... + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + #endregion + } public class AlignmentPointCollection : ObservableCollection @@ -85,4 +135,6 @@ protected override void InsertItem(int index, AlignmentPoint item) } + + } diff --git a/EqmodNStarAlignment/Properties/AssemblyInfo.cs b/EqmodNStarAlignment/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..cd38b6a1 --- /dev/null +++ b/EqmodNStarAlignment/Properties/AssemblyInfo.cs @@ -0,0 +1,36 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("EqmodNStarAlignment")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("EqmodNStarAlignment")] +[assembly: AssemblyCopyright("Copyright © 2022")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] + +// Setting ComVisible to false makes the types in this assembly not visible +// to COM components. If you need to access a type in this assembly from +// COM, set the ComVisible attribute to true on that type. +[assembly: ComVisible(false)] + +// The following GUID is for the ID of the typelib if this project is exposed to COM +[assembly: Guid("2b12e1e9-a2bb-4fa8-9e49-4888b2874233")] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/EqmodNStarAlignment/Resources/ASCOM.snk b/EqmodNStarAlignment/Resources/ASCOM.snk new file mode 100644 index 0000000000000000000000000000000000000000..5b911b2dd45ff55f837f84759f53f5684dbae07d GIT binary patch literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa500986qTcbIbGIsd@kxk`lk9?xw_Z(18(d{7 zq%;?&c8SiBQH4C=0(itr|4OA^o4OCb;U~R zn@*akkTPyBlA4(cTw%6(RzpMoAyj?|ZLz5iP(hp$!;oYah9?09Vh>UMeU$H1zV7JN zNKHfH*e=}%t5noW{9Y56(0dtniA@C{okBzV#FovIIT9fiPC!oU+!<#VNXI-Lq7;@W zkvbyA`Qj1TcB1`rzmP#0CKrlWIY_O?=rna3DoT?rlsK=2;65r?>95VAa6lM#$Np5N z5bd5^vHVrAjbf-nfGJ#7UxNw3+8XQSg{d|+hJEG5y;|mnlkXw)93|`l{vh5q9PenAhY4?(uF;IQ8d93Xi#Y*be_?|ovHm^m2^0bBmK@g8(s$y^? zx7YiBvQ8?2`4Wceb0XE}sR<_6S(LibU;|fyvFDfjYOYzAM2Ge>n(R%2g#0}Fc6AXB4FC9Gq literal 0 HcmV?d00001 diff --git a/EQMODAlignment/Utilities/AstroConvert.cs b/EqmodNStarAlignment/Utilities/AstroConvert.cs similarity index 100% rename from EQMODAlignment/Utilities/AstroConvert.cs rename to EqmodNStarAlignment/Utilities/AstroConvert.cs diff --git a/EQMODAlignment/Utilities/EnumTypeConverter.cs b/EqmodNStarAlignment/Utilities/EnumTypeConverter.cs similarity index 100% rename from EQMODAlignment/Utilities/EnumTypeConverter.cs rename to EqmodNStarAlignment/Utilities/EnumTypeConverter.cs diff --git a/EQMODAlignment/Utilities/Range.cs b/EqmodNStarAlignment/Utilities/Range.cs similarity index 100% rename from EQMODAlignment/Utilities/Range.cs rename to EqmodNStarAlignment/Utilities/Range.cs diff --git a/EQMODAlignment/Utilities/SiderealTime.cs b/EqmodNStarAlignment/Utilities/SiderealTime.cs similarity index 100% rename from EQMODAlignment/Utilities/SiderealTime.cs rename to EqmodNStarAlignment/Utilities/SiderealTime.cs diff --git a/GS.Server/GS.Server.csproj b/GS.Server/GS.Server.csproj index c8bc8239..fecfbb1e 100644 --- a/GS.Server/GS.Server.csproj +++ b/GS.Server/GS.Server.csproj @@ -77,7 +77,7 @@ false - + false diff --git a/GS.Server/Properties/launchSettings.json b/GS.Server/Properties/launchSettings.json index d01fe7ab..2723f85a 100644 --- a/GS.Server/Properties/launchSettings.json +++ b/GS.Server/Properties/launchSettings.json @@ -2,7 +2,7 @@ "profiles": { "GS.Server": { "commandName": "Project", - "commandLineArgs": "/pec /showalignment" + "commandLineArgs": "/showalignment" } } } \ No newline at end of file diff --git a/GS.Server/SkyTelescope/SkyServer.cs b/GS.Server/SkyTelescope/SkyServer.cs index 075d30a4..afc6753e 100644 --- a/GS.Server/SkyTelescope/SkyServer.cs +++ b/GS.Server/SkyTelescope/SkyServer.cs @@ -40,6 +40,7 @@ You should have received a copy of the GNU General Public License using GS.Server.Alignment; using AxisStatus = GS.Simulator.AxisStatus; using Range = GS.Principles.Range; +using EqmodNStarAlignment.DataTypes; namespace GS.Server.SkyTelescope { @@ -118,13 +119,11 @@ static SkyServer() AlignmentModel = new AlignmentModel( SkySettings.Latitude, SkySettings.Longitude, - SkySettings.Elevation, - new EqmodNStarAlignment.DataTypes.EncoderPosition(SkyServer.StepsPerRevolution[0], SkyServer.StepsPerRevolution[1]), - AlignmentSettings.ClearModelOnStartup) + SkySettings.Elevation) { - IsAlignmentOn = (AlignmentShow && AlignmentSettings.IsAlignmentOn) + IsAlignmentOn = (AlignmentShow && AlignmentSettings.IsAlignmentOn), + ThreePointAlgorithm = ThreePointAlgorithmEnum.BestCentre }; - AlignmentModel.SetHomePosition(0, 0); AlignmentModel.Notification += AlignmentModel_Notification; // attach handler to watch for SkySettings changing. @@ -2867,6 +2866,7 @@ private static double[] GetRawSteps() case MountType.SkyWatcher: var skySteps = new SkyGetSteps(SkyQueue.NewId); steps = (double[])SkyQueue.GetCommandResult(skySteps).Result; + return CheckSkyErrors(skySteps) ? new[] { double.NaN, double.NaN } : steps; default: throw new ArgumentOutOfRangeException(); @@ -3656,6 +3656,8 @@ private static bool MountConnect() positionsSet = true; } + // Update AlignmentModel settings. + ConnectAlignmentModel(); break; case MountType.SkyWatcher: @@ -3761,6 +3763,9 @@ private static bool MountConnect() } + // Update AlignmentModel settings. + ConnectAlignmentModel(); + break; default: throw new ArgumentOutOfRangeException(); @@ -4695,6 +4700,13 @@ public static bool CheckAltAzSyncLimit(double alt, double az) #region Alignment + private static void ConnectAlignmentModel() + { + AlignmentModel.StepsPerRev = new EqmodNStarAlignment.DataTypes.EncoderPosition(SkyServer.StepsPerRevolution[0], SkyServer.StepsPerRevolution[1]); + AlignmentModel.SetHomePosition(0, 0); + AlignmentModel.Connect(AlignmentSettings.ClearModelOnStartup); + } + private static bool _alignmentShow; /// /// sets up bool to load a test tab @@ -4739,16 +4751,14 @@ private static void AddAlignmentPoint() // To get the target steps var xy = Axes.RaDecToAxesXY(new[] { TargetRa, TargetDec }); var targ = Axes.AxesAppToMount(new[] { xy[0], xy[1] }); - var targetSteps = new[] { - (long)Math.Floor(DegToRad(targ[0]) + SkyServer.FactorStep[0]), - (long)Math.Floor(DegToRad(targ[1]) + SkyServer.FactorStep[1])}; - - - + var raCmd = new SkyGetAngleToStep(SkyQueue.NewId, AxisId.Axis1, DegToRad(targ[0])); + var decCmd = new SkyGetAngleToStep(SkyQueue.NewId, AxisId.Axis2, DegToRad(targ[1])); + long targetRaSteps = Convert.ToInt64(SkyQueue.GetCommandResult(raCmd).Result); + long targetDecSteps = Convert.ToInt64(SkyQueue.GetCommandResult(decCmd).Result); if (AlignmentModel.SyncToRaDec( new long[] { (long)SkyServer.Steps[0], (long)SkyServer.Steps[0] }, new double[] { TargetRa, TargetDec }, - targetSteps, + new long[] {targetRaSteps, targetDecSteps }, DateTime.Now)) { var monitorItem = new MonitorEntry @@ -4759,7 +4769,7 @@ private static void AddAlignmentPoint() Type = MonitorType.Information, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, - Message = $"Alignment point added: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetSteps[0]}/{targetSteps[1]}" + Message = $"Alignment point added: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetRaSteps}/{targetDecSteps}" }; MonitorLog.LogToMonitor(monitorItem); } @@ -4773,7 +4783,7 @@ private static void AddAlignmentPoint() Type = MonitorType.Error, Method = MethodBase.GetCurrentMethod()?.Name, Thread = Thread.CurrentThread.ManagedThreadId, - Message = $"Alignment point rejected: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetSteps[0]}/{targetSteps[1]}" + Message = $"Alignment point rejected: Mount axis = {SkyServer.Steps[0]}/{SkyServer.Steps[1]}, RA/Dec = {TargetRa}/{TargetDec}, Target axis = {targetRaSteps}/{targetDecSteps}" }; MonitorLog.LogToMonitor(monitorItem); } @@ -5003,8 +5013,17 @@ private static void UpdateServerEvent(object sender, EventArgs e) if (rawSteps == null) { return; } if (double.IsNaN(rawSteps[0]) || double.IsNaN(rawSteps[1])) { return; } + // store actual steps - Steps = rawSteps; + //if (AlignmentModel.IsAlignmentOn) + //{ + // EncoderPosition target = AlignmentModel.GetTargetSteps(new EncoderPosition(rawSteps)); + // Steps = new double[]{target[0], target[1] }; + //} + //else + //{ + Steps = rawSteps; + //} //Implement Pec PecCheck(); diff --git a/GSSolution.sln b/GSSolution.sln index 78be6ac7..bd343977 100644 --- a/GSSolution.sln +++ b/GSSolution.sln @@ -37,13 +37,11 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "XInputDotNetPure", "XInputD {1967D61A-FB64-463C-BB3C-BB6E90FBC76F} = {1967D61A-FB64-463C-BB3C-BB6E90FBC76F} EndProjectSection EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "NStarAlignment", "NStarAlignment\NStarAlignment.csproj", "{1D17F8BA-F10F-493E-A7B5-941510A59679}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "GS.FitsImageManager", "GS.FitsImageManager\GS.FitsImageManager.csproj", "{74B0434D-F37A-4B53-967C-85881529D45C}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NINA", "NINA\NINA.csproj", "{6770B884-0C92-4615-BE0D-7FBE55D2D0EE}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EqmodNStarAlignment", "EQMODAlignment\EqmodNStarAlignment.csproj", "{B2375CA6-17AE-4875-B33D-B276781CC1DA}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment", "EqmodNStarAlignment\EqmodNStarAlignment.csproj", "{2B12E1E9-A2BB-4FA8-9E49-4888B2874233}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment.Tests", "EqmodNStarAlignment.Tests\EqmodNStarAlignment.Tests.csproj", "{A546006B-D866-41B9-B378-F0666F18618C}" EndProject @@ -276,24 +274,6 @@ Global {952700CD-A384-43A4-AC4B-52256F83836E}.Release|x64.Build.0 = Release|x64 {952700CD-A384-43A4-AC4B-52256F83836E}.Release|x86.ActiveCfg = Release|x86 {952700CD-A384-43A4-AC4B-52256F83836E}.Release|x86.Build.0 = Release|x86 - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|x64.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|x64.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|x86.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.AppVeyor|x86.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|x64.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|x64.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|x86.ActiveCfg = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Debug|x86.Build.0 = Debug|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|Any CPU.ActiveCfg = Release|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|Any CPU.Build.0 = Release|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|x64.ActiveCfg = Release|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|x64.Build.0 = Release|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|x86.ActiveCfg = Release|Any CPU - {1D17F8BA-F10F-493E-A7B5-941510A59679}.Release|x86.Build.0 = Release|Any CPU {74B0434D-F37A-4B53-967C-85881529D45C}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU {74B0434D-F37A-4B53-967C-85881529D45C}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU {74B0434D-F37A-4B53-967C-85881529D45C}.AppVeyor|x64.ActiveCfg = Debug|Any CPU @@ -330,24 +310,24 @@ Global {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x64.Build.0 = Release|Any CPU {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x86.ActiveCfg = Release|Any CPU {6770B884-0C92-4615-BE0D-7FBE55D2D0EE}.Release|x86.Build.0 = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x64.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x64.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x86.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.AppVeyor|x86.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x64.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x64.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x86.ActiveCfg = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Debug|x86.Build.0 = Debug|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|Any CPU.Build.0 = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x64.ActiveCfg = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x64.Build.0 = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x86.ActiveCfg = Release|Any CPU - {B2375CA6-17AE-4875-B33D-B276781CC1DA}.Release|x86.Build.0 = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|x64.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|x64.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|x86.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.AppVeyor|x86.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|Any CPU.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|x64.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|x64.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|x86.ActiveCfg = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Debug|x86.Build.0 = Debug|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|Any CPU.ActiveCfg = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|Any CPU.Build.0 = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x64.ActiveCfg = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x64.Build.0 = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x86.ActiveCfg = Release|Any CPU + {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x86.Build.0 = Release|Any CPU {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x64.ActiveCfg = Debug|Any CPU From 03b403386267e66a21a873873c7454732f1a06ce Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Thu, 15 Dec 2022 16:54:51 +0000 Subject: [PATCH 07/18] Fixed Test project. --- .gitignore | 1 + .../EqmodNStarAlignment.Tests.csproj | 27 ++- .../Properties/AssemblyInfo.cs | 6 +- GSSolution.sln | 38 ++-- .../NStarAlignment/NStarAlignment.csproj | 88 ---------- .../NStarAlignment/NuGetUpgradeLog.html | 162 ------------------ .../67336608/NStarAlignment/packages.config | 4 - MigrationBackup/ec178c51/NINA/NINA.csproj | 92 ---------- .../ec178c51/NINA/NuGetUpgradeLog.html | 162 ------------------ MigrationBackup/ec178c51/NINA/packages.config | 4 - 10 files changed, 36 insertions(+), 548 deletions(-) delete mode 100644 MigrationBackup/67336608/NStarAlignment/NStarAlignment.csproj delete mode 100644 MigrationBackup/67336608/NStarAlignment/NuGetUpgradeLog.html delete mode 100644 MigrationBackup/67336608/NStarAlignment/packages.config delete mode 100644 MigrationBackup/ec178c51/NINA/NINA.csproj delete mode 100644 MigrationBackup/ec178c51/NINA/NuGetUpgradeLog.html delete mode 100644 MigrationBackup/ec178c51/NINA/packages.config diff --git a/.gitignore b/.gitignore index 79bd6bf2..caeb2b67 100644 --- a/.gitignore +++ b/.gitignore @@ -263,3 +263,4 @@ __pycache__/ /Resources/Installer/ASCOMGSServer1048Setup.exe /EQMODAlignment.NetStd20 /MigrationBackup +/~EqmodNStarAlignment.Tests diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj index 3d20da3c..2e8232ff 100644 --- a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj +++ b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj @@ -4,7 +4,7 @@ Debug AnyCPU - {A546006B-D866-41B9-B378-F0666F18618C} + {55FBCFCA-0220-43E2-82D0-DD9253A1D254} Library Properties EqmodNStarAlignment.Tests @@ -19,13 +19,12 @@ UnitTest - true full false - bin\Debug\ + ..\Builds\Debug\ DEBUG;TRACE prompt 4 @@ -44,35 +43,35 @@ - - - - + + + + PreserveNewest - - - Always - - {2b12e1e9-a2bb-4fa8-9e49-4888b2874233} EqmodNStarAlignment + + + PreserveNewest + + - 3.0.0 + 2.1.2 - 3.0.0 + 2.1.2 diff --git a/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs b/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs index 3278a883..6f214630 100644 --- a/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs +++ b/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs @@ -2,18 +2,18 @@ using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -[assembly: AssemblyTitle("EqmodNStarAlignment.Tests")] +[assembly: AssemblyTitle("EqmocNStarAlignment.Tests")] [assembly: AssemblyDescription("")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("EqmodNStarAlignment.Tests")] +[assembly: AssemblyProduct("EqmocNStarAlignment.Tests")] [assembly: AssemblyCopyright("Copyright © 2022")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] [assembly: ComVisible(false)] -[assembly: Guid("a546006b-d866-41b9-b378-f0666f18618c")] +[assembly: Guid("55fbcfca-0220-43e2-82d0-dd9253a1d254")] // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("1.0.0.0")] diff --git a/GSSolution.sln b/GSSolution.sln index bd343977..775d2c52 100644 --- a/GSSolution.sln +++ b/GSSolution.sln @@ -43,7 +43,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NINA", "NINA\NINA.csproj", EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment", "EqmodNStarAlignment\EqmodNStarAlignment.csproj", "{2B12E1E9-A2BB-4FA8-9E49-4888B2874233}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment.Tests", "EqmodNStarAlignment.Tests\EqmodNStarAlignment.Tests.csproj", "{A546006B-D866-41B9-B378-F0666F18618C}" +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EqmodNStarAlignment.Tests", "EqmodNStarAlignment.Tests\EqmodNStarAlignment.Tests.csproj", "{55FBCFCA-0220-43E2-82D0-DD9253A1D254}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution @@ -328,24 +328,24 @@ Global {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x64.Build.0 = Release|Any CPU {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x86.ActiveCfg = Release|Any CPU {2B12E1E9-A2BB-4FA8-9E49-4888B2874233}.Release|x86.Build.0 = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x64.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x64.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x86.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.AppVeyor|x86.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x64.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x64.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x86.ActiveCfg = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Debug|x86.Build.0 = Debug|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|Any CPU.Build.0 = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|x64.ActiveCfg = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|x64.Build.0 = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|x86.ActiveCfg = Release|Any CPU - {A546006B-D866-41B9-B378-F0666F18618C}.Release|x86.Build.0 = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|Any CPU.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|Any CPU.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|x64.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|x64.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|x86.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.AppVeyor|x86.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|Any CPU.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|x64.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|x64.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|x86.ActiveCfg = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Debug|x86.Build.0 = Debug|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|Any CPU.ActiveCfg = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|Any CPU.Build.0 = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|x64.ActiveCfg = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|x64.Build.0 = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|x86.ActiveCfg = Release|Any CPU + {55FBCFCA-0220-43E2-82D0-DD9253A1D254}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/MigrationBackup/67336608/NStarAlignment/NStarAlignment.csproj b/MigrationBackup/67336608/NStarAlignment/NStarAlignment.csproj deleted file mode 100644 index b25562b3..00000000 --- a/MigrationBackup/67336608/NStarAlignment/NStarAlignment.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - AnyCPU - {1D17F8BA-F10F-493E-A7B5-941510A59679} - Library - Properties - NStarAlignment - NStarAlignment - v4.7.2 - 512 - true - - - - true - portable - false - ..\Builds\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - pdbonly - true - ..\Builds\Release\ - TRACE - prompt - 4 - - - true - - - true - - - Resources\ASCOM.snk - - - false - - - - ..\packages\Newtonsoft.Json.12.0.3\lib\net45\Newtonsoft.Json.dll - - - - - - - - - - - - - - - - - - - - True - True - Resources.resx - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - - - - - - \ No newline at end of file diff --git a/MigrationBackup/67336608/NStarAlignment/NuGetUpgradeLog.html b/MigrationBackup/67336608/NStarAlignment/NuGetUpgradeLog.html deleted file mode 100644 index b8015a6b..00000000 --- a/MigrationBackup/67336608/NStarAlignment/NuGetUpgradeLog.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - NuGetMigrationLog -

- NuGet Migration Report - NStarAlignment

Overview

Migration to PackageReference was completed successfully. Please build and run your solution to verify that all packages are available.
- If you run into any problems, have feedback, questions, or concerns, please - file an issue on the NuGet GitHub repository.
- Changed files and this report have been backed up here: - C:\Users\phil\source\repos\GSServer\MigrationBackup\67336608\NStarAlignment

Packages processed

Top-level dependencies:

Package IdVersion
Newtonsoft.Json - v12.0.3

Transitive dependencies:

Package IdVersion
- No transitive dependencies found. -

Package compatibility issues

Description
- No issues were found. -
\ No newline at end of file diff --git a/MigrationBackup/67336608/NStarAlignment/packages.config b/MigrationBackup/67336608/NStarAlignment/packages.config deleted file mode 100644 index ce3dc383..00000000 --- a/MigrationBackup/67336608/NStarAlignment/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/MigrationBackup/ec178c51/NINA/NINA.csproj b/MigrationBackup/ec178c51/NINA/NINA.csproj deleted file mode 100644 index 7bd28110..00000000 --- a/MigrationBackup/ec178c51/NINA/NINA.csproj +++ /dev/null @@ -1,92 +0,0 @@ - - - - - Debug - AnyCPU - {6770B884-0C92-4615-BE0D-7FBE55D2D0EE} - Library - Properties - NINA - NINA - v4.7.1 - 512 - true - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Astrometry.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Attributes.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Cache.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Controls.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.DeviceInterfaces.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.DriverAccess.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Exceptions.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Internal.Extensions.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.SettingsProvider.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Utilities.dll - - - ..\packages\ASCOM.Platform.6.5.0\lib\net40\ASCOM.Utilities.Video.dll - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/MigrationBackup/ec178c51/NINA/NuGetUpgradeLog.html b/MigrationBackup/ec178c51/NINA/NuGetUpgradeLog.html deleted file mode 100644 index 2f2935dc..00000000 --- a/MigrationBackup/ec178c51/NINA/NuGetUpgradeLog.html +++ /dev/null @@ -1,162 +0,0 @@ - - - - - NuGetMigrationLog -

- NuGet Migration Report - NINA

Overview

Migration to PackageReference was completed successfully. Please build and run your solution to verify that all packages are available.
- If you run into any problems, have feedback, questions, or concerns, please - file an issue on the NuGet GitHub repository.
- Changed files and this report have been backed up here: - C:\Users\phil\source\repos\GSServer\MigrationBackup\ec178c51\NINA

Packages processed

Top-level dependencies:

Package IdVersion
ASCOM.Platform - v6.5.0

Transitive dependencies:

Package IdVersion
- No transitive dependencies found. -

Package compatibility issues

Description
- No issues were found. -
\ No newline at end of file diff --git a/MigrationBackup/ec178c51/NINA/packages.config b/MigrationBackup/ec178c51/NINA/packages.config deleted file mode 100644 index 0d317169..00000000 --- a/MigrationBackup/ec178c51/NINA/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file From 26c2c6c8b7415ca4a65dad289af8ba6f00c0eaae Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Fri, 16 Dec 2022 12:13:01 +0000 Subject: [PATCH 08/18] Expanded alignment code to include Taki transformations and goto target mapping. --- .../AlignmentModelTests.cs | 5 +- EqmodNStarAlignment.Tests/EqmodVectorTests.cs | 1 - .../DataTypes/EqascomDataTypes.cs | 18 +- EqmodNStarAlignment/Model/AlignmentModel.cs | 24 +- .../Model/AlignmentModel_EqModVector.cs | 210 ++++++++---------- .../Model/AlignmentModel_Goto.cs | 48 ++-- .../Model/AlignmentModel_Math.cs | 123 +++++----- GS.Server/SkyTelescope/SkyServer.cs | 62 +++++- 8 files changed, 266 insertions(+), 225 deletions(-) diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index b66b8c01..eb147099 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -57,7 +57,6 @@ public void Initialize() _alignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); _alignmentModel.StepsPerRev = stepsPerRev; _alignmentModel.SetHomePosition(raHomePos, decHomePos); - _alignmentModel.PolarEnable = true; string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); _alignmentModel.LoadAlignmentPoints(inputFile); @@ -259,8 +258,8 @@ public void Test_EQ_Cartes2Polar(double expectedX, double expectedY, double expe _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; _alignmentModel.ActivePoints = ActivePointsEnum.All; - CartesCoord test = new CartesCoord(testX, testY, 0d, 0d); - CartesCoord rads = new CartesCoord(0d, 0d, testR, testRa); + CartesCoord test = new CartesCoord(testX, testY, 0d, 0d, 0d); + CartesCoord rads = new CartesCoord(0d, 0d, 0d, testR, testRa); Type type = _alignmentModel.GetType(); MethodInfo methodInfo = type.GetMethod("EQ_Cartes2Polar", BindingFlags.NonPublic | BindingFlags.Instance); SphericalCoord result = (SphericalCoord)methodInfo.Invoke(_alignmentModel, new object[] { test, rads }); diff --git a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs index 595403e0..ca75e9f8 100644 --- a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs +++ b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs @@ -31,7 +31,6 @@ public void Initialize() AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); AlignmentModel.StepsPerRev = stepsPerRev; AlignmentModel.SetHomePosition(raHomePos, decHomePos); - AlignmentModel.PolarEnable = true; } diff --git a/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs b/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs index 0db167b2..72be9563 100644 --- a/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs +++ b/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs @@ -94,25 +94,27 @@ public static Matrix CreateInstance() // } //} - public struct Coordt - { - public double x; //x = X Coordinate - public double y; //y = Y Coordinate - public double z; - public short f; - } + //public struct Coordt + //{ + // public double x; //x = X Coordinate + // public double y; //y = Y Coordinate + // public double z; + // public short f; + //} public struct CartesCoord { public double x; //x = X Coordinate public double y; //y = Y Coordinate + public double z; //z = Z coordinate public double r; // Radius Sign public double ra; // Radius Alpha - public CartesCoord(double xValue, double yValue, double rValue, double raValue) + public CartesCoord(double xValue, double yValue, double zValue, double rValue, double raValue) { x = xValue; y = yValue; + z = zValue; r = rValue; ra = raValue; } diff --git a/EqmodNStarAlignment/Model/AlignmentModel.cs b/EqmodNStarAlignment/Model/AlignmentModel.cs index 954dbe17..d9355d2a 100644 --- a/EqmodNStarAlignment/Model/AlignmentModel.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel.cs @@ -51,6 +51,16 @@ public enum ThreePointAlgorithmEnum ClosestPoints } + [TypeConverter(typeof(EnumTypeConverter))] + public enum AlignmentModeEnum + { + [Description("N-Star + Nearest")] + NStarPlusNearest, + [Description("Nearest")] + Nearest + } + + public enum HemisphereEnum { Northern, @@ -151,20 +161,10 @@ public double SiteLatitude public double SiteElevation { get; set; } - private bool _polarEnable = true; - public bool PolarEnable - { - get => _polarEnable; - set - { - if (_polarEnable == value) return; - _polarEnable = value; - SendToMatrix(); - } - } - public bool CheckLocalPier { get; set; } + public AlignmentModeEnum AlignmentMode { get; set; } = AlignmentModeEnum.NStarPlusNearest; + public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set; } = ThreePointAlgorithmEnum.BestCentre; public EncoderPosition HomeEncoder { get; private set; } diff --git a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs index e83c16e4..1a3ffd1b 100644 --- a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs @@ -256,24 +256,32 @@ private bool EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coor } - ////Function to transform the Coordinates (Taki Method) using the MT Matrix and Offset Vector - - //private Coord EQ_Transform_Taki(Coord ob) - //{ - - // // CoordTransform = Offset + CoordObject * Matrix MT - - // Coord result = new Coord(); - // result.x = EQCT.x + ((ob.x * EQMT.Element[0, 0]) + (ob.y * EQMT.Element[1, 0]) + (ob.z * EQMT.Element[2, 0])); - // result.y = EQCT.y + ((ob.x * EQMT.Element[0, 1]) + (ob.y * EQMT.Element[1, 1]) + (ob.z * EQMT.Element[2, 1])); - // result.z = EQCT.z + ((ob.x * EQMT.Element[0, 2]) + (ob.y * EQMT.Element[1, 2]) + (ob.z * EQMT.Element[2, 2])); - - - // return result; - //} - - // Subroutine to draw the Transformation Matrix (Affine Mapping Method) + /// + /// Function to transform the Coordinates (Taki Method) using the MT Matrix and Offset Vector + /// + /// + /// + private CartesCoord EQ_Transform_Taki(CartesCoord pos) + { + CartesCoord result = new CartesCoord(); + result.x = EQCT.x + ((pos.x * EQMT.Element[0, 0]) + (pos.y * EQMT.Element[1, 0]) + (pos.z * EQMT.Element[2, 0])); + result.y = EQCT.y + ((pos.x * EQMT.Element[0, 1]) + (pos.y * EQMT.Element[1, 1]) + (pos.z * EQMT.Element[2, 1])); + result.z = EQCT.z + ((pos.x * EQMT.Element[0, 2]) + (pos.y * EQMT.Element[1, 2]) + (pos.z * EQMT.Element[2, 2])); + return result; + } + /// + /// Subroutine to draw the Transformation Matrix (Affine Mapping Method) + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// private bool EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) { @@ -349,20 +357,11 @@ public Coord EQ_sp2Cs(EncoderPosition pos) CartesCoord tmpobj = new CartesCoord(); SphericalCoord tmpobj4 = new SphericalCoord(); - if (PolarEnable) // TODO Why would this ever be false. - { - tmpobj4 = EQ_SphericalPolar(pos); - tmpobj = EQ_Polar2Cartes(tmpobj4); - result.x = tmpobj.x; - result.y = tmpobj.y; - result.z = 1; - } - else - { - result.x = pos.RA; - result.y = pos.Dec; - result.z = 1; - } + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj = EQ_Polar2Cartes(tmpobj4); + result.x = tmpobj.x; + result.y = tmpobj.y; + result.z = 1; return result; } @@ -448,24 +447,13 @@ internal EncoderPosition EQ_plAffine(EncoderPosition pos) SphericalCoord tmpobj2 = new SphericalCoord(); SphericalCoord tmpobj4 = new SphericalCoord(); - if (PolarEnable) - { - tmpobj4 = EQ_SphericalPolar(pos); - tmpobj1 = EQ_Polar2Cartes(tmpobj4); - tmpobj3 = EQ_Transform_Affine(tmpobj1); - tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj1 = EQ_Polar2Cartes(tmpobj4); - result = EQ_PolarSpherical(tmpobj2, tmpobj4); - - } - else - { - tmpobj3 = EQ_Transform_Affine(new CartesCoord() { x = pos.RA, y = pos.Dec }); - result.RA = (long)Math.Round(tmpobj3.x, 0); - result.Dec = (long)Math.Round(tmpobj3.y, 0); - // result.z = 1; - } + tmpobj3 = EQ_Transform_Affine(tmpobj1); + tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); + result = EQ_PolarSpherical(tmpobj2, tmpobj4); return result; } @@ -512,50 +500,34 @@ internal EncoderPosition EQ_plAffine(EncoderPosition pos) // return result; //} - ////Implement a TAKI transformation on a Polar coordinate system - ////This is done by converting the Polar Data to Cartesian, Apply TAKI transformation - ////Then restore the transformed Cartesian Coordinates back to polar - //internal Coord EQ_plTaki(Coord obj) - //{ - // Coord result = new Coord(); - // double gDECEncoder_Home_pos = 0; - // double gLatitude = 0; - // double gTot_step = 0; - // object HC = null; - // double RAEncoder_Home_pos = 0; - // CartesCoord tmpobj1 = new CartesCoord(); - // Coord tmpobj2 = new Coord(); - // Coord tmpobj3 = new Coord(); - // SphericalCoord tmpobj4 = new SphericalCoord(); - - // if (PolarEnable) - // { - // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); - // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - - // tmpobj2.x = tmpobj1.x; - // tmpobj2.y = tmpobj1.y; - // tmpobj2.z = 1; + /// + /// Implement a TAKI transformation on a Polar coordinate system + /// This is done by converting the Polar Data to Cartesian, Apply TAKI transformation + /// Then restore the transformed Cartesian Coordinates back to polar + /// + /// + /// + internal EncoderPosition EQ_plTaki(EncoderPosition pos) + { + EncoderPosition result = new EncoderPosition(); + CartesCoord tmpobj1 = new CartesCoord(); + CartesCoord tmpobj3 = new CartesCoord(); + SphericalCoord tmpobj2 = new SphericalCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); - // tmpobj3 = EQ_Transform_Taki(tmpobj2); + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj1 = EQ_Polar2Cartes(tmpobj4); - // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); + tmpobj3 = EQ_Transform_Taki(tmpobj1); - // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); + tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); + result = EQ_PolarSpherical(tmpobj2, tmpobj4); - // } - // else - // { - // tmpobj3 = EQ_Transform_Taki(obj); - // result.x = tmpobj3.x; - // result.y = tmpobj3.y; - // result.z = 1; - // } - // return result; - //} + return result; + } /// /// Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates @@ -685,48 +657,46 @@ private SphericalCoord EQ_Cartes2Polar(CartesCoord cart, CartesCoord rads) return result; } - //internal int EQ_UpdateTaki(double x, double Y) - //{ - // int g3PointAlgorithm = 0; - // int gAlignmentStars_count = 0; - - // TriangleCoord tr = new TriangleCoord(); - // Coord tmpcoord = new Coord(); + internal bool EQ_UpdateTaki(EncoderPosition pos) + { + bool result = false; + List nearestPoints = new List(); - // // Adjust only if there are four alignment stars - // if (gAlignmentStars_count < 3) - // { - // return 0; - // } + // Adjust only if there are four alignment stars + if (this.AlignmentPoints.Count < 3) + { + return result; + } - // switch (g3PointAlgorithm) - // { - // case 1: - // // find the 50 nearest points - then find the nearest enclosing triangle - // tr = EQ_ChooseNearest3Points(x, Y); - // break; - // default: - // // find the 50 nearest points - then find the enclosing triangle with the nearest centre point - // tr = EQ_Choose_3Points(x, Y); - // break; - // } + switch (this.ThreePointAlgorithm) + { + case ThreePointAlgorithmEnum.BestCentre: + // find the 50 nearest points - then find the nearest enclosing triangle + nearestPoints = EQ_ChooseNearest3Points(pos); + break; + default: + // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + nearestPoints = EQ_Choose_3Points(pos); + break; + } - // double gTaki1 = tr.i; - // double gTaki2 = tr.j; - // double gTaki3 = tr.k; + if (nearestPoints.Count < 3) + { + return false; + } - // if (gTaki1 == 0 || gTaki2 == 0 || gTaki3 == 0) - // { - // return 0; - // } + Coord tmpCoord = EQ_sp2Cs(pos); - // tmpcoord.x = x; - // tmpcoord.y = Y; - // tmpcoord = EQ_sp2Cs(tmpcoord); - // return EQ_AssembleMatrix_Taki(tmpcoord.x, tmpcoord.y, EQASCOM.ct_PointsC[Convert.ToInt32(gTaki1)], EQASCOM.ct_PointsC[Convert.ToInt32(gTaki2)], EQASCOM.ct_PointsC[Convert.ToInt32(gTaki3)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki1)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki2)], EQASCOM.my_PointsC[Convert.ToInt32(gTaki3)]); + return EQ_AssembleMatrix_Taki(tmpCoord.x, tmpCoord.y, + nearestPoints[0].EncoderCartesian, + nearestPoints[1].EncoderCartesian, + nearestPoints[2].EncoderCartesian, + nearestPoints[0].TargetCartesian, + nearestPoints[1].TargetCartesian, + nearestPoints[2].TargetCartesian); - //} + } internal bool EQ_UpdateAffine(EncoderPosition pos) { @@ -1272,7 +1242,7 @@ private SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) //Debug.WriteLine($"lat/ha/dec (Radians) = {latRad}/{haRad}/{decRad}"); double[] altAzRad = AstroConvert.GetAltAz(latRad, haRad, decRad); //Debug.WriteLine($"alt/Az (Radians) = {altAzRad[0]}/{altAzRad[1]}"); - double[] altAz = new double[] { AstroConvert.RadToDeg(altAzRad[0]), AstroConvert.RadToDeg(altAzRad[1])}; + double[] altAz = new double[] { AstroConvert.RadToDeg(altAzRad[0]), AstroConvert.RadToDeg(altAzRad[1]) }; //Debug.WriteLine($"alt/Az = {altAz[0]}/{altAz[1]}"); result.x = (((altAz[1] - 180) / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; diff --git a/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs b/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs index b6571d26..71819453 100644 --- a/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs @@ -11,50 +11,68 @@ public partial class AlignmentModel /// /// Returns the encoder steps for a given target. /// Based on code from EQMOD's EncoderTimer.Timer event. + /// Used when reporting current position /// /// /// - public EncoderPosition GetTargetSteps(EncoderPosition encoder) + public EncoderPosition GetEncoderSteps(EncoderPosition encoder) { MapResult result; - EncoderPosition target = encoder; if (!_threeStarEnabled) { SelectedAlignmentPoint = null; result = Delta_Map(encoder); - target = result.EncoderPosition; } else { - switch (this.ThreePointAlgorithm) + switch (this.AlignmentMode) { - case ThreePointAlgorithmEnum.BestCentre: + case AlignmentModeEnum.Nearest: result = DeltaSync_Matrix_Map(encoder); break; - case ThreePointAlgorithmEnum.ClosestPoints: - result = Delta_Matrix_Reverse_Map(encoder); - break; default: result = Delta_Matrix_Reverse_Map(encoder); if (!result.InTriangle) { - result = DeltaSync_Matrix_Map(target); + result = DeltaSync_Matrix_Map(encoder); } - target = result.EncoderPosition; break; } } - return target; + return result.EncoderPosition; } /// - /// Returns the target steps for a given encoder position. + /// Returns the target steps to go to to an aligned target. + /// Used for goto. /// - /// + /// The steps for the target /// - public double[] GetEncoderSteps(double[] targetSteps) + public EncoderPosition GetTargetSteps(EncoderPosition target) { - return targetSteps; + MapResult result; + if (!_threeStarEnabled) + { + SelectedAlignmentPoint = null; + result = DeltaReverse_Map(target); + + } + { + switch (this.AlignmentMode) + { + case AlignmentModeEnum.Nearest: + result = DeltaSyncReverse_Matrix_Map(target); + break; + default: + result = Delta_Matrix_Map(target); + if (!result.InTriangle) + { + result = DeltaSyncReverse_Matrix_Map(target); + } + break; + } + } + return result.EncoderPosition; } diff --git a/EqmodNStarAlignment/Model/AlignmentModel_Math.cs b/EqmodNStarAlignment/Model/AlignmentModel_Math.cs index a1ec8d86..f69da3ed 100644 --- a/EqmodNStarAlignment/Model/AlignmentModel_Math.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_Math.cs @@ -769,36 +769,48 @@ private MapResult Delta_Map(EncoderPosition original) }; } - //private Coordt Delta_Matrix_Map(double RA, double DEC) - //{ - // Coordt result = new Coordt(); - // Coord obtmp = new Coord(); + private long DeltaReverse_RA_Map(long raTarget) + { - // if ((RA >= 0x1000000) || (DEC >= 0x1000000)) - // { - // result.x = RA; - // result.y = DEC; - // result.z = 1; - // result.f = 0; - // return result; - // } + return raTarget - this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) - // obtmp.x = RA; - // obtmp.y = DEC; - // obtmp.z = 1; + } - // // re transform based on the nearest 3 stars - // int i = EQ_UpdateTaki(RA, DEC); + private long DeltaReverse_DEC_Map(long decTarget) + { - // Coord obtmp2 = EQ_plTaki(obtmp); + return decTarget - this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) - // result.x = obtmp2.x; - // result.y = obtmp2.y; - // result.z = 1; - // result.f = (short)i; + } + + private MapResult DeltaReverse_Map(EncoderPosition original) + { + return new MapResult() + { + EncoderPosition = new EncoderPosition(DeltaReverse_RA_Map(original.RA), DeltaReverse_DEC_Map(original.Dec)) + }; + } - // return result; - //} + + private MapResult Delta_Matrix_Map(EncoderPosition pos) + { + MapResult result = new MapResult(); + + if ((pos.RA >= 0x1000000) || (pos.Dec >= 0x1000000)) + { + result.EncoderPosition = new EncoderPosition(pos.RA, pos.Dec); + return result; + } + + // re transform based on the nearest 3 stars + bool inTriangle = EQ_UpdateTaki(pos); + + EncoderPosition obtmp2 = EQ_plTaki(pos); + result.EncoderPosition = new EncoderPosition(obtmp2.RA, obtmp2.Dec); + result.InTriangle = inTriangle; + + return result; + } private MapResult Delta_Matrix_Reverse_Map(EncoderPosition pos) @@ -859,41 +871,36 @@ private MapResult DeltaSync_Matrix_Map(EncoderPosition encoderPosition) return result; } + /// + /// Reverse map from an aligned target position to the encoder position + /// + /// + /// + private MapResult DeltaSyncReverse_Matrix_Map(EncoderPosition targetPosition) + { + MapResult result = new MapResult(); - //private Coordt DeltaSyncReverse_Matrix_Map(double RA, double DEC) - //{ - // Coordt result = new Coordt(); - // int i = 0; - - // if ((RA >= 0x1000000) || (DEC >= 0x1000000) || EQASCOM.gAlignmentStars_count == 0) - // { - // result.x = RA; - // result.y = DEC; - // result.z = 1; - // result.f = 0; - // } - // else - // { - // i = GetNearest(RA, DEC); - - // if (i != -1) - // { - // EQASCOM.gSelectStar = i; - // result.x = RA - (EQASCOM.ct_Points[i].x - EQASCOM.my_Points[i].x); - // result.y = DEC - (EQASCOM.ct_Points[i].y - EQASCOM.my_Points[i].y); - // result.z = 1; - // result.f = 0; - // } - // else - // { - // result.x = RA; - // result.y = DEC; - // result.z = 1; - // result.f = 0; - // } - // } - // return result; - //} + if ((targetPosition.RA >= 0x1000000) || (targetPosition.Dec >= 0x1000000) || this.AlignmentPoints.Count == 0) + { + result.EncoderPosition = targetPosition; + } + else + { + this.SelectedAlignmentPoint = GetNearest(targetPosition); + if (this.SelectedAlignmentPoint != null) + { + result.EncoderPosition = new EncoderPosition( + targetPosition.RA - (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA), // + gRASync01; + targetPosition.Dec - (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec) + ); + } + else + { + result.EncoderPosition = targetPosition; + } + } + return result; + } //TODO: Improve GetQuadrant to return an Enum value (NW, NE, SW or SE) instead of an int. diff --git a/GS.Server/SkyTelescope/SkyServer.cs b/GS.Server/SkyTelescope/SkyServer.cs index afc6753e..528b1698 100644 --- a/GS.Server/SkyTelescope/SkyServer.cs +++ b/GS.Server/SkyTelescope/SkyServer.cs @@ -1213,7 +1213,7 @@ private static int SimGoTo(double[] target, bool trackingState) var stopwatch = Stopwatch.StartNew(); SimTasks(MountTaskName.StopAxes); - var simTarget = Axes.AxesAppToMount(target); + var simTarget = GetAlignedTarget(Axes.AxesAppToMount(target)); #region First Slew @@ -1386,7 +1386,7 @@ private static int SimPrecisionGoToRA(double[] target, bool trackingState, Stopw MonitorLog.LogToMonitor(monitorItem); target[0] += deltaDegree; - var deltaTarget = Axes.AxesAppToMount(target); + var deltaTarget = GetAlignedTarget(Axes.AxesAppToMount(target)); if (SlewState == SlewType.SlewNone) { break; } //check for a stop @@ -1681,7 +1681,7 @@ private static int SkyGoTo(double[] target, bool trackingState) var stopwatch = Stopwatch.StartNew(); SkyTasks(MountTaskName.StopAxes); - var skyTarget = Axes.AxesAppToMount(target); + var skyTarget = GetAlignedTarget(Axes.AxesAppToMount(target)); #region First Slew // time could be off a bit may need to deal with each axis separate @@ -1854,7 +1854,7 @@ private static int SkyPrecisionGoToRA(double[] target, bool trackingState, Stopw if (deltaDegree < gotoPrecision) { break; } target[0] += deltaDegree; - var deltaTarget = Axes.AxesAppToMount(target); + var deltaTarget = GetAlignedTarget(Axes.AxesAppToMount(target)); if (SlewState == SlewType.SlewNone) { break; } //check for a stop object _ = new SkyAxisGoToTarget(0, AxisId.Axis1, deltaTarget[0]); //move to new target @@ -4628,7 +4628,7 @@ public static bool CheckRaDecSyncLimit(double ra, double dec) //convert ra dec to mount positions var xy = Axes.RaDecToAxesXY(new[] { ra, dec }); - var target = Axes.AxesAppToMount(xy); + var target = GetAlignedTarget(Axes.AxesAppToMount(xy)); //convert current position to mount position var current = Axes.AxesMountToApp(new[] { _mountAxisX, _mountAxisY }); @@ -4668,7 +4668,7 @@ public static bool CheckAltAzSyncLimit(double alt, double az) //convert ra dec to mount positions var yx = Axes.AltAzToAxesYX(new[] { alt, az }); - var target = Axes.AxesAppToMount(new[] { yx[1], yx[0] }); + var target = GetAlignedTarget(Axes.AxesAppToMount(new[] { yx[1], yx[0] })); //convert current position to mount position var current = Axes.AxesMountToApp(new[] { _mountAxisX, _mountAxisY }); @@ -4758,7 +4758,7 @@ private static void AddAlignmentPoint() if (AlignmentModel.SyncToRaDec( new long[] { (long)SkyServer.Steps[0], (long)SkyServer.Steps[0] }, new double[] { TargetRa, TargetDec }, - new long[] {targetRaSteps, targetDecSteps }, + new long[] { targetRaSteps, targetDecSteps }, DateTime.Now)) { var monitorItem = new MonitorEntry @@ -4789,7 +4789,53 @@ private static void AddAlignmentPoint() } } + private static double[] GetAlignedTarget(double[] target) + { + if (AlignmentModel.IsAlignmentOn) + { + var raCmd = new SkyGetAngleToStep(SkyQueue.NewId, AxisId.Axis1, DegToRad(target[0])); + var decCmd = new SkyGetAngleToStep(SkyQueue.NewId, AxisId.Axis2, DegToRad(target[1])); + long targetRaSteps = Convert.ToInt64(SkyQueue.GetCommandResult(raCmd).Result); + long targetDecSteps = Convert.ToInt64(SkyQueue.GetCommandResult(decCmd).Result); + EncoderPosition aligned = AlignmentModel.GetTargetSteps(new EncoderPosition(targetRaSteps, targetDecSteps)); + var alignedRaCmd = new SkyGetStepToAngle(SkyQueue.NewId, AxisId.Axis1, aligned.RA); + var alignedDecCmd = new SkyGetStepToAngle(SkyQueue.NewId, AxisId.Axis2, aligned.Dec); + double alignedRa = RadToDeg(Convert.ToDouble(SkyQueue.GetCommandResult(alignedRaCmd).Result)); + double alignedDec = RadToDeg(Convert.ToDouble(SkyQueue.GetCommandResult(alignedDecCmd).Result)); + var monitorItem = new MonitorEntry + { + Datetime = HiResDateTime.UtcNow, + Device = MonitorDevice.Server, + Category = MonitorCategory.Alignment, + Type = MonitorType.Information, + Method = MethodBase.GetCurrentMethod()?.Name, + Thread = Thread.CurrentThread.ManagedThreadId, + Message = $"Mapped Encoder steps: {targetRaSteps}/{targetDecSteps} to {aligned.RA}/{aligned.Dec}\n" + + $" Axis angles: {target[0]}/{target[1]} to {alignedRa}/{alignedDec}" + }; + return new double[] { alignedRa, alignedDec }; + } + else + { + return target; + } + } + + + private static double[] GetDealignedEncoder(double[] alignedSteps) + { + if (AlignmentModel.IsAlignmentOn) + { + var reported = AlignmentModel.GetEncoderSteps(new long[]{(long)alignedSteps[0], (long)alignedSteps[1] }); + return new double[] {reported.RA, reported.Dec}; + + } + else + { + return alignedSteps; + } + } #endregion #region Server Items @@ -5022,7 +5068,7 @@ private static void UpdateServerEvent(object sender, EventArgs e) //} //else //{ - Steps = rawSteps; + Steps = GetDealignedEncoder(rawSteps); //} //Implement Pec From 6f6e8370d258780825e41f6e56d682f5a8adf0c0 Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Fri, 16 Dec 2022 21:17:29 +0000 Subject: [PATCH 09/18] Delta_Matrix_Map which is used for N-Star Goto is now testing correctly compared to EQMOD. --- .../AlignmentModelTests.cs | 62 +++++++++++-------- .../Model/AlignmentModel_EqModVector.cs | 14 ++--- 2 files changed, 43 insertions(+), 33 deletions(-) diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index eb147099..098ba42c 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -181,32 +181,42 @@ public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, 120, "Dec result is incorrect"); } - /* - Get_EncoderHours [DataRow( 6.00557616960605 , 8388608 , 8388037 , 2457601 )] // (EQ_SphericalPolar) - Get_EncoderDegrees [DataRow( 298.381592455407 , 9003008.25 , 9196760 , 2457601 )] // (EQ_SphericalPolar) - Range360 [DataRow( 298.381592455407 )] // (EQ_SphericalPolar) - hadec_aa [DataRow( 0.919235827154167 , 1.57225616639081 , 5.20774120974001 ,-0.775376033155811 , 3.86988561836677 )] // (EQ_SphericalPolar) - [DataRow( 8388037 , 9196760 , 8673472.03453868 , 9625248.59910099 , 1 )] // (EQ_SphericalPolar) - - * - Get_EncoderHours [DataRow( 7.3038666569553 , 8388608 , 8255092 , 2457601 )] // (EQ_SphericalPolar) - Get_EncoderDegrees [DataRow( 596.661305069456 , 9003008.25 , 8775416 , 2457601 )] // (EQ_SphericalPolar) - Range360 [DataRow( 236.661305069456 )] // (EQ_SphericalPolar) - hadec_aa [DataRow( 0.919235827154167 , 1.91214782155489 , 4.13051898080895 ,-0.585620724448854 , 2.47103051434048 )] // (EQ_SphericalPolar) - [DataRow( 8255092 , 8775416 , 8126324.76231087 , 9773690.13425487 , 1 )] // (EQ_SphericalPolar) - - Get_EncoderHours [DataRow( 2.10939611434078 , 8388608 , 8787006 , 2457601 )] // (EQ_SphericalPolar) - Get_EncoderDegrees [DataRow( 544.180076424122 , 9003008.25 , 8417144 , 2457601 )] // (EQ_SphericalPolar) - Range360 [DataRow( 184.180076424122 )] // (EQ_SphericalPolar) - hadec_aa [DataRow( 0.919235827154167 , 0.552238611994933 , 3.21454874650256 ,-0.610002127045004 , 0.692316929152782 )] // (EQ_SphericalPolar) - [DataRow( 8787006 , 8417144 , 7430599.89173006 , 9754617.08246391 , 1 )] // (EQ_SphericalPolar) - - Get_EncoderHours [DataRow( 9.09690303674193 , 8388608 , 8071485 , 2457601 )] // (EQ_SphericalPolar) - Get_EncoderDegrees [DataRow( 360.214379795581 , 9003008.25 , 9618872 , 2457601 )] // (EQ_SphericalPolar) - Range360 [DataRow( 0.214379795581124 )] // (EQ_SphericalPolar) - hadec_aa [DataRow( 0.919235827154167 , 2.38156364862407 , 3.74163327836756E-03 ,-0.45178319762006 , 5.41095216511199 )] // (EQ_SphericalPolar) - [DataRow( 8071485 , 9618872 , 9276243.79763711 , 9878388.38000644 , 1 )] // (EQ_SphericalPolar) - */ + + + [DataRow(8318556, 9135011, 8318406, 9135007)] + [DataRow(8318680, 9135011, 8318530, 9135007)] + [DataRow(8318720, 9135011, 8318570, 9135007)] + [DataRow(8415618, 8802574, 8415466, 8802564)] + [DataRow(8416084, 8802574, 8415932, 8802564)] + [DataRow(8416122, 8802574, 8415970, 8802564)] + [DataRow(8817928, 8501604, 8817859, 8501627)] + [DataRow(8818483, 8501604, 8818414, 8501627)] + [DataRow(8818520, 8501604, 8818451, 8501627)] + [DataRow(7987185, 9739355, 7987148, 9739356)] + [DataRow(7988774, 9739355, 7988737, 9739356)] + [DataRow(7988813, 9739355, 7988776, 9739356)] + [DataRow(8159832, 9424845, 8159627, 9424835)] + [DataRow(8160276, 9424845, 8160071, 9424835)] + [DataRow(8160314, 9424845, 8160109, 9424835)] + [DataRow(8100720, 9086494, 8100493, 9086534)] + [DataRow(8101199, 9086494, 8100972, 9086534)] + [DataRow(8101237, 9086494, 8101010, 9086534)] + [DataRow(8488796, 9229195, 8488634, 9229188)] + [DataTestMethod] + public void TestDelta_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + EncoderPosition test = new EncoderPosition(testRA, testDec); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); + MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); + // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, 120, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, 120, "Dec result is incorrect"); + } + [DataRow(8388037, 9196760, 8673472.03453868, 9625248.59910099, 1)] [DataRow(8255092, 8775416, 8126324.76231087, 9773690.13425487, 1)] // (EQ_SphericalPolar) diff --git a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs index 1a3ffd1b..61358359 100644 --- a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs +++ b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs @@ -689,12 +689,12 @@ internal bool EQ_UpdateTaki(EncoderPosition pos) Coord tmpCoord = EQ_sp2Cs(pos); return EQ_AssembleMatrix_Taki(tmpCoord.x, tmpCoord.y, - nearestPoints[0].EncoderCartesian, - nearestPoints[1].EncoderCartesian, - nearestPoints[2].EncoderCartesian, nearestPoints[0].TargetCartesian, nearestPoints[1].TargetCartesian, - nearestPoints[2].TargetCartesian); + nearestPoints[2].TargetCartesian, + nearestPoints[0].EncoderCartesian, + nearestPoints[1].EncoderCartesian, + nearestPoints[2].EncoderCartesian); } @@ -1461,7 +1461,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) centreDistance = Math.Pow(triangleCentre.x - posCartesean.x, 2) + Math.Pow(triangleCentre.y - posCartesean.y, 2); if (centreDistance < minCentreDistance) { - results = new List { p1, p2, p3 }; // Reversed to match EQMOD sort order + results = new List { p3, p2, p1 }; // Reversed to match EQMOD sort order minCentreDistance = centreDistance; } } @@ -1469,7 +1469,7 @@ internal List EQ_Choose_3Points(EncoderPosition pos) } } results.ForEach(p => p.SelectedForGoto = true); - return results.OrderBy(p => p.AlignTime).ToList(); + return results.ToList(); } @@ -1581,7 +1581,7 @@ internal List EQ_ChooseNearest3Points(EncoderPosition pos) if (done) break; } results.ForEach(p => p.SelectedForGoto = true); - return results.OrderBy(p => p.AlignTime).ToList(); + return results.ToList(); } From a9e11fbe6b5d16318b06865024acd6cb2dd0c24c Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Fri, 16 Dec 2022 21:53:02 +0000 Subject: [PATCH 10/18] DeltaSync_Matrix_Map and DeltaSyncReverse_Matrix_Map are now testing compared to EQMOD results to within 25 arc seconds. --- .../AlignmentModelTests.cs | 91 ++++++++++++------- 1 file changed, 59 insertions(+), 32 deletions(-) diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs index 098ba42c..1a854a32 100644 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs @@ -19,7 +19,7 @@ public class AlignmentModelTests const long decHomePos = 9003008; const long raHomePos = 8388608; const double doubleDelta = 0.0001; - const double deltaEncoder = 10; // 1/16 arcsecond + const double deltaEncoder = 500; // approx 25 arc seconds AlignmentPoint[] points = new AlignmentPoint[] { new AlignmentPoint(new EncoderPosition(8987817, 8919464), new double[] { 23.6715774536133, 77.7643051147461 }, new EncoderPosition(8987821, 8919479), new DateTime(2022, 11, 28, 19, 06, 06)), new AlignmentPoint(new EncoderPosition(7985357, 9135000), new double[] { 21.481803894043, 70.6648559570313 }, new EncoderPosition(7985268, 9135003), new DateTime(2022, 11, 28, 19, 07, 17)), @@ -177,8 +177,8 @@ public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Reverse_Map", BindingFlags.NonPublic | BindingFlags.Instance); MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, 120, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, 120, "Dec result is incorrect"); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); } @@ -213,11 +213,64 @@ public void TestDelta_Matrix_Map(long expectedRa, long expectedDec, long testRA, MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, 120, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, 120, "Dec result is incorrect"); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); } + [DataRow(8352920, 9189469, 8352753, 9189475)] + [DataRow(8353213, 9189469, 8353046, 9189475)] + [DataRow(8353251, 9189469, 8353084, 9189475)] + [DataTestMethod] + public void TestDeltaSyncReverse_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + EncoderPosition test = new EncoderPosition(testRA, testDec); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("DeltaSyncReverse_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); + MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); + // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); + } + + + [DataRow(8388973, 9002686, 8389140, 9002680)] + [DataRow(8390205, 9001670, 8390372, 9001664)] + [DataRow(8392461, 8999710, 8392628, 8999704)] + [DataRow(8396005, 8996502, 8396172, 8996496)] + [DataRow(8425094, 8968120, 8425140, 8968128)] + [DataRow(8430214, 8962352, 8430260, 8962360)] + [DataRow(8433950, 8956216, 8433996, 8956224)] + [DataRow(8437598, 8944216, 8437644, 8944224)] + [DataRow(8438238, 8937976, 8438284, 8937984)] + [DataRow(8438356, 8924648, 8438402, 8924656)] + [DataRow(8438416, 8876272, 8438462, 8876280)] + [DataRow(8438423, 8870216, 8438469, 8870224)] + [DataRow(8438430, 8864368, 8438476, 8864376)] + [DataRow(8438332, 8822237, 8438528, 8822224)] + [DataRow(8438431, 8816106, 8438536, 8816088)] + [DataRow(8440706, 8802554, 8440811, 8802536)] + [DataTestMethod] + public void TestDeltaSync_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) + { + _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; + _alignmentModel.ActivePoints = ActivePointsEnum.All; + + EncoderPosition test = new EncoderPosition(testRA, testDec); + Type type = _alignmentModel.GetType(); + MethodInfo methodInfo = type.GetMethod("DeltaSync_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); + MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); + // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); + Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); // 1000 is about 50 arc seconds just over the angular diameter of Jupiter + Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); + } + + + + [DataRow(8388037, 9196760, 8673472.03453868, 9625248.59910099, 1)] [DataRow(8255092, 8775416, 8126324.76231087, 9773690.13425487, 1)] // (EQ_SphericalPolar) [DataRow(8787006, 8417144, 7430599.89173006, 9754617.08246391, 1)] // (EQ_SphericalPolar) @@ -255,11 +308,6 @@ public void Test_EQ_Polar2Cartes(double expectedRa, double expectedDec, double t } - - - // EQ_Transform_Affine[DataRow(509688.110229567, 43.3535014036799, 509701.89727284, -0.545762684044915, 1)] // (EQ_plAffine) - - [DataRow(8388641.26987594, 9512696.11207337, 0, 509688.110229567, 43.3535014036799, 1, 0)] // 2457601 8388608 9003008.25 (EQ_plAffine) [DataTestMethod] public void Test_EQ_Cartes2Polar(double expectedX, double expectedY, double expectedR, double testX, double testY, double testR,double testRa) @@ -277,28 +325,7 @@ public void Test_EQ_Cartes2Polar(double expectedX, double expectedY, double expe Assert.AreEqual(expectedY, result.y, doubleDelta, "y result is incorrect"); } - /* - i / j = 45.6245611530248 /-35.8465499073082 - aa_hadec [DataRow( 0.919235827154167 ,-0.625640320648098 , 0.796298810987879 ,-2.51826869952598 ,-0.122171513161253 )]// (EQ_PolarSpherical) - X/Y = 2.38092213307473 / 186.999912079268 - [DataRow( 7471271.29753954 , 9742383.65611805 , 1 , 8759202 , 8436394 )] // (EQ_PolarSpherical) - - i / j = 293.182350156892 /-35.2779827906899 - aa_hadec [DataRow( 0.919235827154167 ,-0.615716952455876 , 5.11699731312566 , 2.24992160190372 ,-0.267520981472236 )]// (EQ_PolarSpherical) - X/Y = 8.59406745883108 / 344.672176833943 - [DataRow( 9161266.49146647 , 9750146.49564232 , 1 , 8122975 , 9512771 )] // (EQ_PolarSpherical) - - i / j = 225.266546243132 /-15.7592732434377 - aa_hadec [DataRow( 0.919235827154167 ,-0.275051205505143 , 3.93164292204616 , 1.07035991069787 ,-0.677340930938018 )]// (EQ_PolarSpherical) - X/Y = 4.08847369169778 / 321.191223374651 - [DataRow( 8697627.74809352 , 10016642.0517647 , 1 , 8584348 , 9352474 )] // (EQ_PolarSpherical) - - i / j = 135.229150634789 /-31.6026716503086 - aa_hadec [DataRow( 0.919235827154167 ,-0.551570672094294 , 2.36019392055553 ,-1.30546762821246 ,-0.900034929862018 )]// (EQ_PolarSpherical) - X/Y = 7.01348097965497 / 231.568202883672 - [DataRow( 8082972.21063669 , 9800326.76416405 , 1 , 8284828 , 8740647 )] // (EQ_PolarSpherical) - - */ + [DataRow(7471271.29753954, 9742383.65611805, 1, 8759202, 8436394)] // (EQ_PolarSpherical) [DataRow(9161266.49146647, 9750146.49564232, 1, 8122975, 9512771)] // (EQ_PolarSpherical) From 310e17ee3eb07a53d1ef3a63e20d97e4f864cdce Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Thu, 22 Dec 2022 23:05:59 +0000 Subject: [PATCH 11/18] Working on alignment settings in UI. --- GS.Server/Alignment/AlignmentModel.cs | 441 +++++ .../Alignment/AlignmentModel_EqModVector.cs | 1537 +++++++++++++++++ .../AlignmentModel_EqmodAlignment.cs | 79 + GS.Server/Alignment/AlignmentModel_Goto.cs | 80 + GS.Server/Alignment/AlignmentModel_Math.cs | 307 ++++ GS.Server/Alignment/AlignmentPoint.cs | 139 ++ GS.Server/Alignment/AlignmentSettings.cs | 45 +- GS.Server/Alignment/AlignmentV.xaml | 124 +- GS.Server/Alignment/AlignmentVM.cs | 66 +- GS.Server/Alignment/AxisPosition.cs | 184 ++ GS.Server/Alignment/EqascomDataTypes.cs | 145 ++ GS.Server/Alignment/MapResult.cs | 13 + GS.Server/App.config | 20 - GS.Server/Focuser/FocuserVM.cs | 1 - GS.Server/GS.Server.csproj | 1 - GS.Server/Properties/Alignment.Designer.cs | 42 +- GS.Server/Properties/Alignment.settings | 13 +- GS.Server/SkyTelescope/SkyServer.cs | 111 +- GS.Shared/Domain/EnumTypeConverter.cs | 57 + .../Domain/EnumValueBindingSourceExtension.cs | 71 + .../Languages/StringResServer_en-us.xaml | 10 +- GSSolution.sln | 40 - 22 files changed, 3259 insertions(+), 267 deletions(-) create mode 100644 GS.Server/Alignment/AlignmentModel.cs create mode 100644 GS.Server/Alignment/AlignmentModel_EqModVector.cs create mode 100644 GS.Server/Alignment/AlignmentModel_EqmodAlignment.cs create mode 100644 GS.Server/Alignment/AlignmentModel_Goto.cs create mode 100644 GS.Server/Alignment/AlignmentModel_Math.cs create mode 100644 GS.Server/Alignment/AlignmentPoint.cs create mode 100644 GS.Server/Alignment/AxisPosition.cs create mode 100644 GS.Server/Alignment/EqascomDataTypes.cs create mode 100644 GS.Server/Alignment/MapResult.cs create mode 100644 GS.Shared/Domain/EnumTypeConverter.cs create mode 100644 GS.Shared/Domain/EnumValueBindingSourceExtension.cs diff --git a/GS.Server/Alignment/AlignmentModel.cs b/GS.Server/Alignment/AlignmentModel.cs new file mode 100644 index 00000000..d02e01ed --- /dev/null +++ b/GS.Server/Alignment/AlignmentModel.cs @@ -0,0 +1,441 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.IO; +using System.Reflection; +using System.Text; +using System.Threading; +using System.Linq; +using GS.Shared.Domain; + +namespace GS.Server.Alignment +{ + public enum NotificationType + { + Information, + Data, + Warning, + Error + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum PierSideEnum + { + [Description("Unknown")] + Unknown = -1, + [Description("East")] + EastLookingWest, + [Description("West")] + WestLookingEast, + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum ActivePointsEnum + { + [Description("All")] + All, + [Description("Pierside Only")] + PierSide, + [Description("Local Quadrant")] + LocalQuadrant + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum ThreePointAlgorithmEnum + { + [Description("Best Centre")] + BestCentre, + [Description("Closest Points")] + ClosestPoints + } + + [TypeConverter(typeof(EnumTypeConverter))] + public enum AlignmentBehaviourEnum + { + [Description("N-Star + Nearest")] + NStarPlusNearest, + [Description("Nearest")] + Nearest + } + + + public enum HemisphereEnum + { + Northern, + Southern + } + + public class NotificationEventArgs : EventArgs + { + public NotificationType NotificationType { get; set; } + public string Method { get; set; } + + public int Thread { get; set; } + public string Message { get; set; } + + + public NotificationEventArgs(NotificationType notificationType, string method, string message) + { + this.NotificationType = notificationType; + this.Method = method; + this.Message = message; + this.Thread = System.Threading.Thread.CurrentThread.ManagedThreadId; + } + } + + public partial class AlignmentModel + { + #region Events ... + + public event EventHandler Notification = delegate { }; + + private void RaiseNotification(NotificationType notificationType, string method, string message) + { + Volatile.Read(ref Notification).Invoke(this, new NotificationEventArgs(notificationType, method, message)); + } + + #endregion + + #region variables ... + private readonly List _exceptionMessages = new List(); + + private bool _threeStarEnabled = false; + #endregion + + #region Properties ... + public bool IsAlignmentOn { get; set; } + + private double _proximityLimit = 0.5; + /// + /// How close existing alignment points have to be to the new alignment point + /// before they are removed and replaced with the new one (degrees) + /// + public double ProximityLimit + { + get => _proximityLimit; + set + { + if (_proximityLimit == value) return; + _proximityLimit = value; + } + } + + + private double _siteLongitude; + public double SiteLongitude + { + get => _siteLongitude; + set + { + if (_siteLongitude == value) return; + _siteLongitude = value; + SendToMatrix(); + } + } + + private double _siteLatitude; + public double SiteLatitude + { + get => _siteLatitude; + set + { + if (_siteLatitude == value) return; + _siteLatitude = value; + Hemisphere = (_siteLatitude >= 0 ? HemisphereEnum.Northern : HemisphereEnum.Southern); + SendToMatrix(); // Refresh the matrices as these are affected by the site latitude + } + } + + public HemisphereEnum Hemisphere { get; private set; } = HemisphereEnum.Northern; + + public double SiteElevation { get; set; } + + public bool CheckLocalPier { get; set; } + + public AlignmentBehaviourEnum AlignmentBehaviour { get; set; } = AlignmentBehaviourEnum.NStarPlusNearest; + + public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set; } = ThreePointAlgorithmEnum.BestCentre; + + public AxisPosition Home { get; private set; } + + //private double[] _reportedHomePosition = new double[]{ 0, 0 }; + + public void SetHomePosition(double ra, double dec) + { + Home = new AxisPosition(ra, dec); + SendToMatrix(); + } + + //private AxisPosition _stepsPerRev; + //public AxisPosition StepsPerRev + //{ + // get => _stepsPerRev; + // set + // { + // if (_stepsPerRev == value) + // { + // return; + // } + // _stepsPerRev = value; + // } + //} + + public ActivePointsEnum ActivePoints { get; set; } + + public AlignmentPointCollection AlignmentPoints { get; } = new AlignmentPointCollection(); + + public AlignmentPoint SelectedAlignmentPoint { get; private set; } + + public DateTime? LastAccessDateTime { get; private set; } + + public int NStarMaxCombinationCount { get; set; } = 50; + + // String builder for building more detailed messages. + private readonly StringBuilder _stringBuilder = new StringBuilder(); + + private readonly object _accessLock = new object(); + + private readonly string _configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\Points.config"); + + private readonly string _timeStampFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\TimeStamp.config"); + + private const double _homeZeroPosition = 0x800000; // As per EQMOD + + public AxisPosition EncoderMappingOffset { get; private set; } // Mapping from Mount unsynced positions to internal unsynced positions + + /// + /// RA/Dec unsynced adjustments for when there is only one star/point logged. + /// + private AxisPosition _oneStarAdjustment = new AxisPosition(0, 0); + + #endregion + + #region Constructor ... + public AlignmentModel(double siteLatitude, double siteLongitude, double siteElevation) + { + SiteLatitude = siteLatitude; + SiteLongitude = siteLongitude; + SiteElevation = siteElevation; + } + #endregion + + public void Connect(bool clearPointsOnStartup = false) + { + try + { + // Load the last access time property. + ReadLastAccessTime(); + // Re-load alignment points unless clear points on start up is specified + // In case of lost connections or restarts the points are only cleared if the last time the model was accessed is more than an hour ago. + if (!clearPointsOnStartup || (LastAccessDateTime != null && + (LastAccessDateTime.Value > DateTime.Now - new TimeSpan(1, 0, 0)))) + { + LoadAlignmentPoints(); + } + } + catch (Exception ex) + { + LogException(ex, true); + } + } + + #region Alignment point management ... + public bool SyncToRaDec(double[] unsynced, double[] origRaDec, double[] synced, DateTime syncTime) + { + try + { + lock (_accessLock) + { + + // AlignmentPoints.Add(new AlignmentPoint(unsynced, origRaDec, synced, syncTime)); + if (EQ_NPointAppend(new AlignmentPoint(unsynced , origRaDec, synced, syncTime))) + { + + } + //_currentChecksum = int.MinValue; // Reset checksum so that offsets are recalculated + + //OneStarAdjustment[0] = observedAxes[0] - mountAxes[0]; + //OneStarAdjustment[1] = observedAxes[1] - mountAxes[1]; + SaveAlignmentPoints(); + + return true; + } + } + catch (Exception ex) + { + LogException(ex, true); + } + return false; + } + + + public bool RemoveAlignmentPoint(AlignmentPoint pointToDelete) + { + try + { + bool result = AlignmentPoints.Remove(pointToDelete); + if (result) + { + int ptCt = AlignmentPoints.Count(); + if (ptCt == 0) + { + _oneStarAdjustment = new AxisPosition(0d, 0d); + } + else + { + _oneStarAdjustment = AlignmentPoints[ptCt-1].Delta; // Use the last point's delta + } + if (ptCt < 3) + { + _threeStarEnabled = false; + } + SaveAlignmentPoints(); + } + + return result; + } + catch (Exception ex) + { + LogException(ex, true); + return false; + } + } + + + public void SaveAlignmentPoints(string filename) + { + File.WriteAllText(filename, JsonConvert.SerializeObject(AlignmentPoints, Formatting.Indented)); + } + + private void SaveAlignmentPoints() + { + var dir = Path.GetDirectoryName(_configFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + SaveAlignmentPoints(_configFile); + ReportAlignmentPoints(); + } + + + public void LoadAlignmentPoints(string filename) + { + AlignmentPoints.Clear(); + using (var file = File.OpenText(filename)) + { + var serializer = new JsonSerializer(); + try + { + var loaded = + (AlignmentPointCollection)serializer.Deserialize(file, typeof(AlignmentPointCollection)); + if (loaded != null) + { + foreach (var alignmentPoint in loaded) + { + AlignmentPoints.Add(alignmentPoint); + _oneStarAdjustment = alignmentPoint.Delta; + } + SendToMatrix(); // Updates the cartesean values. + } + } + catch (Exception ex) + { + LogException(ex); + } + } + + } + + private void LoadAlignmentPoints() + { + var dir = Path.GetDirectoryName(_configFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + if (File.Exists(_configFile)) + { + LoadAlignmentPoints(_configFile); + } + ReportAlignmentPoints(); + } + + public void ClearAlignmentPoints() + { + try + { + AlignmentPoints.Clear(); + _oneStarAdjustment = new AxisPosition(0d, 0d); + _threeStarEnabled = false; + SaveAlignmentPoints(); + } + catch (Exception ex) + { + LogException(ex, true); + } + } + + #endregion + + + #region Access time related ... + private void WriteLastAccessTime() + { + LastAccessDateTime = DateTime.Now; + var dir = Path.GetDirectoryName(_timeStampFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + File.WriteAllText(_timeStampFile, JsonConvert.SerializeObject(LastAccessDateTime, Formatting.Indented)); + } + + private void ReadLastAccessTime() + { + var dir = Path.GetDirectoryName(_timeStampFile); + if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) + { + Directory.CreateDirectory(dir); + } + if (File.Exists(_timeStampFile)) + { + using (var file = File.OpenText(_timeStampFile)) + { + var serializer = new JsonSerializer(); + DateTime? loaded = (DateTime?)serializer.Deserialize(file, typeof(DateTime?)); + LastAccessDateTime = loaded; + } + } + } + #endregion + + #region Helper methods ... + private void ReportAlignmentPoints() + { + _stringBuilder.Clear(); + _stringBuilder.AppendLine("=============== Alignment points ==============="); + _stringBuilder.AppendLine("ID \tUnsynced Ra/Dec \tOrig Ra/Dec \tSynced RaDec \tObserved time"); + foreach (var pt in AlignmentPoints) + { + _stringBuilder.AppendLine( + $"{pt.Id:D3}\t{pt.Unsynced.RA}/{pt.Unsynced.Dec}\t{pt.OrigRaDec.RA}/{pt.OrigRaDec.Dec}\t{pt.Synced.RA}/{pt.Synced.Dec}\t{pt.AlignTime}"); + } + RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod()?.Name, _stringBuilder.ToString()); + _stringBuilder.Clear(); + } + + private void LogException(Exception ex, bool allowDuplicates = false) + { + if (allowDuplicates || !_exceptionMessages.Contains(ex.Message)) + { + _exceptionMessages.Add(ex.Message); + string message = $"{ex.Message}|{ex.StackTrace}"; + RaiseNotification(NotificationType.Error, MethodBase.GetCurrentMethod()?.Name, message); + } + } + + #endregion + } +} diff --git a/GS.Server/Alignment/AlignmentModel_EqModVector.cs b/GS.Server/Alignment/AlignmentModel_EqModVector.cs new file mode 100644 index 00000000..ec7e66d1 --- /dev/null +++ b/GS.Server/Alignment/AlignmentModel_EqModVector.cs @@ -0,0 +1,1537 @@ +/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + along with this program. If not, see . + */ +//--------------------------------------------------------------------- +// based on original work +// Copyright � 2006 Raymund Sarmiento +// +// Permission is hereby granted to use this Software for any purpose +// including combining with commercial products, creating derivative +// works, and redistribution of source or binary code, without +// limitation or consideration. Any redistributed copies of this +// Software must include the above Copyright Notice. +// +// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO +// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS +// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//--------------------------------------------------------------------- +// +// EQMODVECTOR.BAS - Matrix Transformation Routines for 3-Star Alignment +// (Renamed EQTakiAffine.cs) +// Written: 10-Dec-06 Raymund Sarmiento +// +// Edits: +// +// When Who What +// --------- --- -------------------------------------------------- +// 10-Dec-06 rcs Initial edit for EQ Mount 3-Star Matrix Transformation +// 14-Dec-06 rcs Added Taki Method on top of Affine Mapping Method for Comparison +// Taki Routines based on John Archbold's Excel computation +// 08-Apr-07 rcs N-star implementation +// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# +//--------------------------------------------------------------------- +// +// + +// DISCLAIMER: + +// You can use the information on this site COMPLETELY AT YOUR OWN RISK. +// The modification steps and other information on this site is provided +// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, +// implied or otherwise, including without limitation any warranty of +// merchantability or fitness for any particular or intended purpose. +// In no event the author will be liable for any direct, indirect, +// punitive, special, incidental or consequential damages or loss of any +// kind whether or not the author has been advised of the possibility +// of such loss. + +// WARNING: + +// Circuit modifications implemented on your setup could invalidate +// any warranty that you may have with your product. Use this +// information at your own risk. The modifications involve direct +// access to the stepper motor controls of your mount. Any "mis-control" +// or "mis-command" / "invalid parameter" or "garbage" data sent to the +// mount could accidentally activate the stepper motors and allow it to +// rotate "freely" damaging any equipment connected to your mount. +// It is also possible that any garbage or invalid data sent to the mount +// could cause its firmware to generate mis-steps pulse sequences to the +// motors causing it to overheat. Make sure that you perform the +// modifications and testing while there is no physical "load" or +// dangling wires on your mount. Be sure to disconnect the power once +// this event happens or if you notice any unusual sound coming from +// the motor assembly. +// + +using GS.Principles; +using GS.Server.SkyTelescope; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; + +namespace GS.Server.Alignment +{ + partial class AlignmentModel + { + + + + + //Define Affine Matrix + + private static Matrix EQMP = Matrix.CreateInstance(); + private static Matrix EQMQ = Matrix.CreateInstance(); + + private static Matrix EQMI = Matrix.CreateInstance(); + private static Matrix EQMM = Matrix.CreateInstance(); + private static Coord EQCO = new Coord(); + + + //Define Taki Matrix + + private static Matrix EQLMN1 = Matrix.CreateInstance(); + private static Matrix EQLMN2 = Matrix.CreateInstance(); + + private static Matrix EQMI_T = Matrix.CreateInstance(); + private static Matrix EQMT = Matrix.CreateInstance(); + private static Coord EQCT = new Coord(); + + + + //Function to put coordinate values into a LMN/lmn matrix array + + private Matrix GETLMN(Coord p1, Coord p2, Coord p3) + { + + Matrix temp = Matrix.CreateInstance(); + Matrix UnitVect = Matrix.CreateInstance(); + + + temp.Element[0, 0] = p2.x - p1.x; + temp.Element[1, 0] = p3.x - p1.x; + + temp.Element[0, 1] = p2.y - p1.y; + temp.Element[1, 1] = p3.y - p1.y; + + temp.Element[0, 2] = p2.z - p1.z; + temp.Element[1, 2] = p3.z - p1.z; + + + + + UnitVect.Element[0, 0] = (temp.Element[0, 1] * temp.Element[1, 2]) - (temp.Element[0, 2] * temp.Element[1, 1]); + UnitVect.Element[0, 1] = (temp.Element[0, 2] * temp.Element[1, 0]) - (temp.Element[0, 0] * temp.Element[1, 2]); + UnitVect.Element[0, 2] = (temp.Element[0, 0] * temp.Element[1, 1]) - (temp.Element[0, 1] * temp.Element[1, 0]); + UnitVect.Element[1, 0] = Math.Pow(UnitVect.Element[0, 0], 2) + Math.Pow(UnitVect.Element[0, 1], 2) + Math.Pow(UnitVect.Element[0, 2], 2); + UnitVect.Element[1, 1] = Math.Sqrt(UnitVect.Element[1, 0]); + if (UnitVect.Element[1, 1] != 0) + { + UnitVect.Element[1, 2] = 1 / UnitVect.Element[1, 1]; + } + + + + temp.Element[2, 0] = UnitVect.Element[1, 2] * UnitVect.Element[0, 0]; + temp.Element[2, 1] = UnitVect.Element[1, 2] * UnitVect.Element[0, 1]; + temp.Element[2, 2] = UnitVect.Element[1, 2] * UnitVect.Element[0, 2]; + + + + + return temp; + + } + + //Function to put coordinate values into a P/Q Affine matrix array + + private Matrix GETPQ(Coord p1, Coord p2, Coord p3) + { + + Matrix temp = Matrix.CreateInstance(); + + temp.Element[0, 0] = p2.x - p1.x; + temp.Element[1, 0] = p3.x - p1.x; + temp.Element[0, 1] = p2.y - p1.y; + temp.Element[1, 1] = p3.y - p1.y; + + return temp; + + } + + // Subroutine to draw the Transformation Matrix (Taki Method) + + private bool EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + { + + + double Det = 0; + + + // Get the LMN Matrix + + EQLMN1 = GETLMN(a1, a2, a3); + + // Get the lmn Matrix + + EQLMN2 = GETLMN(m1, m2, m3); + + + + + // Get the Determinant + + Det = EQLMN1.Element[0, 0] * ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])); + Det -= (EQLMN1.Element[0, 1] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 2]))); + Det += (EQLMN1.Element[0, 2] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1]))); + + + // Compute for the Matrix Inverse of EQLMN1 + + if (Det == 0) + { + throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); + } + else + { + + EQMI_T.Element[0, 0] = ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])) / Det; + EQMI_T.Element[0, 1] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[0, 1] * EQLMN1.Element[2, 2])) / Det; + EQMI_T.Element[0, 2] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[1, 2]) - (EQLMN1.Element[1, 1] * EQLMN1.Element[0, 2])) / Det; + EQMI_T.Element[1, 0] = ((EQLMN1.Element[1, 2] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 2] * EQLMN1.Element[1, 0])) / Det; + EQMI_T.Element[1, 1] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[0, 2])) / Det; + EQMI_T.Element[1, 2] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[1, 0]) - (EQLMN1.Element[1, 2] * EQLMN1.Element[0, 0])) / Det; + EQMI_T.Element[2, 0] = ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1])) / Det; + EQMI_T.Element[2, 1] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[0, 0])) / Det; + EQMI_T.Element[2, 2] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[1, 1]) - (EQLMN1.Element[1, 0] * EQLMN1.Element[0, 1])) / Det; + } + + + + // Get the M Matrix by Multiplying EQMI and EQLMN2 + // EQMI_T - Matrix A + // EQLMN2 - Matrix B + + + EQMT.Element[0, 0] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[0, 1] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[0, 2] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 2]); + + EQMT.Element[1, 0] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[1, 1] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[1, 2] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 2]); + + EQMT.Element[2, 0] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 0]); + EQMT.Element[2, 1] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 1]); + EQMT.Element[2, 2] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 2]); + + + // Get the Coordinate Offset Vector and store it at EQCO Matrix + + EQCT.x = m1.x - ((a1.x * EQMT.Element[0, 0]) + (a1.y * EQMT.Element[1, 0]) + (a1.z * EQMT.Element[2, 0])); + EQCT.y = m1.y - ((a1.x * EQMT.Element[0, 1]) + (a1.y * EQMT.Element[1, 1]) + (a1.z * EQMT.Element[2, 1])); + EQCT.z = m1.z - ((a1.x * EQMT.Element[0, 2]) + (a1.y * EQMT.Element[1, 2]) + (a1.z * EQMT.Element[2, 2])); + + + if ((x + Y) == 0) + { + return false; + } + else + { + return EQ_CheckPoint_in_Triangle(x, Y, a1.x, a1.y, a2.x, a2.y, a3.x, a3.y); + } + + + } + + + /// + /// Function to transform the Coordinates (Taki Method) using the MT Matrix and Offset Vector + /// + /// + /// + private CartesCoord EQ_Transform_Taki(CartesCoord pos) + { + CartesCoord result = new CartesCoord(); + result.x = EQCT.x + ((pos.x * EQMT.Element[0, 0]) + (pos.y * EQMT.Element[1, 0]) + (pos.z * EQMT.Element[2, 0])); + result.y = EQCT.y + ((pos.x * EQMT.Element[0, 1]) + (pos.y * EQMT.Element[1, 1]) + (pos.z * EQMT.Element[2, 1])); + result.z = EQCT.z + ((pos.x * EQMT.Element[0, 2]) + (pos.y * EQMT.Element[1, 2]) + (pos.z * EQMT.Element[2, 2])); + return result; + } + + /// + /// Subroutine to draw the Transformation Matrix (Affine Mapping Method) + /// + /// + /// + /// + /// + /// + /// + /// + /// + /// + private bool EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) + { + + double Det = 0; + + // Get the P Matrix + EQMP = GETPQ(a1, a2, a3); + + // Get the Q Matrix + EQMQ = GETPQ(m1, m2, m3); + + // Get the Inverse of P + // Get the EQMP Determinant for Inverse Computation + Det = (EQMP.Element[0, 0] * EQMP.Element[1, 1]) - (EQMP.Element[0, 1] * EQMP.Element[1, 0]); + + // Make sure Determinant is NON ZERO + if (Det == 0) + { + throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); + } + else + { + //Perform the Matrix Inversion, put result to EQMI matrix + EQMI.Element[0, 0] = (EQMP.Element[1, 1]) / Det; + EQMI.Element[0, 1] = (-EQMP.Element[0, 1]) / Det; + EQMI.Element[1, 0] = (-EQMP.Element[1, 0]) / Det; + EQMI.Element[1, 1] = (EQMP.Element[0, 0]) / Det; + } + + // Get the M Matrix by Multiplying EQMI and EQMQ + // EQMI - Matrix A + // EQMQ - Matrix B + EQMM.Element[0, 0] = (EQMI.Element[0, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 0]); + EQMM.Element[0, 1] = (EQMI.Element[0, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 1]); + EQMM.Element[1, 0] = (EQMI.Element[1, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 0]); + EQMM.Element[1, 1] = (EQMI.Element[1, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 1]); + + // Get the Coordinate Offset Vector and store it at EQCO Matrix + EQCO.x = m1.x - ((a1.x * EQMM.Element[0, 0]) + (a1.y * EQMM.Element[1, 0])); + EQCO.y = m1.y - ((a1.x * EQMM.Element[0, 1]) + (a1.y * EQMM.Element[1, 1])); + + if ((x + Y) == 0) + { + return false; + } + else + { + return EQ_CheckPoint_in_Triangle(x, Y, m1.x, m1.y, m2.x, m2.y, m3.x, m3.y); + } + + } + + + /// + /// Function to transform the Coordinates (Affine Mapping) using the M Matrix and Offset Vector + /// + /// + /// + private CartesCoord EQ_Transform_Affine(CartesCoord pos) + { + CartesCoord result = new CartesCoord(); + result.x = EQCO.x + ((pos.x * EQMM.Element[0, 0]) + (pos.y * EQMM.Element[1, 0])); + result.y = EQCO.y + ((pos.x * EQMM.Element[0, 1]) + (pos.y * EQMM.Element[1, 1])); + return result; + } + + //Function to convert spherical coordinates to Cartesian using the Coord structure + + public Coord EQ_sp2Cs(AxisPosition pos) + { + Coord result = new Coord(); + + CartesCoord tmpobj = new CartesCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); + + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj = EQ_Polar2Cartes(tmpobj4); + result.x = tmpobj.x; + result.y = tmpobj.y; + result.z = 1; + + return result; + } + + + ////Function to convert spherical coordinates to Cartesian using the Coord structure + + //internal Coord EQ_sp2Cs2(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECUnsynced_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAUnsynced_Home_pos = 0; + + // CartesCoord tmpobj = new CartesCoord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, this.StepsPerRev, this.HomeUnsynced, Math.Abs(gLatitude)); + // tmpobj = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos); + // result.x = tmpobj.x; + // result.y = tmpobj.y; + // result.z = 1; + // } + // else + // { + // result.x = obj.x; + // result.y = obj.y; + // result.z = 1; + // } + + // return result; + //} + + + ////Function to convert polar coordinates to Cartesian using the Coord structure + + + //internal Coord EQ_pl2Cs(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECUnsynced_Home_pos = 0; + // double gTot_step = 0; + // object HC = null; + // double RAUnsynced_Home_pos = 0; + + // CartesCoord tmpobj = new CartesCoord(); + + // if (PolarEnable) + // { + // tmpobj = EQ_Polar2Cartes(obj.x, obj.y, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos); + + // result.x = tmpobj.x; + // result.y = tmpobj.y; + // result.z = 1; + // } + // else + // { + // result.x = obj.x; + // result.y = obj.y; + // result.z = 1; + // } + + // return result; + //} + + + /// + /// Implement an Affine transformation on a Polar coordinate system + /// This is done by converting the Polar Data to Cartesian, Apply affine transformation + /// Then restore the transformed Cartesian Coordinates back to polar + /// + /// + /// + internal AxisPosition EQ_plAffine(AxisPosition pos) + { + AxisPosition result = new AxisPosition(); + CartesCoord tmpobj1 = new CartesCoord(); + CartesCoord tmpobj3 = new CartesCoord(); + SphericalCoord tmpobj2 = new SphericalCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); + + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj1 = EQ_Polar2Cartes(tmpobj4); + + tmpobj3 = EQ_Transform_Affine(tmpobj1); + + tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); + result = EQ_PolarSpherical(tmpobj2, tmpobj4); + return result; + } + + + //internal Coord EQ_plAffine2(Coord obj) + //{ + // Coord result = new Coord(); + // double gDECUnsynced_Home_pos = 0; + // double gLatitude = 0; + // double gTot_step = 0; + // object HC = null; + // double RAUnsynced_Home_pos = 0; + + // CartesCoord tmpobj1 = new CartesCoord(); + // Coord tmpobj2 = new Coord(); + // Coord tmpobj3 = new Coord(); + // SphericalCoord tmpobj4 = new SphericalCoord(); + + // if (PolarEnable) + // { + // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos, gLatitude); + + // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos); + + // tmpobj2.x = tmpobj1.x; + // tmpobj2.y = tmpobj1.y; + // tmpobj2.z = 1; + + // tmpobj3 = EQ_Transform_Affine(tmpobj2); + + // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos); + + + // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAUnsynced_Home_pos, gDECUnsynced_Home_pos, gLatitude, tmpobj4.r); + + // } + // else + // { + // tmpobj3 = EQ_Transform_Affine(obj); + // result.x = tmpobj3.x; + // result.y = tmpobj3.y; + // result.z = 1; + // } + + // return result; + //} + + + /// + /// Implement a TAKI transformation on a Polar coordinate system + /// This is done by converting the Polar Data to Cartesian, Apply TAKI transformation + /// Then restore the transformed Cartesian Coordinates back to polar + /// + /// + /// + internal AxisPosition EQ_plTaki(AxisPosition pos) + { + AxisPosition result = new AxisPosition(); + CartesCoord tmpobj1 = new CartesCoord(); + CartesCoord tmpobj3 = new CartesCoord(); + SphericalCoord tmpobj2 = new SphericalCoord(); + SphericalCoord tmpobj4 = new SphericalCoord(); + + tmpobj4 = EQ_SphericalPolar(pos); + tmpobj1 = EQ_Polar2Cartes(tmpobj4); + + tmpobj3 = EQ_Transform_Taki(tmpobj1); + + tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); + result = EQ_PolarSpherical(tmpobj2, tmpobj4); + + + return result; + } + + /// + /// Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates + /// + /// + /// + private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) + { + CartesCoord result = new CartesCoord(); + double raDiff; + + if (polar.x > Home.RA) + { + raDiff = polar.x - Home.RA; + } + else + { + raDiff = 360d - (Home.RA-polar.x); + } + double theta = SkyServer.DegToRad(Range.Range360(raDiff)); + + //treat y as the radius of the polar coordinate + + double radius = polar.y - Home.Dec; + + double radpeak = 0; + + + // Avoid division 0 errors + + if (radius == 0) + { + radius = 1; + } + + // Get the cartesian coordinates + + result.x = Math.Cos(theta) * radius; + result.y = Math.Sin(theta) * radius; + result.ra = radpeak; + + // if radius is a negative number, pass this info on the next conversion routine + + if (radius > 0) + { + result.r = 1; + } + else + { + result.r = -1; + } + + Debug.WriteLine($"Polar2Cartes {polar.x}/{polar.y} => {result.x}/{result.y}/{result.r}"); + return result; + } + + ////Function to convert the Cartesian Coordinate data back to RA/DEC polar + + private SphericalCoord EQ_Cartes2Polar(CartesCoord cart, CartesCoord rads) + { + SphericalCoord result = new SphericalCoord(); + + // Ah the famous radius formula + double radiusder = Math.Sqrt((cart.x * cart.x) + (cart.y * cart.y)) * rads.r; + + + // And the nasty angle compute routine (any simpler way to impelent this ?) + + double angle = 0; + if (cart.x > 0) + { + angle = Math.Atan(cart.y / cart.x); + } + if (cart.x < 0) + { + if (cart.y >= 0) + { + angle = Math.Atan(cart.y / cart.x) + Math.PI; + + } + else + { + angle = Math.Atan(cart.y / cart.x) - Math.PI; + } + } + if (cart.x == 0) + { + if (cart.y > 0) + { + angle = Math.PI / 2d; + } + else + { + angle = -1 * (Math.PI / 2d); + } + } + + // Convert angle to degrees + + angle = SkyServer.RadToDeg(angle); + + if (angle < 0) + { + angle = 360 + angle; + } + + if (rads.r < 0) + { + angle = Range.Range360((angle + 180)); + } + + if (angle > 180) + { + result.x = Home.RA - (360 - angle); + } + else + { + result.x = angle + Home.RA; + } + + //treat y as the polar coordinate radius (ra var not used - always 0) + + result.y = radiusder + Home.Dec; + + Debug.WriteLine($"Cartes2Polar {cart.x}/{cart.y}/{rads.r} => {result.x}/{result.y}"); + return result; + } + + internal bool EQ_UpdateTaki(AxisPosition pos) + { + bool result = false; + List nearestPoints = new List(); + + // Adjust only if there are four alignment stars + if (this.AlignmentPoints.Count < 3) + { + return result; + } + + + switch (this.ThreePointAlgorithm) + { + case ThreePointAlgorithmEnum.BestCentre: + // find the 50 nearest points - then find the nearest enclosing triangle + nearestPoints = EQ_ChooseNearest3Points(pos); + break; + default: + // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + nearestPoints = EQ_Choose_3Points(pos); + break; + } + + if (nearestPoints.Count < 3) + { + return false; + } + + Coord tmpCoord = EQ_sp2Cs(pos); + + return EQ_AssembleMatrix_Taki(tmpCoord.x, tmpCoord.y, + nearestPoints[0].UnsyncedCartesian, + nearestPoints[1].UnsyncedCartesian, + nearestPoints[2].UnsyncedCartesian, + nearestPoints[0].SyncedCartesian, + nearestPoints[1].SyncedCartesian, + nearestPoints[2].SyncedCartesian); + + } + + internal bool EQ_UpdateAffine(AxisPosition pos) + { + bool result = false; + + List nearestPoints = new List(); + + if (this.AlignmentPoints.Count < 3) + { + return result; + } + + switch (this.ThreePointAlgorithm) + { + case ThreePointAlgorithmEnum.BestCentre: + // find the 50 nearest points - then find the nearest enclosing triangle + nearestPoints = EQ_ChooseNearest3Points(pos); + break; + default: + // find the 50 nearest points - then find the enclosing triangle with the nearest centre point + nearestPoints = EQ_Choose_3Points(pos); + break; + } + + + if (nearestPoints.Count < 3) + { + return false; + } + + Coord tmpcoord = EQ_sp2Cs(pos); + + return EQ_AssembleMatrix_Affine(tmpcoord.x, tmpcoord.y, + nearestPoints[0].SyncedCartesian, + nearestPoints[1].SyncedCartesian, + nearestPoints[2].SyncedCartesian, + nearestPoints[0].UnsyncedCartesian, + nearestPoints[1].UnsyncedCartesian, + nearestPoints[2].UnsyncedCartesian); + } + + //// Subroutine to implement find Array index with the lowest value + //private int EQ_FindLowest(double[] List, int min, int max) + //{ + // double val = 0; + // double newval = 0; + // int i = 0; + + // int idx = -1; + // int tempForEndVar = 0; + // if (!(min >= max || max > List.GetUpperBound(0))) + // { + + // val = List[min]; + // tempForEndVar = max; + // for (i = min; i <= tempForEndVar; i++) + // { + // newval = List[i]; + // if (newval <= val) + // { + // val = newval; + // idx = i; + // } + // } + + // } + + // return idx; + //} + + //private void EQ_FindLowest3(double[] List, int[] Sublist, int min, int max) + //{ + // double val = 0; + // double min1 = 0; + // double min2 = 0; + // double min3 = 0; + // int i = 0; + + // int tempForEndVar = 0; + // if (!(min >= max || max > List.GetUpperBound(0))) + // { + + // if (List[1] <= List[2] && List[1] <= List[3]) + // { + // //List 1 is first + // min1 = List[1]; + // if (List[2] <= List[3]) + // { + // //List2 is second + // //List3 is third + // min2 = List[2]; + // min3 = List[3]; + // } + // else + // { + // //List3 is second + // //List2 is third + // min2 = List[3]; + // min3 = List[2]; + // } + // } + // else + // { + // if (List[2] <= List[1] && List[2] <= List[3]) + // { + // //List 2 is first + // min1 = List[2]; + // if (List[1] <= List[3]) + // { + // //List1 is second + // //List3 is third + // min2 = List[1]; + // min3 = List[3]; + // } + // else + // { + // //List3 is second + // //List1 is third + // min2 = List[3]; + // min3 = List[1]; + // } + // } + // else + // { + // if (List[3] <= List[1] && List[3] <= List[2]) + // { + // //List 3 is first + // min1 = List[3]; + // if (List[1] <= List[2]) + // { + // //List1 is second + // //List2 is third + // min2 = List[1]; + // min3 = List[2]; + // } + // else + // { + // //List2 is second + // //List1 is third + // min2 = List[2]; + // min3 = List[1]; + // } + // } + // } + // } + + // val = List[min]; + + // tempForEndVar = max; + // for (i = min; i <= tempForEndVar; i++) + // { + // val = List[i]; + // if (val < min1) + // { + // min1 = val; + // Sublist[3] = Sublist[2]; + // Sublist[2] = Sublist[1]; + // Sublist[1] = i; + // } + // else + // { + // if (val < min2) + // { + // min2 = val; + // Sublist[3] = Sublist[2]; + // Sublist[2] = i; + // } + // else + // { + // if (val < min3) + // { + // Sublist[3] = i; + // } + // } + // } + // } + + // } + + + //} + + + + + //// Subroutine to implement an Array sort + //private void EQ_Quicksort(double[] List, double[] Sublist, int min, int max) + //{ + + + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // double med_value = List[i]; + // double submed = Sublist[i]; + + // List[i] = List[min]; + // Sublist[i] = Sublist[min]; + + // int lo = min; + // int hi = max; + // do + // { + + // while (List[hi] >= med_value) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // Sublist[lo] = submed; + // break; + // } + + // List[lo] = List[hi]; + // Sublist[lo] = Sublist[hi]; + + // lo++; + + // while (List[lo] < med_value) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // Sublist[hi] = submed; + // break; + // } + + // List[hi] = List[lo]; + // Sublist[hi] = Sublist[lo]; + + // } + // while (true); + + // EQ_Quicksort(List, Sublist, min, lo - 1); + // EQ_Quicksort(List, Sublist, lo + 1, max); + + //} + + + //// Subroutine to implement an Array sort + + //private void EQ_Quicksort2(Tdatholder[] List, int min, int max) + //{ + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // Tdatholder med_value = Tdatholder.CreateInstance(); + + // List[i] = List[min]; + + // int lo = min; + // int hi = max; + + // do + // { + + // while (List[hi].dat >= med_value.dat) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // break; + // } + + // List[lo] = List[hi]; + + // lo++; + + // while (List[lo].dat < med_value.dat) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // break; + // } + + // List[hi] = List[lo]; + // } + // while (true); + + // EQ_Quicksort2(List, min, lo - 1); + // EQ_Quicksort2(List, lo + 1, max); + + //} + + //// Subroutine to implement an Array sort with three sublists + + //private void EQ_Quicksort3(double[] List, double[] Sublist1, double[] Sublist2, double[] Sublist3, int min, int max) + //{ + + // if (min >= max) + // { + // return; + // } + + // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); + // double med_value = List[i]; + // double submed1 = Sublist1[i]; + // double submed2 = Sublist2[i]; + // double submed3 = Sublist3[i]; + + // List[i] = List[min]; + // Sublist1[i] = Sublist1[min]; + // Sublist2[i] = Sublist2[min]; + // Sublist3[i] = Sublist3[min]; + + // int lo = min; + // int hi = max; + // do + // { + + + // while (List[hi] >= med_value) + // { + // hi--; + // if (hi <= lo) + // { + // break; + // } + // }; + // if (hi <= lo) + // { + // List[lo] = med_value; + // Sublist1[lo] = submed1; + // Sublist2[lo] = submed2; + // Sublist3[lo] = submed3; + // break; + // } + + + // List[lo] = List[hi]; + // Sublist1[lo] = Sublist1[hi]; + // Sublist2[lo] = Sublist2[hi]; + // Sublist3[lo] = Sublist3[hi]; + + // lo++; + + // while (List[lo] < med_value) + // { + // lo++; + // if (lo >= hi) + // { + // break; + // } + // }; + // if (lo >= hi) + // { + // lo = hi; + // List[hi] = med_value; + // Sublist1[hi] = submed1; + // Sublist2[hi] = submed2; + // Sublist3[hi] = submed3; + // break; + // } + + // List[hi] = List[lo]; + // Sublist1[hi] = Sublist1[lo]; + // Sublist2[hi] = Sublist2[lo]; + // Sublist3[hi] = Sublist3[lo]; + // } + // while (true); + + // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, min, lo - 1); + // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, lo + 1, max); + + //} + + // Function to compute for an area of a triangle + + private double EQ_Triangle_Area(double px1, double py1, double px2, double py2, double px3, double py3) + { + + + //True formula is this + // EQ_Triangle_Area = Abs(((px2 * py1) - (px1 * py2)) + ((px3 * py2) - (px2 * py3)) + ((px1 * py3) - (px3 * py1))) / 2 + + // Make LARGE numerical value safe for Windows by adding a scaling factor + + double ta = (((px2 * py1) - (px1 * py2)) / 10000d) + (((px3 * py2) - (px2 * py3)) / 10000d) + (((px1 * py3) - (px3 * py1)) / 10000d); + + return Math.Abs(ta) / 2d; + + } + + // Function to check if a point is inside the triangle. Computed based sum of areas method + + private bool EQ_CheckPoint_in_Triangle(double px, double py, double px1, double py1, double px2, double py2, double px3, double py3) + { + + + double ta = EQ_Triangle_Area(px1, py1, px2, py2, px3, py3); + double t1 = EQ_Triangle_Area(px, py, px2, py2, px3, py3); + double t2 = EQ_Triangle_Area(px1, py1, px, py, px3, py3); + double t3 = EQ_Triangle_Area(px1, py1, px2, py2, px, py); + + + if (Math.Abs(ta - t1 - t2 - t3) < 2) + { + return true; + } + else + { + return false; + } + + } + + + + /// + /// Returns the centroid of a triangle. + /// + /// + /// + /// + /// + private Coord EQ_GetCenterPoint(Coord p1, Coord p2, Coord p3) + { + + Coord result = new Coord(); + double p2x = 0d; + double p2y = 0d; + double p4x = 0d; + double p4y = 0d; + + // Get the two line 4 point data + + double p1x = p1.x; + double p1y = p1.y; + + + if (p3.x > p2.x) + { + p2x = ((p3.x - p2.x) / 2d) + p2.x; + } + else + { + p2x = ((p2.x - p3.x) / 2d) + p3.x; + } + + if (p3.y > p2.y) + { + p2y = ((p3.y - p2.y) / 2d) + p2.y; + } + else + { + p2y = ((p2.y - p3.y) / 2d) + p3.y; + } + + double p3x = p2.x; + double p3y = p2.y; + + + if (p1.x > p3.x) + { + p4x = ((p1.x - p3.x) / 2d) + p3.x; + } + else + { + p4x = ((p3.x - p1.x) / 2d) + p1.x; + } + + if (p1.y > p3.y) + { + p4y = ((p1.y - p3.y) / 2d) + p3.y; + } + else + { + p4y = ((p3.y - p1.y) / 2d) + p1.y; + } + + + double XD1 = p2x - p1x; + double XD2 = p4x - p3x; + double YD1 = p2y - p1y; + double YD2 = p4y - p3y; + double XD3 = p1x - p3x; + double YD3 = p1y - p3y; + + + double dv = (YD2 * XD1) - (XD2 * YD1); + + if (dv == 0) + { + dv = 0.00000001d; + } //avoid div 0 errors + + + double ua = ((XD2 * YD3) - (YD2 * XD3)) / dv; + double ub = ((XD1 * YD3) - (YD1 * XD3)) / dv; + + result.x = p1x + (ua * XD1); + result.y = p1y + (ub * YD1); + + return result; + } + + /// + /// Converts EQ axis positions in degrees to a polar coordinate base on the Alt/Az. + /// + /// Axis positions in degrees + /// + private SphericalCoord EQ_SphericalPolar(AxisPosition spherical) + { + //Debug.WriteLine($"Spherical -> Polar"); + //Debug.WriteLine($"Input = {spherical.RA}/{spherical.Dec}"); + SphericalCoord result = new SphericalCoord(); + double[] azAlt = Axes.AxesXYToAzAlt(spherical); + + + result.x = (azAlt[0] - 180); + result.y = (azAlt[1] + 90); + double quadrant = 90d; + // Check if RA value is within allowed visible range + if (spherical.RA < this.Home.RA + quadrant && spherical.RA > this.Home.RA - quadrant) + { + result.r = 1; // Weights down + } + else + { + result.r = 0; // Weight up + } + Debug.WriteLine($"EQ_SphericalPolar {spherical.RA}/{spherical.Dec} Weights down {result.r} => {result.x}/{result.y}"); + return result; + } + + private AxisPosition EQ_PolarSpherical(SphericalCoord pos, SphericalCoord range) + { + AxisPosition result = new AxisPosition(); + double az = pos.x + 180; + double alt = pos.y - 90; + double[] axes = Axes.AltAzToAxesYX(new double[]{alt, az }); + + double[] raDec = new double[] { axes[1], axes[0] }; + //Debug.WriteLine($"ha/dec = {haDec[0]}/{haDec[1]}"); + double quadrant = 90d; + if (range.r == 1) + { + // Originally weights were down. + if (raDec[0] < this.Home.RA + quadrant && raDec[0] > this.Home.RA - quadrant) + { + // Weights down so nothing to do. + result = new AxisPosition(raDec); + } + else + { + // Weights would be up so flip to alternative axis position. + result = new AxisPosition(Axes.GetAltAxisPosition(raDec)); + } + } + else + { + // Origininally weights were up! + if (raDec[0] < this.Home.RA + quadrant && raDec[0] > this.Home.RA - quadrant) + { + // Weights would be down so flip + result = new AxisPosition(Axes.GetAltAxisPosition(raDec)); + } + else + { + // Weights woudl be up so nothing to do. + result = new AxisPosition(raDec); + } + } + Debug.WriteLine($"EQ_PolarSpherical {pos.x}/{pos.y} Weights down {range.r} => {result.RA}/{result.Dec}"); + + return result; + } + + + /// + /// Returns the 3 points making up at triangle with the centre nearest the position + /// + /// + /// List of 3 points or an empty list + internal List EQ_Choose_3Points(AxisPosition pos) + { + Dictionary distances = new Dictionary(); + List results = new List(); + // Adjust only if there are three alignment stars + + if (AlignmentPoints.Count <= 3) + { + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + pt.SelectedForGoto = true; + results.Add(pt); + } + return results.OrderBy(p => p.AlignTime).ToList(); + } + + Coord posCartesean = EQ_sp2Cs(pos); + + // first find out the distances to the alignment stars + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + pt.SelectedForGoto = false; + switch (this.ActivePoints) + { + case ActivePointsEnum.All: + // all points + + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.UnsyncedCartesian.y * posCartesean.y < 0) + { + continue; + } + + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.UnsyncedCartesian))) + { + continue; + } + + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Unsynced.RA - pos.RA, 2) + Math.Pow(pt.Unsynced.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.UnsyncedCartesian.x - posCartesean.x, 2) + Math.Pow(pt.UnsyncedCartesian.y - posCartesean.y, 2)); + } + } + + if (distances.Count < 3) + { + return results; // Empty list. + } + + // now sort the distances so the closest stars are at the top + //Just use the nearest 50 stars (or max) - saves processing time + List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); + + var tmp1 = sortedIds.Count - 1; + var tmp2 = tmp1 - 1; + + // iterate through all the triangles posible using the nearest alignment points + double minCentreDistance = double.MaxValue; + double centreDistance; + Coord triangleCentre; + for (int i = 0; i <= tmp2; i++) + { + var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); + for (int j = i + 1; j < tmp1; j++) + { + var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); + for (int k = (j + 1); k < sortedIds.Count; k++) + { + var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); + + + if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, + p1.UnsyncedCartesian.x, p1.UnsyncedCartesian.y, + p2.UnsyncedCartesian.x, p2.UnsyncedCartesian.y, + p3.UnsyncedCartesian.x, p3.UnsyncedCartesian.y)) + { + // Compute for the center point + triangleCentre = EQ_GetCenterPoint(p1.UnsyncedCartesian, p2.UnsyncedCartesian, p3.UnsyncedCartesian); + // don't need full pythagoras - sum of squares is good enough + centreDistance = Math.Pow(triangleCentre.x - posCartesean.x, 2) + Math.Pow(triangleCentre.y - posCartesean.y, 2); + if (centreDistance < minCentreDistance) + { + results = new List { p3, p2, p1 }; // Reversed to match EQMOD sort order + minCentreDistance = centreDistance; + } + } + } + } + } + results.ForEach(p => p.SelectedForGoto = true); + return results.ToList(); + + } + + + + /// + /// Returns the nearest 3 alignment points that form and enclosing triangle around a position. + /// + /// + /// List of 3 points or an empty list. + internal List EQ_ChooseNearest3Points(AxisPosition pos) + { + Dictionary distances = new Dictionary(); + List results = new List(); + // Adjust only if there are three alignment stars + + if (AlignmentPoints.Count <= 3) + { + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + pt.SelectedForGoto = true; + results.Add(pt); + } + return results.OrderBy(p => p.AlignTime).ToList(); + } + + Coord posCartesean = EQ_sp2Cs(pos); + + // first find out the distances to the alignment stars + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + pt.SelectedForGoto = false; + switch (ActivePoints) + { + case ActivePointsEnum.All: + // all points + + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.UnsyncedCartesian.y * posCartesean.y < 0) + { + continue; + } + + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.UnsyncedCartesian))) + { + continue; + } + + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Unsynced.RA - pos.RA, 2) + Math.Pow(pt.Unsynced.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.UnsyncedCartesian.x - posCartesean.x, 2) + Math.Pow(pt.UnsyncedCartesian.y - posCartesean.y, 2)); + } + } + + if (distances.Count < 3) + { + return results; // Empty list. + } + + // now sort the distances so the closest stars are at the top + //Just use the nearest 50 stars (or max) - saves processing time + List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); + + var tmp1 = sortedIds.Count - 1; + var tmp2 = tmp1 - 1; + bool done = false; + + + // iterate through all the triangles posible using the nearest alignment points + for (int i = 0; i <= tmp2; i++) + { + var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); + for (int j = i + 1; j < tmp1; j++) + { + var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); + for (int k = (j + 1); k < sortedIds.Count; k++) + { + var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); + + + if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, + p1.UnsyncedCartesian.x, p1.UnsyncedCartesian.y, + p2.UnsyncedCartesian.x, p2.UnsyncedCartesian.y, + p3.UnsyncedCartesian.x, p3.UnsyncedCartesian.y)) + { + results.Add(p1); + results.Add(p2); + results.Add(p3); + done = true; + } + if (done) break; + } + if (done) break; + } + if (done) break; + } + results.ForEach(p => p.SelectedForGoto = true); + return results.ToList(); + + } + + //public static float GetRnd() + //{ + // Random r = new Random(); + // return (float)(r.Next(1, 1000) / 1000.0); + //} + + } +} + + diff --git a/GS.Server/Alignment/AlignmentModel_EqmodAlignment.cs b/GS.Server/Alignment/AlignmentModel_EqmodAlignment.cs new file mode 100644 index 00000000..ea54b742 --- /dev/null +++ b/GS.Server/Alignment/AlignmentModel_EqmodAlignment.cs @@ -0,0 +1,79 @@ +// This file contains code that is based on the logi from the EQMOD Alignment code. +using System; +using System.Linq; + +namespace GS.Server.Alignment +{ + partial class AlignmentModel + { + public bool EQ_NPointAppend(AlignmentPoint data) + { + bool eq_NPointAppend = true; + _oneStarAdjustment = data.Delta; + + if (AlignmentPoints.Count < 2) + { + // Less than three alignment points so just add the incoming one. + AlignmentPoints.Add(data); + } + else + { + if (AlignmentPoints.Count == 2) + { + AlignmentPoints.Add(data); + // Update the matrices + SendToMatrix(); + } + else + { + // Now have more than 3 so see if this point is a replacement + var nearPoints = this.AlignmentPoints.Where(ap => Math.Abs(ap.Unsynced.RA - data.Unsynced.RA) < _proximityLimit + || Math.Abs(ap.Unsynced.Dec - data.Unsynced.Dec) < _proximityLimit).ToList(); + foreach (AlignmentPoint ap in nearPoints) + { + this.AlignmentPoints.Remove(ap); + } + + // Add the incoming point + AlignmentPoints.Add(data); + + // Update the matrices + SendToMatrix(); + } + } + return eq_NPointAppend; + } + public void SendToMatrix() + { + if (AlignmentPoints.Count < 3) + { + return; + } + foreach (AlignmentPoint pt in AlignmentPoints) + { + pt.UnsyncedCartesian = EQ_sp2Cs(pt.Unsynced); + pt.SyncedCartesian = EQ_sp2Cs(pt.Synced); + + } + + ActivateMatrix(); + } + + private void ActivateMatrix() + { + _threeStarEnabled = false; + if (AlignmentPoints.Count >= 3) + { + + _ = EQ_AssembleMatrix_Taki(0, 0, + AlignmentPoints[0].UnsyncedCartesian, AlignmentPoints[1].UnsyncedCartesian, AlignmentPoints[2].UnsyncedCartesian, + AlignmentPoints[0].SyncedCartesian, AlignmentPoints[1].SyncedCartesian, AlignmentPoints[2].SyncedCartesian); + _ = EQ_AssembleMatrix_Affine(0, 0, + AlignmentPoints[0].SyncedCartesian, AlignmentPoints[1].SyncedCartesian, AlignmentPoints[2].SyncedCartesian, + AlignmentPoints[0].UnsyncedCartesian, AlignmentPoints[1].UnsyncedCartesian, AlignmentPoints[2].UnsyncedCartesian); + _threeStarEnabled = true; + } + } + // /pec /showalignment + } +} diff --git a/GS.Server/Alignment/AlignmentModel_Goto.cs b/GS.Server/Alignment/AlignmentModel_Goto.cs new file mode 100644 index 00000000..fd7efa37 --- /dev/null +++ b/GS.Server/Alignment/AlignmentModel_Goto.cs @@ -0,0 +1,80 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace GS.Server.Alignment +{ + public partial class AlignmentModel + { + + /// + /// Returns the unsynced axis position for a given synced axis position. + /// Based on code from EQMOD's EncoderTimer.Timer event. + /// Used when reporting current position + /// + /// + /// + public AxisPosition GetUnsyncedValue(AxisPosition synced) + { + MapResult result; + if (!_threeStarEnabled) + { + SelectedAlignmentPoint = null; + result = Delta_Map(synced); + } + else + { + switch (this.AlignmentBehaviour) + { + case AlignmentBehaviourEnum.Nearest: + result = DeltaSync_Matrix_Map(synced); + break; + default: + result = Delta_Matrix_Reverse_Map(synced); + if (!result.InTriangle) + { + result = DeltaSync_Matrix_Map(synced); + } + break; + } + } + return result.Position; + } + + /// + /// Returns the synced axis position for a given unsynced axis position. + /// Used for goto. + /// + /// The steps for the target + /// + public AxisPosition GetSyncedValue(AxisPosition unsynced) + { + MapResult result; + if (!_threeStarEnabled) + { + SelectedAlignmentPoint = null; + result = DeltaReverse_Map(unsynced); + + } + else + { + switch (this.AlignmentBehaviour) + { + case AlignmentBehaviourEnum.Nearest: + result = DeltaSyncReverse_Matrix_Map(unsynced); + break; + default: + result = Delta_Matrix_Map(unsynced); + if (!result.InTriangle) + { + result = DeltaSyncReverse_Matrix_Map(unsynced); + } + break; + } + } + return result.Position; + } + + + } +} diff --git a/GS.Server/Alignment/AlignmentModel_Math.cs b/GS.Server/Alignment/AlignmentModel_Math.cs new file mode 100644 index 00000000..d3e72231 --- /dev/null +++ b/GS.Server/Alignment/AlignmentModel_Math.cs @@ -0,0 +1,307 @@ +/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published + by the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + You should have received a copy of the GNU General Public License + a double with this program. If not, see . + */ +//--------------------------------------------------------------------- +// based on original work +// Copyright © 2006 Raymund Sarmiento +// +// Permission is hereby granted to use this Software for any purpose +// including combining with commercial products, creating derivative +// works, and redistribution of source or binary code, without +// limitation or consideration. Any redistributed copies of this +// Software must include the above Copyright Notice. +// +// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO +// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS +// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. +//--------------------------------------------------------------------- +// +// EQMATH.bas - Math functions for EQMOD ASCOM RADECALTAZ computations +// +// +// Written: 07-Oct-06 Raymund Sarmiento +// +// Edits: +// +// When Who What +// --------- --- -------------------------------------------------- +// 04-Nov-06 rcs Initial edit for EQ Mount Driver Function Prototype +// 20-Nov-06 rcs wrote a new function for now_lst that will generate millisecond +// granularity +// 21-Nov-06 rcs Append RA GOTO Compensation to minimize discrepancy +// 19-Mar-07 rcs Initial Edit for Three star alignment +// 05-Apr-07 rcs Add MAXSYNC +// 08-Apr-07 rcs N-star implementation +// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# +//--------------------------------------------------------------------- +// +// +// DISCLAIMER: + +// You can use the information on this site COMPLETELY AT YOUR OWN RISK. +// The modification steps and other information on this site is provided +// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, +// implied or otherwise, including without limitation any warranty of +// merchantability or fitness for any particular or intended purpose. +// In no event the author will be liable for any direct, indirect, +// punitive, special, incidental or consequential damages or loss of any +// kind whether or not the author has been advised of the possibility +// of such loss. + +using System; +using System.Collections.Generic; +using System.Linq; + +namespace GS.Server.Alignment +{ + partial class AlignmentModel + { + + private double Delta_RA_Map(double raEncoder) + { + + return raEncoder - this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) + + } + + private double Delta_DEC_Map(double decEncoder) + { + + return decEncoder - this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) + + } + + private MapResult Delta_Map(AxisPosition original) + { + return new MapResult() + { + Position = new AxisPosition(Delta_RA_Map(original.RA), Delta_DEC_Map(original.Dec)) + }; + } + + private double DeltaReverse_RA_Map(double raTarget) + { + + return raTarget + this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) + + } + + private double DeltaReverse_DEC_Map(double decTarget) + { + + return decTarget + this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) + + } + + private MapResult DeltaReverse_Map(AxisPosition original) + { + return new MapResult() + { + Position = new AxisPosition(DeltaReverse_RA_Map(original.RA), DeltaReverse_DEC_Map(original.Dec)) + }; + } + + + private MapResult Delta_Matrix_Map(AxisPosition pos) + { + MapResult result = new MapResult(); + + // re transform based on the nearest 3 stars + bool inTriangle = EQ_UpdateTaki(pos); + + AxisPosition obtmp2 = EQ_plTaki(pos); + result.Position = new AxisPosition(obtmp2.RA, obtmp2.Dec); + result.InTriangle = inTriangle; + + return result; + } + + + private MapResult Delta_Matrix_Reverse_Map(AxisPosition pos) + { + + MapResult result = new MapResult(); + + + // re transform using the 3 nearest stars + bool inTriangle = EQ_UpdateAffine(pos); + AxisPosition obtmp2 = EQ_plAffine(pos); + + result.Position = new AxisPosition(obtmp2.RA, obtmp2.Dec); + result.InTriangle = inTriangle; + + + return result; + } + + /// + /// Maps an encoder position to the calculate target position + /// + /// + /// + private MapResult DeltaSync_Matrix_Map(AxisPosition encoderPosition) + { + MapResult result = new MapResult(); + + this.SelectedAlignmentPoint = GetNearest(encoderPosition); + if (this.SelectedAlignmentPoint != null) + { + result.Position = new AxisPosition( + encoderPosition.RA + (this.SelectedAlignmentPoint.Synced.RA - this.SelectedAlignmentPoint.Unsynced.RA), // + gRASync01; + encoderPosition.Dec + (this.SelectedAlignmentPoint.Synced.Dec - this.SelectedAlignmentPoint.Unsynced.Dec) + ); // + gDecSync01; + // result.z = 1; + // result.f = 0; + } + else + { + result.Position = encoderPosition; + // result.z = 0; + // result.f = 0; + } + return result; + } + + /// + /// Reverse map from an aligned target position to the encoder position + /// + /// + /// + private MapResult DeltaSyncReverse_Matrix_Map(AxisPosition targetPosition) + { + MapResult result = new MapResult(); + + if (this.AlignmentPoints.Count == 0) + { + result.Position = targetPosition; + } + else + { + this.SelectedAlignmentPoint = GetNearest(targetPosition); + if (this.SelectedAlignmentPoint != null) + { + result.Position = new AxisPosition( + targetPosition.RA - (this.SelectedAlignmentPoint.Synced.RA - this.SelectedAlignmentPoint.Unsynced.RA), // + gRASync01; + targetPosition.Dec - (this.SelectedAlignmentPoint.Synced.Dec - this.SelectedAlignmentPoint.Unsynced.Dec) + ); + } + else + { + result.Position = targetPosition; + } + } + return result; + } + + //TODO: Improve GetQuadrant to return an Enum value (NW, NE, SW or SE) instead of an int. + + /// + /// Returns a quadrant based on a cartesean coordinate + /// + /// + /// + private int GetQuadrant(Coord tmpcoord) + { + int ret = 0; + + if (tmpcoord.x >= 0) + { + if (tmpcoord.y >= 0) + { + ret = 0; + } + else + { + ret = 1; + } + } + else + { + if (tmpcoord.y >= 0) + { + ret = 2; + } + else + { + ret = 3; + } + } + + return ret; + + } + + + /// + /// Return the nearest alignment point to an encoder position + /// + /// + /// + private AlignmentPoint GetNearest(AxisPosition pos) + { + Dictionary distances = new Dictionary(); + int[] datholder2 = new int[this.AlignmentPoints.Count]; + + Coord posCartesean = EQ_sp2Cs(pos); + + foreach (AlignmentPoint pt in this.AlignmentPoints) + { + switch (ActivePoints) + { + case ActivePointsEnum.All: + // all points + break; + case ActivePointsEnum.PierSide: + // only consider points on this side of the meridian + if (pt.UnsyncedCartesian.y * posCartesean.y < 0) + { + continue; + } + break; + case ActivePointsEnum.LocalQuadrant: + // local quadrant + if (GetQuadrant(posCartesean) != GetQuadrant(pt.UnsyncedCartesian)) + { + continue; + } + break; + } + + if (CheckLocalPier) + { + // calculate polar distance + distances.Add(pt.Id, Math.Pow(pt.Unsynced.RA - pos.RA, 2) + Math.Pow(pt.Unsynced.Dec - pos.Dec, 2)); + } + else + { + // calculate cartesian disatnce + distances.Add(pt.Id, Math.Pow(pt.UnsyncedCartesian.x - posCartesean.x, 2) + Math.Pow(pt.UnsyncedCartesian.y - posCartesean.y, 2)); + } + } + + if (distances.Count == 0) + { + return null; + } + else + { + int nearestId = distances.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key).First(); + return AlignmentPoints.FirstOrDefault(pt => pt.Id == nearestId); + } + + } + + + } +} + + diff --git a/GS.Server/Alignment/AlignmentPoint.cs b/GS.Server/Alignment/AlignmentPoint.cs new file mode 100644 index 00000000..017f662f --- /dev/null +++ b/GS.Server/Alignment/AlignmentPoint.cs @@ -0,0 +1,139 @@ +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; +using System.Text; +using System.Threading.Tasks; + +namespace GS.Server.Alignment +{ + public class AlignmentPoint : INotifyPropertyChanged + { + /// + /// Unique ID for alignment point + /// + public int Id { get; set; } + + /// + /// Alignment date and time of the sync + /// + public DateTime AlignTime { get; set; } + + /// + /// The axis position following slew but before sync (where the mount thinks it is pointing) + /// + public AxisPosition Unsynced { get; set; } + + /// + /// The Cartesian equivalent of the Unmapped axis position + /// + public Coord UnsyncedCartesian { get; set; } + + + /// + /// The Target Ra/Dec in hours/degrees + /// + public AxisPosition OrigRaDec { get; set; } + + + /// + /// The unadjusted axis position after sync + /// + public AxisPosition Synced { get; set; } + + /// + /// The cartesean version of the mapped (synched) axis positions + /// + public Coord SyncedCartesian { get; set; } + + [JsonIgnore] + public AxisPosition Delta => (Synced - Unsynced); + + + [JsonIgnore] + public string SyncedTime => $"{AlignTime:G}"; + + private bool _selected; + + /// + /// Selected for correcting display + /// + [JsonIgnore] + public bool Selected + { + get => _selected; + set + { + if (value == _selected) return; + _selected = value; + OnPropertyChanged(); + } + } + + private bool _selectedForGoto; + + /// + /// Selected for slew/goto calculation + /// + [JsonIgnore] + public bool SelectedForGoto + { + get => _selectedForGoto; + set + { + if (value == _selectedForGoto) return; + _selectedForGoto = value; + OnPropertyChanged(); + } + } + + + public AlignmentPoint() + { + + } + + public AlignmentPoint(double[] unsynced, double[] origRaDec, double[] synced, DateTime syncTime) + { + Unsynced = new AxisPosition(unsynced); + OrigRaDec = new AxisPosition(origRaDec); + Synced = new AxisPosition(synced); + AlignTime = syncTime; + } + + #region INotifyPropertyChanged interface ... + public event PropertyChangedEventHandler PropertyChanged; + + protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + #endregion + + } + + public class AlignmentPointCollection : ObservableCollection + { + protected override void InsertItem(int index, AlignmentPoint item) + { + if (item != null && item.Id == 0) + { + if (Items.Any()) + { + item.Id = Items.Max(i => i.Id) + 1; + } + else + { + item.Id = 1; + } + } + base.InsertItem(index, item); + } + + + } + +} diff --git a/GS.Server/Alignment/AlignmentSettings.cs b/GS.Server/Alignment/AlignmentSettings.cs index 2ba0ce94..f18b5725 100644 --- a/GS.Server/Alignment/AlignmentSettings.cs +++ b/GS.Server/Alignment/AlignmentSettings.cs @@ -64,30 +64,46 @@ public static double ProximityLimit } - private static double _nearbyLimit; - public static double NearbyLimit + + private static AlignmentBehaviourEnum _alignmentBehaviour; + public static AlignmentBehaviourEnum AlignmentBehaviour + { + get => _alignmentBehaviour; + set + { + if (_alignmentBehaviour == value) return; + _alignmentBehaviour = value; + Properties.Alignment.Default.AlignmentBehaviour = (int)value; + LogSetting(MethodBase.GetCurrentMethod()?.Name, $"{value}"); + OnStaticPropertyChanged(); + } + + } + + private static ActivePointsEnum _activePoints; + public static ActivePointsEnum ActivePoints { - get => _nearbyLimit; + get => _activePoints; set { - if (Math.Abs(_nearbyLimit - value) < 0.0000000000001) return; - _nearbyLimit = value; - Properties.Alignment.Default.NearbyLimit = value; + if (_activePoints == value) return; + _activePoints = value; + Properties.Alignment.Default.ActivePoints = (int)value; LogSetting(MethodBase.GetCurrentMethod()?.Name, $"{value}"); OnStaticPropertyChanged(); } } - private static int _sampleSize; - public static int SampleSize + private static ThreePointAlgorithmEnum _threePointAlgorithm; + public static ThreePointAlgorithmEnum ThreePointAlgorithm { - get => _sampleSize; + get => _threePointAlgorithm; set { - if (_sampleSize == value) return; - _sampleSize = value; - Properties.Alignment.Default.SampleSize = value; + if (_threePointAlgorithm == value) return; + _threePointAlgorithm = value; + Properties.Alignment.Default.ThreePointAlgorithm = (int)value; LogSetting(MethodBase.GetCurrentMethod()?.Name, $"{value}"); OnStaticPropertyChanged(); } @@ -123,8 +139,9 @@ public static void Load() IsAlignmentOn = Properties.Alignment.Default.IsAlignmentOn; ClearModelOnStartup = Properties.Alignment.Default.ClearModelOnStartup; ProximityLimit = Properties.Alignment.Default.ProximityLimit; - NearbyLimit = Properties.Alignment.Default.NearbyLimit; - SampleSize = Properties.Alignment.Default.SampleSize; + AlignmentBehaviour = (AlignmentBehaviourEnum)Properties.Alignment.Default.AlignmentBehaviour; + ActivePoints = (ActivePointsEnum)Properties.Alignment.Default.ActivePoints; + ThreePointAlgorithm = (ThreePointAlgorithmEnum)Properties.Alignment.Default.ThreePointAlgorithm; } /// diff --git a/GS.Server/Alignment/AlignmentV.xaml b/GS.Server/Alignment/AlignmentV.xaml index 7845b8e4..d35b80cc 100644 --- a/GS.Server/Alignment/AlignmentV.xaml +++ b/GS.Server/Alignment/AlignmentV.xaml @@ -25,11 +25,12 @@ - + + - - - + + + @@ -42,7 +43,24 @@ Command="{x:Static md:DrawerHost.CloseDrawerCommand}" CommandParameter="{x:Static Dock.Left}" IsChecked="{Binding ElementName=MenuToggleButton, Path=IsChecked, Mode=TwoWay}"/> - + + + + + + + + + + + + @@ -54,13 +72,13 @@ Style="{StaticResource MaterialDesignRaisedButton}" Command="{Binding ResetProximityLimit}"/> - - - - - - - - - - public Coord UnsyncedCartesian { get; set; } - - /// - /// The Target Ra/Dec in hours/degrees - /// - public AxisPosition OrigRaDec { get; set; } - - /// /// The unadjusted axis position after sync /// @@ -96,10 +89,9 @@ public AlignmentPoint() } - public AlignmentPoint(double[] unsynced, double[] origRaDec, double[] synced, DateTime syncTime) + public AlignmentPoint(double[] unsynced, double[] synced, DateTime syncTime) { Unsynced = new AxisPosition(unsynced); - OrigRaDec = new AxisPosition(origRaDec); Synced = new AxisPosition(synced); AlignTime = syncTime; } diff --git a/GS.Server/Alignment/AlignmentV.xaml b/GS.Server/Alignment/AlignmentV.xaml index 7bd17736..f59b9706 100644 --- a/GS.Server/Alignment/AlignmentV.xaml +++ b/GS.Server/Alignment/AlignmentV.xaml @@ -192,8 +192,6 @@ - - diff --git a/GS.Server/SkyTelescope/SkyServer.cs b/GS.Server/SkyTelescope/SkyServer.cs index 2dc6f4cb..ffb5a27a 100644 --- a/GS.Server/SkyTelescope/SkyServer.cs +++ b/GS.Server/SkyTelescope/SkyServer.cs @@ -4752,7 +4752,6 @@ private static void AddAlignmentPoint() double[] synced = new double[] { ConvertStepsToDegrees(rawSteps[0], 0), ConvertStepsToDegrees(rawSteps[1], 1) }; if (AlignmentModel.SyncToRaDec( unsynced, - new double[] { TargetRa, TargetDec }, synced, DateTime.Now)) { From d28797bedb4f52d7ae74bd45bdd6482707e73773 Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Mon, 9 Jan 2023 22:46:40 +0000 Subject: [PATCH 16/18] Removing unused projects. --- .../AlignmentModelTests.cs | 393 ---- .../AstroConvertTests.cs | 113 -- .../Data/AlignmentPointsIn.json | 600 ------- .../EqmodNStarAlignment.Tests.csproj | 79 - EqmodNStarAlignment.Tests/EqmodVectorTests.cs | 70 - EqmodNStarAlignment.Tests/Legacy.cs | 92 - .../Properties/AssemblyInfo.cs | 20 - EqmodNStarAlignment.Tests/RangeTests.cs | 21 - EqmodNStarAlignment.Tests/astro32.dll | Bin 28672 -> 0 bytes EqmodNStarAlignment/DataTypes/AxisPosition.cs | 184 -- .../DataTypes/EncoderPosition.cs | 185 -- .../DataTypes/EqascomDataTypes.cs | 145 -- EqmodNStarAlignment/DataTypes/MapResult.cs | 13 - .../EqmodNStarAlignment.csproj | 88 - EqmodNStarAlignment/Model/AlignmentModel.cs | 450 ----- .../Model/AlignmentModel_EqModVector.cs | 1597 ----------------- .../Model/AlignmentModel_EqmodAlignment.cs | 81 - .../Model/AlignmentModel_Goto.cs | 80 - .../Model/AlignmentModel_Math.cs | 1007 ----------- EqmodNStarAlignment/Model/AlignmentPoint.cs | 140 -- .../Properties/AssemblyInfo.cs | 36 - EqmodNStarAlignment/Resources/ASCOM.snk | Bin 596 -> 0 bytes EqmodNStarAlignment/Utilities/AstroConvert.cs | 184 -- .../Utilities/EnumTypeConverter.cs | 57 - EqmodNStarAlignment/Utilities/Range.cs | 140 -- EqmodNStarAlignment/Utilities/SiderealTime.cs | 22 - NStarAlignment.Tests/MatrixTests.cs | 79 - .../NStarAlignment.Tests.csproj | 80 - NStarAlignment.Tests/NStarTriangleCentre.cs | 182 -- NStarAlignment.Tests/NearestTriangleCentre.cs | 182 -- .../Properties/AssemblyInfo.cs | 19 - NStarAlignment.Tests/SphericalPolarTests.cs | 479 ----- NStarAlignment.Tests/TimeUtils.cs | 140 -- NStarAlignment.Tests/packages.config | 5 - 34 files changed, 6963 deletions(-) delete mode 100644 EqmodNStarAlignment.Tests/AlignmentModelTests.cs delete mode 100644 EqmodNStarAlignment.Tests/AstroConvertTests.cs delete mode 100644 EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json delete mode 100644 EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj delete mode 100644 EqmodNStarAlignment.Tests/EqmodVectorTests.cs delete mode 100644 EqmodNStarAlignment.Tests/Legacy.cs delete mode 100644 EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs delete mode 100644 EqmodNStarAlignment.Tests/RangeTests.cs delete mode 100644 EqmodNStarAlignment.Tests/astro32.dll delete mode 100644 EqmodNStarAlignment/DataTypes/AxisPosition.cs delete mode 100644 EqmodNStarAlignment/DataTypes/EncoderPosition.cs delete mode 100644 EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs delete mode 100644 EqmodNStarAlignment/DataTypes/MapResult.cs delete mode 100644 EqmodNStarAlignment/EqmodNStarAlignment.csproj delete mode 100644 EqmodNStarAlignment/Model/AlignmentModel.cs delete mode 100644 EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs delete mode 100644 EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs delete mode 100644 EqmodNStarAlignment/Model/AlignmentModel_Goto.cs delete mode 100644 EqmodNStarAlignment/Model/AlignmentModel_Math.cs delete mode 100644 EqmodNStarAlignment/Model/AlignmentPoint.cs delete mode 100644 EqmodNStarAlignment/Properties/AssemblyInfo.cs delete mode 100644 EqmodNStarAlignment/Resources/ASCOM.snk delete mode 100644 EqmodNStarAlignment/Utilities/AstroConvert.cs delete mode 100644 EqmodNStarAlignment/Utilities/EnumTypeConverter.cs delete mode 100644 EqmodNStarAlignment/Utilities/Range.cs delete mode 100644 EqmodNStarAlignment/Utilities/SiderealTime.cs delete mode 100644 NStarAlignment.Tests/MatrixTests.cs delete mode 100644 NStarAlignment.Tests/NStarAlignment.Tests.csproj delete mode 100644 NStarAlignment.Tests/NStarTriangleCentre.cs delete mode 100644 NStarAlignment.Tests/NearestTriangleCentre.cs delete mode 100644 NStarAlignment.Tests/Properties/AssemblyInfo.cs delete mode 100644 NStarAlignment.Tests/SphericalPolarTests.cs delete mode 100644 NStarAlignment.Tests/TimeUtils.cs delete mode 100644 NStarAlignment.Tests/packages.config diff --git a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs b/EqmodNStarAlignment.Tests/AlignmentModelTests.cs deleted file mode 100644 index 1a854a32..00000000 --- a/EqmodNStarAlignment.Tests/AlignmentModelTests.cs +++ /dev/null @@ -1,393 +0,0 @@ -using System; -using System.Diagnostics; -using System.IO; -using System.Reflection; -using EqmodNStarAlignment.DataTypes; -using EqmodNStarAlignment.Model; -using EqmodNStarAlignment.Utilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; - -namespace EqmodNStarAlignment.Tests -{ - [TestClass] - public class AlignmentModelTests - { - const double siteLatitude = 52.6683333333333; - const double siteLongitude = -1.33888888888889; - const double siteElevation = 200d; - const double siteTemperatire = 15d; - const long decHomePos = 9003008; - const long raHomePos = 8388608; - const double doubleDelta = 0.0001; - const double deltaEncoder = 500; // approx 25 arc seconds - AlignmentPoint[] points = new AlignmentPoint[] { - new AlignmentPoint(new EncoderPosition(8987817, 8919464), new double[] { 23.6715774536133, 77.7643051147461 }, new EncoderPosition(8987821, 8919479), new DateTime(2022, 11, 28, 19, 06, 06)), - new AlignmentPoint(new EncoderPosition(7985357, 9135000), new double[] { 21.481803894043, 70.6648559570313 }, new EncoderPosition(7985268, 9135003), new DateTime(2022, 11, 28, 19, 07, 17)), - new AlignmentPoint(new EncoderPosition(7847708, 9164640), new double[] { 22.8413619995117, 66.3250198364258 }, new EncoderPosition(7847528, 9164630), new DateTime(2022, 11, 28, 19, 08, 09)), - new AlignmentPoint(new EncoderPosition(8200354, 9412632), new double[] { 21.2521438598633, 29.9979152679443 }, new EncoderPosition(8200185, 9412623), new DateTime(2022, 11, 30, 20, 51, 15)), - new AlignmentPoint(new EncoderPosition(8380206, 9263912), new double[] { 19.5041027069092, 51.7807502746582 }, new EncoderPosition(8380039, 9263918), new DateTime(2022, 11, 30, 20, 51, 45)), - new AlignmentPoint(new EncoderPosition(8421824, 9522552), new double[] { 19.107213973999, 13.8985624313354 }, new EncoderPosition(8421625, 9522528), new DateTime(2022, 11, 30, 20, 52, 18)), - new AlignmentPoint(new EncoderPosition(7887790, 9676808), new double[] { 0.343226462602615, -8.69821166992188 }, new EncoderPosition(7887531, 9676788), new DateTime(2022, 11, 30, 20, 53, 31)), - new AlignmentPoint(new EncoderPosition(7907761, 9417944), new double[] { 0.159508779644966, 29.2189121246338 }, new EncoderPosition(7907519, 9417941), new DateTime(2022, 11, 30, 20, 54, 12)), - new AlignmentPoint(new EncoderPosition(8155121, 9549296), new double[] { 21.7548809051514, 9.98066520690918 }, new EncoderPosition(8154849, 9549274), new DateTime(2022, 11, 30, 20, 54, 51)), - new AlignmentPoint(new EncoderPosition(8964653, 8318792), new double[] { 1.87664878368378, -10.2228670120239 }, new EncoderPosition(8964648, 8318820), new DateTime(2022, 11, 30, 20, 56, 38)), - new AlignmentPoint(new EncoderPosition(8549669, 8439192), new double[] { 5.94036722183228, 7.41184711456299 }, new EncoderPosition(8549590, 8439206), new DateTime(2022, 11, 30, 20, 57, 16)), - new AlignmentPoint(new EncoderPosition(8836220, 8668816), new double[] { 3.16128063201904, 41.0447845458984 }, new EncoderPosition(8836045, 8668807), new DateTime(2022, 11, 30, 20, 58, 21)), - new AlignmentPoint(new EncoderPosition(8810409, 8729584), new double[] { 3.43303275108337, 49.9433364868164 }, new EncoderPosition(8810306, 8729555), new DateTime(2022, 11, 30, 20, 59, 35)), - new AlignmentPoint(new EncoderPosition(8028636, 8809304), new double[] { 11.0852670669556, 61.624095916748 }, new EncoderPosition(8028459, 8809295), new DateTime(2022, 11, 30, 21, 00, 36)), - new AlignmentPoint(new EncoderPosition(8378814, 8423856), new double[] { 7.6750659942627, 5.16721248626709 }, new EncoderPosition(8378754, 8423883), new DateTime(2022, 11, 30, 21, 01, 14)), - new AlignmentPoint(new EncoderPosition(8387315, 8605928), new double[] { 7.60103368759155, 31.8366107940674 }, new EncoderPosition(8387210, 8605946), new DateTime(2022, 11, 30, 21, 01, 45)), - new AlignmentPoint(new EncoderPosition(8206767, 8622712), new double[] { 9.37405490875244, 34.2941551208496 }, new EncoderPosition(8206583, 8622723), new DateTime(2022, 11, 30, 21, 02, 17)), - new AlignmentPoint(new EncoderPosition(8661869, 8841768), new double[] { 4.93953990936279, 66.3796844482422 }, new EncoderPosition(8661823, 8841760), new DateTime(2022, 11, 30, 21, 02, 58)), - new AlignmentPoint(new EncoderPosition(8625168, 8702760), new double[] { 5.30665588378906, 46.0202331542969 }, new EncoderPosition(8624972, 8702773), new DateTime(2022, 11, 30, 21, 03, 24)), - new AlignmentPoint(new EncoderPosition(8696329, 8501640), new double[] { 4.62079238891602, 16.5555591583252 }, new EncoderPosition(8696186, 8501627), new DateTime(2022, 11, 30, 21, 03, 58)), - new AlignmentPoint(new EncoderPosition(8959119, 9178696), new double[] { 14.0829401016235, 64.2641220092773 }, new EncoderPosition(8959093, 9178699), new DateTime(2022, 11, 30, 21, 05, 44)), - new AlignmentPoint(new EncoderPosition(8912307, 9356584), new double[] { 14.549503326416, 38.2075653076172 }, new EncoderPosition(8912190, 9356578), new DateTime(2022, 11, 30, 21, 06, 15)), - new AlignmentPoint(new EncoderPosition(8412924, 9595864), new double[] { 19.4437313079834, 3.1609582901001 }, new EncoderPosition(8412645, 9595830), new DateTime(2022, 11, 30, 21, 07, 12)) - }; - - - private EncoderPosition stepsPerRev = new EncoderPosition(2457601, 2457601); - - private AlignmentModel _alignmentModel; - - [TestInitialize] - public void Initialize() - { - _alignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); - _alignmentModel.StepsPerRev = stepsPerRev; - _alignmentModel.SetHomePosition(raHomePos, decHomePos); - string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); - _alignmentModel.LoadAlignmentPoints(inputFile); - - } - - - [TestMethod] - public void SavePointsTest() - { - string outputFile = Path.Combine(Directory.GetCurrentDirectory(), "AlignmentPointsOut.json"); - if (File.Exists(outputFile)) - { - File.Delete(outputFile); - } - foreach (AlignmentPoint pt in points) - { - _alignmentModel.EQ_NPointAppend(pt); - } - _alignmentModel.SaveAlignmentPoints(outputFile); - - Assert.IsTrue(File.Exists(outputFile)); - } - - [TestMethod] - public void LoadPointsTest() - { - string inputFile = Path.Combine(Directory.GetCurrentDirectory(), "Data", "AlignmentPointsIn.json"); - _alignmentModel.ClearAlignmentPoints(); - - _alignmentModel.LoadAlignmentPoints(inputFile); - - Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 23); - - } - - [TestMethod] - public void TestMatrices() - { - - Matrix ExpectedTaki = Matrix.CreateInstance(); - ExpectedTaki.Element[0, 0] = 0.999962437601123; - ExpectedTaki.Element[0, 1] = -1.03237679560398E-03; - ExpectedTaki.Element[0, 2] = 0; - ExpectedTaki.Element[1, 0] = 4.1772366345733E-04; - ExpectedTaki.Element[1, 1] = 0.999904533164291; - ExpectedTaki.Element[1, 2] = 0; - ExpectedTaki.Element[2, 0] = 0; - ExpectedTaki.Element[2, 1] = 0; - ExpectedTaki.Element[2, 2] = 1; - - Matrix ExpectedAffine = Matrix.CreateInstance(); - ExpectedAffine.Element[0, 0] = 1.00003713248826; - ExpectedAffine.Element[0, 1] = 1.03251370113913E-03; - ExpectedAffine.Element[1, 0] = -4.17779058621084E-04; - ExpectedAffine.Element[1, 1] = 1.00009504460391; - - // Clear points and reload first three - _alignmentModel.ClearAlignmentPoints(); - - for (int i = 0; i < 3; i++) - { - _alignmentModel.EQ_NPointAppend(points[i]); - } - - Assert.IsTrue(_alignmentModel.AlignmentPoints.Count == 3); - - Assert.AreEqual(ExpectedTaki.Element[0, 0], AlignmentModel.EQMT.Element[0, 0], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[0, 1], AlignmentModel.EQMT.Element[0, 1], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[0, 2], AlignmentModel.EQMT.Element[0, 2], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[1, 0], AlignmentModel.EQMT.Element[1, 0], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[1, 1], AlignmentModel.EQMT.Element[1, 1], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[1, 2], AlignmentModel.EQMT.Element[1, 2], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[2, 0], AlignmentModel.EQMT.Element[2, 0], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[2, 1], AlignmentModel.EQMT.Element[2, 1], doubleDelta); - Assert.AreEqual(ExpectedTaki.Element[2, 2], AlignmentModel.EQMT.Element[2, 2], doubleDelta); - - Assert.AreEqual(ExpectedAffine.Element[0, 0], AlignmentModel.EQMM.Element[0, 0], doubleDelta); - Assert.AreEqual(ExpectedAffine.Element[0, 1], AlignmentModel.EQMM.Element[0, 1], doubleDelta); - Assert.AreEqual(ExpectedAffine.Element[1, 0], AlignmentModel.EQMM.Element[1, 0], doubleDelta); - Assert.AreEqual(ExpectedAffine.Element[1, 1], AlignmentModel.EQMM.Element[1, 1], doubleDelta); - - } - - [DataRow(8230673, 8846876, 8230828, 8846880)] - [DataRow(8224190, 8840364, 8224348, 8840368)] - [DataRow(8218188, 8834403, 8218348, 8834408)] - [DataRow(8212194, 8828474, 8212404, 8828464)] - [DataRow(8206462, 8822595, 8206588, 8822600)] - [DataRow(8200335, 8816551, 8200468, 8816552)] - [DataRow(8194520, 8810698, 8194660, 8810696)] - [DataRow(8188449, 8804653, 8188596, 8804648)] - [DataRow(8182274, 8798512, 8182428, 8798504)] - [DataRow(8176361, 8792548, 8176548, 8792552)] - [DataRow(8170243, 8786429, 8170364, 8786408)] - [DataRow(8164092, 8780291, 8164220, 8780272)] - [DataRow(8157949, 8774145, 8158084, 8774128)] - [DataRow(8152079, 8768280, 8152220, 8768264)] - [DataRow(8145665, 8761853, 8145812, 8761840)] - [DataRow(8139500, 8755707, 8139652, 8755696)] - [DataRow(8133279, 8749473, 8133436, 8749464)] - [DataRow(8126858, 8743046, 8127020, 8743040)] - [DataRow(8120654, 8736900, 8120820, 8736896)] - [DataRow(8052366, 8698287, 8052543, 8698296)] - [DataRow(8052373, 8698287, 8052550, 8698296)] - [DataRow(8052380, 8698287, 8052557, 8698296)] - [DataRow(8052387, 8698287, 8052564, 8698296)] - [DataRow(8114850, 8731041, 8115020, 8731040)] - [DataRow(8108318, 8724510, 8108492, 8724512)] - [DataRow(8102251, 8718452, 8102428, 8718456)] - [DataTestMethod] - public void TestDelta_Matrix_Reverse_Map(long expectedRa, long expectedDec, long testRA, long testDec) - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - EncoderPosition test = new EncoderPosition(testRA, testDec); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Reverse_Map", BindingFlags.NonPublic | BindingFlags.Instance); - MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); - // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); - } - - - - [DataRow(8318556, 9135011, 8318406, 9135007)] - [DataRow(8318680, 9135011, 8318530, 9135007)] - [DataRow(8318720, 9135011, 8318570, 9135007)] - [DataRow(8415618, 8802574, 8415466, 8802564)] - [DataRow(8416084, 8802574, 8415932, 8802564)] - [DataRow(8416122, 8802574, 8415970, 8802564)] - [DataRow(8817928, 8501604, 8817859, 8501627)] - [DataRow(8818483, 8501604, 8818414, 8501627)] - [DataRow(8818520, 8501604, 8818451, 8501627)] - [DataRow(7987185, 9739355, 7987148, 9739356)] - [DataRow(7988774, 9739355, 7988737, 9739356)] - [DataRow(7988813, 9739355, 7988776, 9739356)] - [DataRow(8159832, 9424845, 8159627, 9424835)] - [DataRow(8160276, 9424845, 8160071, 9424835)] - [DataRow(8160314, 9424845, 8160109, 9424835)] - [DataRow(8100720, 9086494, 8100493, 9086534)] - [DataRow(8101199, 9086494, 8100972, 9086534)] - [DataRow(8101237, 9086494, 8101010, 9086534)] - [DataRow(8488796, 9229195, 8488634, 9229188)] - [DataTestMethod] - public void TestDelta_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - EncoderPosition test = new EncoderPosition(testRA, testDec); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("Delta_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); - MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); - // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); - } - - - [DataRow(8352920, 9189469, 8352753, 9189475)] - [DataRow(8353213, 9189469, 8353046, 9189475)] - [DataRow(8353251, 9189469, 8353084, 9189475)] - [DataTestMethod] - public void TestDeltaSyncReverse_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - EncoderPosition test = new EncoderPosition(testRA, testDec); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("DeltaSyncReverse_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); - MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); - // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); - } - - - [DataRow(8388973, 9002686, 8389140, 9002680)] - [DataRow(8390205, 9001670, 8390372, 9001664)] - [DataRow(8392461, 8999710, 8392628, 8999704)] - [DataRow(8396005, 8996502, 8396172, 8996496)] - [DataRow(8425094, 8968120, 8425140, 8968128)] - [DataRow(8430214, 8962352, 8430260, 8962360)] - [DataRow(8433950, 8956216, 8433996, 8956224)] - [DataRow(8437598, 8944216, 8437644, 8944224)] - [DataRow(8438238, 8937976, 8438284, 8937984)] - [DataRow(8438356, 8924648, 8438402, 8924656)] - [DataRow(8438416, 8876272, 8438462, 8876280)] - [DataRow(8438423, 8870216, 8438469, 8870224)] - [DataRow(8438430, 8864368, 8438476, 8864376)] - [DataRow(8438332, 8822237, 8438528, 8822224)] - [DataRow(8438431, 8816106, 8438536, 8816088)] - [DataRow(8440706, 8802554, 8440811, 8802536)] - [DataTestMethod] - public void TestDeltaSync_Matrix_Map(long expectedRa, long expectedDec, long testRA, long testDec) - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - EncoderPosition test = new EncoderPosition(testRA, testDec); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("DeltaSync_Matrix_Map", BindingFlags.NonPublic | BindingFlags.Instance); - MapResult result = (MapResult)methodInfo.Invoke(_alignmentModel, new object[] { test }); - // var result = AlignmentModel.Delta_Matrix_Reverse_Map(new EncoderPosition(testRA, testDec)); - Assert.AreEqual(expectedRa, result.EncoderPosition.RA, deltaEncoder, "RA result is incorrect"); // 1000 is about 50 arc seconds just over the angular diameter of Jupiter - Assert.AreEqual(expectedDec, result.EncoderPosition.Dec, deltaEncoder, "Dec result is incorrect"); - } - - - - - [DataRow(8388037, 9196760, 8673472.03453868, 9625248.59910099, 1)] - [DataRow(8255092, 8775416, 8126324.76231087, 9773690.13425487, 1)] // (EQ_SphericalPolar) - [DataRow(8787006, 8417144, 7430599.89173006, 9754617.08246391, 1)] // (EQ_SphericalPolar) - [DataRow(8071485, 9618872, 9276243.79763711, 9878388.38000644, 1)] // (EQ_SphericalPolar) - [DataTestMethod] - public void Test_EQ_SphericalPolar(long ra, long dec, double expectedX, double expectedY, double expectedR) - - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - EncoderPosition test = new EncoderPosition(ra, dec); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("EQ_SphericalPolar", BindingFlags.NonPublic | BindingFlags.Instance); - SphericalCoord result = (SphericalCoord)methodInfo.Invoke(_alignmentModel, new object[] { test }); - Assert.AreEqual(expectedX, result.x, 1d, "x result is incorrect"); - Assert.AreEqual(expectedY, result.y, 1d, "y result is incorrect"); - Assert.AreEqual(expectedR, result.r, 1d, "r result is incorrect"); - } - - [DataRow(509702.147272839, -0.545762684044915, 8388607.58399624, 9512710.14727313)] // 2457601 8388608 9003008.25 (EQ_plAffine) - [DataTestMethod] - public void Test_EQ_Polar2Cartes(double expectedRa, double expectedDec, double testX, double testY) - - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - SphericalCoord test = new SphericalCoord(testX, testY, 0); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("EQ_Polar2Cartes", BindingFlags.NonPublic | BindingFlags.Instance); - CartesCoord result = (CartesCoord)methodInfo.Invoke(_alignmentModel, new object[] { test }); - Assert.AreEqual(expectedRa, result.x, doubleDelta, "x result is incorrect"); - Assert.AreEqual(expectedDec, result.y, doubleDelta, "y result is incorrect"); - } - - - [DataRow(8388641.26987594, 9512696.11207337, 0, 509688.110229567, 43.3535014036799, 1, 0)] // 2457601 8388608 9003008.25 (EQ_plAffine) - [DataTestMethod] - public void Test_EQ_Cartes2Polar(double expectedX, double expectedY, double expectedR, double testX, double testY, double testR,double testRa) - { - // EQ_Cartes2Polar(tmpobj3.X, tmpobj3.Y, tmpobj1.r, tmpobj1.RA, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos) - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - CartesCoord test = new CartesCoord(testX, testY, 0d, 0d, 0d); - CartesCoord rads = new CartesCoord(0d, 0d, 0d, testR, testRa); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("EQ_Cartes2Polar", BindingFlags.NonPublic | BindingFlags.Instance); - SphericalCoord result = (SphericalCoord)methodInfo.Invoke(_alignmentModel, new object[] { test, rads }); - Assert.AreEqual(expectedX, result.x, doubleDelta, "x result is incorrect"); - Assert.AreEqual(expectedY, result.y, doubleDelta, "y result is incorrect"); - } - - - - [DataRow(7471271.29753954, 9742383.65611805, 1, 8759202, 8436394)] // (EQ_PolarSpherical) - [DataRow(9161266.49146647, 9750146.49564232, 1, 8122975, 9512771)] // (EQ_PolarSpherical) - [DataRow(8697627.74809352, 10016642.0517647, 1, 8584348, 9352474)] // (EQ_PolarSpherical) - [DataRow(8082972.21063669, 9800326.76416405, 1, 8284828, 8740647)] // (EQ_PolarSpherical) - [DataTestMethod] - public void Test_EQ_PolarSpherical(double ra, double dec, long range, double testX, double testY) - - { - _alignmentModel.ThreePointAlgorithm = ThreePointAlgorithmEnum.ClosestPoints; - _alignmentModel.ActivePoints = ActivePointsEnum.All; - - SphericalCoord test = new SphericalCoord(ra, dec, 0d); - SphericalCoord rads = new SphericalCoord(0d, 0d, range); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("EQ_PolarSpherical", BindingFlags.NonPublic | BindingFlags.Instance); - EncoderPosition result = (EncoderPosition)methodInfo.Invoke(_alignmentModel, new object[] { test, rads }); - Assert.AreEqual(testX, result.RA, 1d, "x result is incorrect"); - Assert.AreEqual(testY, result.Dec, 1d, "y result is incorrect"); - } - - - - [DataRow(7.17370069429496, 8388608, 8268421, 2457601)] // (EQ_SphericalPolar) - [DataRow(6.00557616960605, 8388608, 8388037, 2457601)] - [DataRow(7.3038666569553, 8388608, 8255092, 2457601)] - [DataRow(9.09690303674193, 8388608, 8071485, 2457601)] - [DataRow(2.10939611434078, 8388608, 8787006, 2457601)] - [DataTestMethod] - public void Test_Get_EncoderHours(double expectedHrs, long raCentre, long encoderRa, long stepsPerRev) - { - // Get_EncoderHours(RACENTER, RA, TOT, 0) - Assert.AreEqual(_alignmentModel.HomeEncoder.RA, raCentre, "RA Home position is incorrect."); - Assert.AreEqual(_alignmentModel.StepsPerRev.RA, stepsPerRev, "RA Steps Per 360 is incorrect"); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("Get_EncoderHours", BindingFlags.NonPublic | BindingFlags.Instance); - double result = (double)methodInfo.Invoke(_alignmentModel, new object[] { encoderRa }); - Assert.AreEqual(expectedHrs, result, doubleDelta, "Resultant hours are incorrect"); - } - - [DataRow(246.372629242908, 9003008, 8841712, 2457601)] // (EQ_SphericalPolar) - [DataRow(298.381592455407, 9003008, 9196760, 2457601)] - [DataRow(236.661305069456, 9003008, 8775416, 2457601)] - [DataRow(184.180076424122, 9003008, 8417144, 2457601)] - [DataRow(0.214379795581124, 9003008, 9618872, 2457601)] - [DataTestMethod] - public void Test_Get_EncoderDegrees(double expectedDegrees, long decCentre, long encoderDec, long stepsPerRev) - { - // j = Get_EncoderDegrees(DECCENTER, DEC, TOT, 0) + 270 - Assert.AreEqual(_alignmentModel.HomeEncoder.Dec, decCentre, "Dec Home position is incorrect."); - Assert.AreEqual(_alignmentModel.StepsPerRev.Dec, stepsPerRev, "Dec Steps Per 360 is incorrect"); - Type type = _alignmentModel.GetType(); - MethodInfo methodInfo = type.GetMethod("Get_EncoderDegrees", BindingFlags.NonPublic | BindingFlags.Instance); - double result = (double)methodInfo.Invoke(_alignmentModel, new object[] { encoderDec }); - result = Range.Range360(result + 270d); - Assert.AreEqual(expectedDegrees, result, doubleDelta, "Resultant degrees are incorrect"); - } - - - - } -} - - - diff --git a/EqmodNStarAlignment.Tests/AstroConvertTests.cs b/EqmodNStarAlignment.Tests/AstroConvertTests.cs deleted file mode 100644 index ca9bbe05..00000000 --- a/EqmodNStarAlignment.Tests/AstroConvertTests.cs +++ /dev/null @@ -1,113 +0,0 @@ -using EqmodNStarAlignment.Utilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using System.Diagnostics; - -namespace EqmodNStarAlignment.Tests -{ - [TestClass] - public class AstroConvertTests - { - [DataRow(52.6683333333333, 0, 51.5)] - [DataRow(52.6683333333333, 3.5, 51.5)] - [DataRow(52.6683333333333, 9.5, 51.5)] - [DataRow(52.6683333333333, 12.0, 51.5)] - [DataRow(52.6683333333333, 15.5, 51.5)] - [DataRow(52.6683333333333, 21.5, 51.5)] - [DataRow(52.6683333333333, 0, -51.5)] - [DataRow(52.6683333333333, 3.5, -51.5)] - [DataRow(52.6683333333333, 9.5, -51.5)] - [DataRow(52.6683333333333, 12.0, -51.5)] - [DataRow(52.6683333333333, 15.5, -51.5)] - [DataRow(52.6683333333333, 21.5, -51.5)] - [DataTestMethod] - public void CompareHaDec_aa2GetAltAz(double lat, double ha, double dec) - { - double haRad = AstroConvert.HrsToRad(Range.Range24(ha)); - double decRad = AstroConvert.DegToRad(Range.Range360(dec)); - double latRad = AstroConvert.DegToRad(lat); - Debug.WriteLine($"HA/Dec (Radians) = {haRad}/{decRad}"); - - - double[] altAzRad1 = AstroConvert.GetAltAz(latRad, haRad, decRad); - Debug.WriteLine($"Alt/Az 1 (Radians) = {altAzRad1[0]}/{altAzRad1[1]}"); - - double altOut = 0d; - double azOut = 0d; - Legacy.hadec_aa(latRad, haRad, decRad, ref altOut, ref azOut); - - Debug.WriteLine($"Alt/Az 2 (Radians) = {altOut}/{azOut}"); - - Assert.AreEqual(altOut, altAzRad1[0], 0.0001); - Assert.AreEqual(azOut, altAzRad1[1], 0.0001); - - } - - [DataRow(52.6683333333333, 51.5, 35.0)] - [DataRow(52.6683333333333, 51.5, 125.0)] - [DataRow(52.6683333333333, 51.5, 180.0)] - [DataRow(52.6683333333333, 51.5, 215.0)] - [DataRow(52.6683333333333, 51.5, 305.0)] - [DataRow(52.6683333333333, -51.5, 35.0)] - [DataRow(52.6683333333333, -51.5, 125.0)] - [DataRow(52.6683333333333, -51.5, 180.0)] - [DataRow(52.6683333333333, -51.5, 215.0)] - [DataRow(52.6683333333333, -51.5, 305.0)] - [DataTestMethod] - public void CompareAa_hadec2GetHaDec(double lat, double alt, double az) - { - double altRad = AstroConvert.DegToRad(Range.Range90(alt)); - double azRad = AstroConvert.DegToRad(Range.Range360(az)); - double latRad = AstroConvert.DegToRad(lat); - Debug.WriteLine($"\nAlt/Az (Radians) = {altRad}/{azRad}"); - - - double[] haDecRad1 = AstroConvert.GetHaDec(latRad, altRad, azRad); - Debug.WriteLine($"HA/Dec 1 (Radians) = {haDecRad1[0]}/{haDecRad1[1]}"); - - double haOut = 0d; - double decOut = 0d; - Legacy.aa_hadec(latRad, altRad, azRad, ref haOut, ref decOut); - - Debug.WriteLine($"HA/Dec 2 (Radians) = {haOut}/{decOut}"); - - Assert.AreEqual(haOut, haDecRad1[0], 0.0001); - Assert.AreEqual(decOut, haDecRad1[1], 0.0001); - - } - - /* - \\ hadec_aa( 0.919235827154167 , 1.38444074819784 , 5.38324899333645 , -0.585928494201069 , 3.96459956111439 ) - hadec_aa [DataRow(-33.5712298065115 , 227.154822259407 , 5.28817411776769 , 308.437447738669 , 52.6683333333333 )] // (EQ_SphericalPolar) - \\ aa_hadec( 0.919235827154167 , -0.586184018473869 , 3.96475101882834 , 1.38487663513127 , -0.9000246120113 ) - aa_hadec [DataRow( 79.3475863211831 ,-51.5676117143725 ,-33.5858703149488 , 227.163500458629 , 52.6683333333333 )]// (EQ_PolarSpherical) - - \\ hadec_aa( 0.919235827154167 , 1.56557568277018 , 4.71760386839224 , -0.919190774841039 , 3.15019144835534 ) - hadec_aa [DataRow(-52.6657519537263 , 180.492674607753 , 5.98005860186418 , 270.298791382328 , 52.6683333333333 )] // (EQ_SphericalPolar) - \\ aa_hadec( 0.919235827154167 , -0.919213641878334 , 3.15024659248481 , 1.5707963267949 , -1.56554822344537 ) - aa_hadec [DataRow( 89.9999999794503 ,-89.6993058071428 ,-52.6670622106594 , 180.495834381095 , 52.6683333333333 )]// (EQ_PolarSpherical) - - */ - - [DataRow(0.919235827154167, 1.38444074819784, 5.38324899333645, -0.585928494201069, 3.96459956111439)] - [DataRow(0.919235827154167, 1.56557568277018, 4.71760386839224, -0.919190774841039, 3.15019144835534)] - [DataTestMethod] - public void TestGetAltAz(double latRad, double haRad, double decRad, double altRad, double azRad) - { - double[] altAzRad = AstroConvert.GetAltAz(latRad, haRad, decRad); - Assert.AreEqual(altRad, altAzRad[0], 0.001, "Alt is wrong value"); - Assert.AreEqual(azRad, altAzRad[1], 0.001, "Az is wrong value"); - } - - [DataRow(0.919235827154167, -0.586184018473869, 3.96475101882834, 1.38487663513127, -0.9000246120113)] - [DataRow(0.919235827154167, -0.919213641878334, 3.15024659248481, 1.5707963267949, -1.56554822344537)] - [DataTestMethod] - public void TestGetHaDec(double latRad, double altRad, double azRad, double haRad, double decRad) - { - double[] haDecRad = AstroConvert.GetHaDec(latRad, altRad, azRad); - Assert.AreEqual(haRad, haDecRad[0], 0.001, "HA is wrong value"); - Assert.AreEqual(decRad, haDecRad[1], 0.001, "Dec is wrong value"); - } - - } -} diff --git a/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json b/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json deleted file mode 100644 index ae7ed0ac..00000000 --- a/EqmodNStarAlignment.Tests/Data/AlignmentPointsIn.json +++ /dev/null @@ -1,600 +0,0 @@ -[ - { - "Id": 1, - "AlignTime": "2022-11-28T19:06:06", - "Encoder": { - "RA": 8987817, - "Dec": 8919464 - }, - "EncoderCartesian": { - "x": 342728.16089956538, - "y": -6649.3588683929838, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 23.6715774536133, - "Dec": 77.7643051147461 - }, - "Target": { - "RA": 8987821, - "Dec": 8919479 - }, - "TargetCartesian": { - "x": 342758.08223162079, - "y": -6646.4711006996022, - "z": 1.0 - } - }, - { - "Id": 2, - "AlignTime": "2022-11-28T19:07:17", - "Encoder": { - "RA": 7985357, - "Dec": 9135000 - }, - "EncoderCartesian": { - "x": 278206.08853135124, - "y": 136673.20035502975, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 21.481803894043, - "Dec": 70.6648559570313 - }, - "Target": { - "RA": 7985268, - "Dec": 9135003 - }, - "TargetCartesian": { - "x": 278173.736918419, - "y": 136623.09109976405, - "z": 1.0 - } - }, - { - "Id": 3, - "AlignTime": "2022-11-28T19:08:09", - "Encoder": { - "RA": 7847708, - "Dec": 9164640 - }, - "EncoderCartesian": { - "x": 191153.88419931807, - "y": 59329.821460311192, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 22.8413619995117, - "Dec": 66.3250198364258 - }, - "Target": { - "RA": 7847528, - "Dec": 9164630 - }, - "TargetCartesian": { - "x": 191150.61251677698, - "y": 59182.4784978333, - "z": 1.0 - } - }, - { - "Id": 4, - "AlignTime": "2022-11-30T20:51:15", - "Encoder": { - "RA": 8200354, - "Dec": 9412632 - }, - "EncoderCartesian": { - "x": -13919.881744680215, - "y": 684697.9981491986, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 21.2521438598633, - "Dec": 29.9979152679443 - }, - "Target": { - "RA": 8200185, - "Dec": 9412623 - }, - "TargetCartesian": { - "x": -14139.317224949669, - "y": 684475.672556519, - "z": 1.0 - } - }, - { - "Id": 5, - "AlignTime": "2022-11-30T20:51:45", - "Encoder": { - "RA": 8380206, - "Dec": 9263912 - }, - "EncoderCartesian": { - "x": 416846.96845720615, - "y": 553420.05401999969, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 19.5041027069092, - "Dec": 51.7807502746582 - }, - "Target": { - "RA": 8380039, - "Dec": 9263918 - }, - "TargetCartesian": { - "x": 416628.11493296688, - "y": 553391.65624300111, - "z": 1.0 - } - }, - { - "Id": 6, - "AlignTime": "2022-11-30T20:52:18", - "Encoder": { - "RA": 8421824, - "Dec": 9522552 - }, - "EncoderCartesian": { - "x": 238415.57011894978, - "y": 1092404.25300819, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 19.107213973999, - "Dec": 13.8985624313354 - }, - "Target": { - "RA": 8421625, - "Dec": 9522528 - }, - "TargetCartesian": { - "x": 237966.90363106574, - "y": 1092221.8164167311, - "z": 1.0 - } - }, - { - "Id": 7, - "AlignTime": "2022-11-30T20:53:31", - "Encoder": { - "RA": 7887790, - "Dec": 9676808 - }, - "EncoderCartesian": { - "x": -815547.06846760714, - "y": 273221.7218742111, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 0.343226462602615, - "Dec": -8.69821166992188 - }, - "Target": { - "RA": 7887531, - "Dec": 9676788 - }, - "TargetCartesian": { - "x": -815608.9485487903, - "y": 272599.02581901528, - "z": 1.0 - } - }, - { - "Id": 8, - "AlignTime": "2022-11-30T20:54:12", - "Encoder": { - "RA": 7907761, - "Dec": 9417944 - }, - "EncoderCartesian": { - "x": -291027.75380665145, - "y": 237650.45582203756, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 0.159508779644966, - "Dec": 29.2189121246338 - }, - "Target": { - "RA": 7907519, - "Dec": 9417941 - }, - "TargetCartesian": { - "x": -291127.43161888863, - "y": 237226.22113095695, - "z": 1.0 - } - }, - { - "Id": 9, - "AlignTime": "2022-11-30T20:54:51", - "Encoder": { - "RA": 8155121, - "Dec": 9549296 - }, - "EncoderCartesian": { - "x": -320725.98442469758, - "y": 779540.8161398056, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 21.7548809051514, - "Dec": 9.98066520690918 - }, - "Target": { - "RA": 8154849, - "Dec": 9549274 - }, - "TargetCartesian": { - "x": -321065.92753720423, - "y": 779031.81836311787, - "z": 1.0 - } - }, - { - "Id": 10, - "AlignTime": "2022-11-30T20:56:38", - "Encoder": { - "RA": 8964653, - "Dec": 8318792 - }, - "EncoderCartesian": { - "x": -856204.6769207156, - "y": -93064.025504266756, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 1.87664878368378, - "Dec": -10.2228670120239 - }, - "Target": { - "RA": 8964648, - "Dec": 8318820 - }, - "TargetCartesian": { - "x": -856147.97213822755, - "y": -93074.688817985909, - "z": 1.0 - } - }, - { - "Id": 11, - "AlignTime": "2022-11-30T20:57:16", - "Encoder": { - "RA": 8549669, - "Dec": 8439192 - }, - "EncoderCartesian": { - "x": -241287.73550525878, - "y": -923730.87958620174, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 5.94036722183228, - "Dec": 7.41184711456299 - }, - "Target": { - "RA": 8549590, - "Dec": 8439206 - }, - "TargetCartesian": { - "x": -241125.82207367822, - "y": -923845.64256972133, - "z": 1.0 - } - }, - { - "Id": 12, - "AlignTime": "2022-11-30T20:58:21", - "Encoder": { - "RA": 8836220, - "Dec": 8668816 - }, - "EncoderCartesian": { - "x": -118016.3137986113, - "y": -249147.29470023135, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 3.16128063201904, - "Dec": 41.0447845458984 - }, - "Target": { - "RA": 8836045, - "Dec": 8668807 - }, - "TargetCartesian": { - "x": -117948.42381812769, - "y": -249405.35522428833, - "z": 1.0 - } - }, - { - "Id": 13, - "AlignTime": "2022-11-30T20:59:35", - "Encoder": { - "RA": 8810409, - "Dec": 8729584 - }, - "EncoderCartesian": { - "x": 10587.822495838014, - "y": -241814.3121508582, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 3.43303275108337, - "Dec": 49.9433364868164 - }, - "Target": { - "RA": 8810306, - "Dec": 8729555 - }, - "TargetCartesian": { - "x": 10584.066870398241, - "y": -241958.97158849737, - "z": 1.0 - } - }, - { - "Id": 14, - "AlignTime": "2022-11-30T21:00:36", - "Encoder": { - "RA": 8028636, - "Dec": 8809304 - }, - "EncoderCartesian": { - "x": 799568.8135243149, - "y": -275811.9765455196, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 11.0852670669556, - "Dec": 61.624095916748 - }, - "Target": { - "RA": 8028459, - "Dec": 8809295 - }, - "TargetCartesian": { - "x": 799708.560806113, - "y": -275671.60279076087, - "z": 1.0 - } - }, - { - "Id": 15, - "AlignTime": "2022-11-30T21:01:14", - "Encoder": { - "RA": 8378814, - "Dec": 8423856 - }, - "EncoderCartesian": { - "x": 88280.058254589487, - "y": -1181333.7144075404, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 7.6750659942627, - "Dec": 5.16721248626709 - }, - "Target": { - "RA": 8378754, - "Dec": 8423883 - }, - "TargetCartesian": { - "x": 88475.4938693466, - "y": -1181348.8395656894, - "z": 1.0 - } - }, - { - "Id": 16, - "AlignTime": "2022-11-30T21:01:45", - "Encoder": { - "RA": 8387315, - "Dec": 8605928 - }, - "EncoderCartesian": { - "x": 316116.1919223427, - "y": -833792.92244761018, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 7.60103368759155, - "Dec": 31.8366107940674 - }, - "Target": { - "RA": 8387210, - "Dec": 8605946 - }, - "TargetCartesian": { - "x": 316332.94734941737, - "y": -833809.39461784938, - "z": 1.0 - } - }, - { - "Id": 17, - "AlignTime": "2022-11-30T21:02:17", - "Encoder": { - "RA": 8206767, - "Dec": 8622712 - }, - "EncoderCartesian": { - "x": 686997.790061526, - "y": -797459.83996625361, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 9.37405490875244, - "Dec": 34.2941551208496 - }, - "Target": { - "RA": 8206583, - "Dec": 8622723 - }, - "TargetCartesian": { - "x": 687373.25458370347, - "y": -797335.29697127256, - "z": 1.0 - } - }, - { - "Id": 18, - "AlignTime": "2022-11-30T21:02:58", - "Encoder": { - "RA": 8661869, - "Dec": 8841768 - }, - "EncoderCartesian": { - "x": 285414.38366064249, - "y": -249659.318428496, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 4.93953990936279, - "Dec": 66.3796844482422 - }, - "Target": { - "RA": 8661823, - "Dec": 8841760 - }, - "TargetCartesian": { - "x": 285428.00986361125, - "y": -249697.51210656876, - "z": 1.0 - } - }, - { - "Id": 19, - "AlignTime": "2022-11-30T21:03:24", - "Encoder": { - "RA": 8625168, - "Dec": 8702760 - }, - "EncoderCartesian": { - "x": 102260.38822977719, - "y": -477240.57892356854, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 5.30665588378906, - "Dec": 46.0202331542969 - }, - "Target": { - "RA": 8624972, - "Dec": 8702773 - }, - "TargetCartesian": { - "x": 102477.42021589061, - "y": -477417.913543929, - "z": 1.0 - } - }, - { - "Id": 20, - "AlignTime": "2022-11-30T21:03:58", - "Encoder": { - "RA": 8696329, - "Dec": 8501640 - }, - "EncoderCartesian": { - "x": -327512.345605439, - "y": -604327.76189749048, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 4.62079238891602, - "Dec": 16.5555591583252 - }, - "Target": { - "RA": 8696186, - "Dec": 8501627 - }, - "TargetCartesian": { - "x": -327381.17138699419, - "y": -604596.83183397341, - "z": 1.0 - } - }, - { - "Id": 21, - "AlignTime": "2022-11-30T21:05:44", - "Encoder": { - "RA": 8959119, - "Dec": 9178696 - }, - "EncoderCartesian": { - "x": 858342.46155537292, - "y": 46924.7693590433, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 14.0829401016235, - "Dec": 64.2641220092773 - }, - "Target": { - "RA": 8959093, - "Dec": 9178699 - }, - "TargetCartesian": { - "x": 858345.16833731206, - "y": 46953.300017825939, - "z": 1.0 - } - }, - { - "Id": 22, - "AlignTime": "2022-11-30T21:06:15", - "Encoder": { - "RA": 8912307, - "Dec": 9356584 - }, - "EncoderCartesian": { - "x": 1187015.8701597615, - "y": 218031.25275041172, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 14.549503326416, - "Dec": 38.2075653076172 - }, - "Target": { - "RA": 8912190, - "Dec": 9356578 - }, - "TargetCartesian": { - "x": 1186928.6231936759, - "y": 218298.30140286568, - "z": 1.0 - } - }, - { - "Id": 23, - "AlignTime": "2022-11-30T21:07:12", - "Encoder": { - "RA": 8412924, - "Dec": 9595864 - }, - "EncoderCartesian": { - "x": 101238.08335319124, - "y": 1219790.59552515, - "z": 1.0 - }, - "OrigRaDec": { - "RA": 19.4437313079834, - "Dec": 3.1609582901001 - }, - "Target": { - "RA": 8412645, - "Dec": 9595830 - }, - "TargetCartesian": { - "x": 100578.5267699728, - "y": 1219452.4650133308, - "z": 1.0 - } - } -] \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj b/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj deleted file mode 100644 index 2e8232ff..00000000 --- a/EqmodNStarAlignment.Tests/EqmodNStarAlignment.Tests.csproj +++ /dev/null @@ -1,79 +0,0 @@ - - - - - Debug - AnyCPU - {55FBCFCA-0220-43E2-82D0-DD9253A1D254} - Library - Properties - EqmodNStarAlignment.Tests - EqmodNStarAlignment.Tests - v4.7.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - true - full - false - ..\Builds\Debug\ - DEBUG;TRACE - prompt - 4 - x86 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - PreserveNewest - - - - - {2b12e1e9-a2bb-4fa8-9e49-4888b2874233} - EqmodNStarAlignment - - - - - PreserveNewest - - - - - 2.1.2 - - - 2.1.2 - - - - - \ No newline at end of file diff --git a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs b/EqmodNStarAlignment.Tests/EqmodVectorTests.cs deleted file mode 100644 index ca75e9f8..00000000 --- a/EqmodNStarAlignment.Tests/EqmodVectorTests.cs +++ /dev/null @@ -1,70 +0,0 @@ -using EqmodNStarAlignment.DataTypes; -using EqmodNStarAlignment.Model; -using EqmodNStarAlignment.Utilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; - -namespace EqmodNStarAlignment.Tests -{ - //TODO: Set methods back to private and invoke using reflection. - [TestClass] - public class EqmodVectorTests - { - const double siteLatitude = 52.6683333333333; - const double siteLongitude = -1.33888888888889; - const double siteElevation = 200d; - const double siteTemperatire = 15d; - - const long decHomePos = 9003008; - const long raHomePos = 8388608; - const double doubleDelta = 0.00000001; - - const HemisphereEnum hemisphere = HemisphereEnum.Northern; - - private EncoderPosition stepsPerRev = new EncoderPosition(2457601, 2457601); - - private AlignmentModel AlignmentModel; - - [TestInitialize] - public void Initialize() - { - AlignmentModel = new AlignmentModel(siteLatitude, siteLongitude, siteElevation); - AlignmentModel.StepsPerRev = stepsPerRev; - AlignmentModel.SetHomePosition(raHomePos, decHomePos); - - } - - [TestMethod] - public void TestEQ_sp2Cs_1() - { - EncoderPosition encoder = new EncoderPosition(8619721, 8850776); - Coord expected = new Coord() - { - x = 322188.53833622788, - y = -258342.03199652123, - z = 1 - }; - Coord result = AlignmentModel.EQ_sp2Cs(encoder); - Assert.AreEqual(expected.x, result.x, 1.0); - Assert.AreEqual(expected.y, result.y, 1.0); - Assert.AreEqual(expected.z, result.z); - } - - [TestMethod] - public void TestEQ_sp2Cs_2() - { - EncoderPosition encoder = new EncoderPosition(8487504, 8913867); - Coord expected = new Coord() - { - x = 456444.627886648, - y = -182935.356983078, - z = 1 - }; - Coord result = AlignmentModel.EQ_sp2Cs(encoder); - Assert.AreEqual(expected.x, result.x, 1.0); - Assert.AreEqual(expected.y, result.y, 1.0); - Assert.AreEqual(expected.z, result.z); - } - - } -} diff --git a/EqmodNStarAlignment.Tests/Legacy.cs b/EqmodNStarAlignment.Tests/Legacy.cs deleted file mode 100644 index 6199e517..00000000 --- a/EqmodNStarAlignment.Tests/Legacy.cs +++ /dev/null @@ -1,92 +0,0 @@ -/* -MIT License - -Copyright (c) 2017 Phil Crompton - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Portions - Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace EqmodNStarAlignment.Tests -{ - - public static class Legacy - { - #region Astro32.dll ... - /// - /// ================= - /// LIBRARY FUNCTIONS - /// ================= - /// - /// NOTES: - /// - /// (1) For whatever reason, the authors of the original C functions chose - /// to pass back and forth via parameters only for most functions. - /// - /// (2) The descriptive comments below were lifted straight out of the C - /// functions. Some variables are listed with the C dereferening ///*///. - /// Note that these are passed ByRef in the declarations, then forget - /// about the ///*///. - /// - /// (3) Modified Julian Dates (number of days elapsed since 1900 jan 0.5,) - /// are used for most times. Several functions are provided for converting - /// between mjd and other time systems (C runtime, VB, Win32). - /// - /// - /// given latitude (n+, radians), lat, altitude (up+, radians), alt, and - /// azimuth (angle around to the east from north+, radians), - /// return hour angle (radians), ha, and declination (radians), dec. - /// - [DllImport("astro32.dll")] - public static extern void aa_hadec(double lat, double alt, double az, ref double ha, ref double dec); - // Declare Sub aa_hadec Lib "astro32" (ByVal lat As Double, ByVal Alt As Double, ByVal Az As Double, ByRef ha As Double, ByRef DEC As Double) - - /// - /// given latitude (n+, radians), lat, hour angle (radians), ha, and declination - /// (radians), dec, return altitude (up+, radians), alt, and azimuth (angle - /// round to the east from north+, radians), - /// - - [DllImport("astro32.dll")] - public static extern void hadec_aa(double lat, double ha, double dec, ref double alt, ref double az); - // Declare Sub hadec_aa Lib "astro32" (ByVal lat As Double, ByVal ha As Double, ByVal DEC As Double, ByRef Alt As Double, ByRef Az As Double) - - #endregion - } -} diff --git a/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs b/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 6f214630..00000000 --- a/EqmodNStarAlignment.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,20 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("EqmocNStarAlignment.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("EqmocNStarAlignment.Tests")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("55fbcfca-0220-43e2-82d0-dd9253a1d254")] - -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/EqmodNStarAlignment.Tests/RangeTests.cs b/EqmodNStarAlignment.Tests/RangeTests.cs deleted file mode 100644 index bb2661a1..00000000 --- a/EqmodNStarAlignment.Tests/RangeTests.cs +++ /dev/null @@ -1,21 +0,0 @@ -using EqmodNStarAlignment.Utilities; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; - -namespace EqmodNStarAlignment.Tests -{ - [TestClass] - public class RangeTests - { - [DataRow(3d, 3d, 6d)] - [DataRow(3d, 9d, 6d)] - [DataRow(0d, 0d, 6d)] - [DataRow(3d, -3d, 6d)] - [DataRow(3d, -9d, 6d)] - [DataTestMethod] - public void TestRangeValue(double expectedValue, double testValue, double range) - { - Assert.AreEqual(expectedValue, Range.ZeroToValue(testValue, range)); - } - } -} diff --git a/EqmodNStarAlignment.Tests/astro32.dll b/EqmodNStarAlignment.Tests/astro32.dll deleted file mode 100644 index 61780dcd54fccd7d30898f8202942f366464fb83..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 28672 zcmeHv4|vnnx&KL;loXOSK%yzM7+vZrl$ti_f10G)LUok2r4-OgDYT_!rR~}T0YQtQ zUP@rr4L9}bMBOHH-i6GH1A)DG_g6QBb*s3UsMQL+C?>YIl1^Kz(eV*U% zcc0($Na=C#_qV^!qB{DTKSi_Wqh7yu zzii>_*Ot}Qw;G#Un%1;btuwB!YHVzB8dudATU?FC`bJ~^_ZJ)2HC5LnYc!KhA<@o< z?pkKPpr0baA5PDll7e#Oe_k`i%G0S+QhB{@${eIej;p6wkX9d0n399^%iwfQ|CfQO zJT0wXT}QJ1SC$tSFt$*pWGTyMIV75sEc)6hvPi~^z=W_P$;fK~W&q_V41GPW|grMk*l#n?+KU?G#!Qaa&rz)Q)3jP+_z0R*R`bi(6c%$wZO z+Oirr-qvDdNH?Vu9tX*5scC2e;b+wLl>nlnbi(6c?4}9Da5n6Lum{2(2zwyxfv^X{ z9te9N?18Wc!X5~F;J@JkPrk|MS!mLF%1r8VkJDr%d8WoGEZ92IhmC4D^#0UBD5~m~So#Ba8j9)Pg0RA@`|a z_s~3lfyx(ezL{wkmoMd}ZHnUd=~5t3?My$^d!>Dg(>@i9PpxAa}+tB z^6)o_;IkySD6zQ2-yhVgi2(iSOCUSky{f>-OvYlmbOi=<UA=m`ZdC?p+&WaGtjCj-1M`ln9e472#&3oTyH!fjTMbDMe28yyR`nH}z7 zxn#~BQc8v?xnX56EZ<~4(HB7>!p-n$9s&&+b)xS?_rwqZU!pI*6SX2b$dE)|0wD&x z2n5Y`(F0pFa+RNSZ!odkVCkBEu_84UwJ#-782Kd&Qw(ZFa{ivL8%h zta1g-EIK~3C@Fksa6pL;j?9 zdM~Vzd{l_=Mv?cxK4ivR;#2OWB9FfQZWxdl8VFM7_!>-!q60{~O3Za!&Yp>KP={eb z-Re_5G_eBwKy?y|jMr?RSP4{ONcWk*udc@Y%zNLnMcXlH+(bz56zPN!T7N8g!>4S6 zoIopBP&8thLeb+gbVN!mp33nF%|x~kWF3>@SQvQ!D%@_qh|XmXe|Z7@sBS;jq1~d0 zc(X&xhl~iDvA26jjWv#8WmD{ed&`^@VvS81FWQN z8&XVO{0f8JLo_&O%V8)lE)gSy+`d*%0~=L&#i^DMb;Hq1gw#!t=w6&i3qoT65-RqiBn-%HO zzq>%;enr=R z-Ey}#>QV>nFj13hqI=D?x;*Re6LFgcKWgXapdM|lmH z;{GGZy*|*>{}%*Jg=rb`-TkkhID`C3)VzwcuD{QJ+~1GV5z^WJ8n0~*m5y+}4e)ip zXN%6`qGN*!hT{mbfF>hTi6^GiQ?3ZjNX4E=I^b-@S`T3=^uz|F6y42WQk5*_v71Qc za`%vd3)g}o$+y$A4NgLK9x69;vV7#6oP;7j38jWmef3y<1#&o&6q7=ns6?R9cAm~t zN(y!VEV1N_^^-KfAxq)Y8_-XDTE1(EUzvy?=s!bCOK4;&9S9d}_YyKgsad3&M5I2Y zk=~)u=`4b-euNMN`jxz7!2Ez2M-8+<#7>+rpkL?HZ-)pewC8e@G;Kg3$Umdmm_NW&I`ug8T0QUF9F~71INc5hv4k;1S0c9n}VK0aj9#afpTU$(dWg*oZ5xW{F znjkdPgn=7&k{p90vMgIUWzC##v-LF^(@iy(6!LeDxldNX7|63O*J$j zvS=bR0{B9N_%-n02ZDC5Snue?1$>6pjkqBMt;5{b|3Uu+7;oUgY`~HQK{U`iAvm-N zaXte=92SijkbE4*N#k%r|EdRq+P&7{?TMKNIGGa zBiE~S4=194k+5Zw+gpvS0W-4#3%>~-XQe^C33A-MisFC)%Z}Jq2X;}mH<53pcpGug z0|OWgU}ON?jL1>ou%^Pot$we84k#z#L|;Nb-cUQ<6wWWr7id*rA595#;=;~}_8Gio zz;8GY2lH(`3OQqifEQa6S~fM!5RH|>SW=F?8S+apK6H?z3lx2Yoi0Kdq70?9gzf}8 z`q=;qBbJ{`2l&)$Sqa|&ScNDdWK6~lf<+}(go&F^v;cM?V%2aP|3wPi$k1qPm}uYW zQ=a9GR*m}$y0QNxwAil(@+RZ>J}$H*a2vc&V)*`7h(Qng5{ALEd;+Biv68^-Z_<<3 zl~<+@%mI13*E#J8EA^MgOmF6y8qsseqvr+rB|TIU>Rk#ixJrR7ekQRL8ZF1#`(hsK z@$|TR)#EJg%_dcZYbt!A@MsdTs&%Mv%u+G9{`a(>9BvOfr+D-ZlF_0Vob&|GnFH0R z+!2j-Yq#~emSSUg6=F&4(UXYwU}eYDmIMc3$ zQFBV_j9@|d&Vvefug>BH`wDP_89Zvw%X8k|q1vvNJD}+N#9Ho9^bbzzv?Ex&MC`P}5aC8oE?J1NNV6RVM#QIEN3_wno?79wxku(XuirYd3>y?z zrRUI#h!HwMmKN7-0Jj*wl`HPJ9d{Lr>zXB$I)nlP{lrNyR7O{~bO%Fs817!s7%XEOA!jr1 zyLc@}(VB8S4#jLK+q-ps?4vLxnpC9F8PkVczAJZ`E}FWQMo6)7(F<&-+p3ynHBhvEjyt%H(muPU$_vGeNM`9?J)cp+(;bTmV`zI%Dg=kdA zVL>xvg0k+2+~#%8oIfwydDXldozv#!IHTt!IVaDX>x`r-*XcIfm{KxXFD|VL6u5<4SA$8t%&Z%xNBsYWv#gyb0MjxQF7m5cK|vi%Hmqypn$)j(W;+ zeu3rKV0_MJxN9p?@tGOB4YElM16+zA4c#JD-nMr;ic~S}t7y?FGPr{>mpuzKG532R z#C<^))4l^4?ugJ#!^eJ1`<^khg9q37-n^I{9w0s4b9!R7T|}-hX4~(1(tZO>g4j4` z6iLEV<~N{dbVj3S4%A>~#I)8SLvu`6rnY@0WM>AxM>R`y9rBRRbudZpdh8qKxby;* zIcAE-MJ*Z|PJz3I#MH8c#u=^~Fk9dZB);$~DGdw-f>{3eH)c9vDVdfSI0C~Z(~Q^; zko{(y&HOWjtxnoDX9k|)WV#O7m1NvUmDC8ZkPOl2<_VI~Xf8REOCFOkHoHjox&0V% z;yg`<4(Y;eA9*W&FV<4Dm!>&Yhn^^(^5F&ZaNaJ2Ur?drTe-EY81pfms0{%p+(KUp zfDHG=C$A{Kn9JXDiF~4b>Xalufhy@r&k#~j?w=Kig=o5NEQW5n&Xc}+;H~2N`2AvF z4a8%3(=A7)1A7O$#!(3y5!OC_t0&zUG(#4)7IW)Fs$3aLmmv)eS@f>IKk(=vUmg|G zMlhIQfUsbKmcNa7lb^5=iOy2)gYkDK2Q`#>G}WlXeCCPj&^!->%U;(81B3dNz_)vs zKXrhR3X6BJ)@@`@P^nIVZ~5vNUQg{uG4LVLbE(Uh59UHg7AHd=n>`w$DBtzNi#cao zrg@^<`<#=4Z}MvQ$BMxZF_xE+{sfZCmakYVTZUT=EG~;Zci;;u7hMo&+t0hA+__{e z8@%2Q3)6js|&Sx14|r3OA@Y4PH~ zr??_$KTl#JT-OuPNkVvC5!V)|-CNYmIaQLa;?9l#981mpu20i=iS z80fM=q*0;tg56`1Z@N!^&c^9>{@fwxz4j1asC?4Cgg>W4_@klpY$(kabZvPd`e;Wj zf0jEe^h{sw(EWD7`wS)Y zyWyrhhG*xFJf5;+KXX)-m40{6!#2V9xAh`zcuu7I9up};K=WsID4iqHXCHIe<0|f2 z_0pbDJ2pA4{``bN&I0zQcfWIM;J0T&_$0@xKmNC&9iM$-PuX0(!u`TU?k~qJ7rk6; z=yf#zL+=eGZ|pf-5D@+}d?EB;9w3rVv?J@W(kJJ?_kjIS&qL++{Phmo)`A#o)Tv+F z9(kCa7wvz|z4|}}Wu-K%H# zez{QCqy3@7G1&5y>9;z2P3zpu((a@7$L{;1@ z8t3ATt=KDH`Gv$eXpQ&QNcn>YI1c$17j(y^5$ErRyVb>CGy&arluD5 zDXXk?HZ`!fWtGlNtu;=@cFQW8UCx@u^(>R9Yw=e?>=F68A2>-I%avC-o9Y=mDi`Hr z;6ufxrp6lPWtG*f&QKmQ4>@CvLSOq~Z$Xi?SM@hB# z3mlS&^heOU+PSg0hUsOM^{pbys#s;^x>c2{T`iUCsx~lIw7C4{(lXJS74q7a8rT#A z`o?;vv!-PodqBRfs)7IY%44jus(P)f)md3vUB6!HJn3(ZsxugU8N_k`iGc0sV`n<% zOW@zZU@>-5!Y%cy32cW%9l(kc#gYw@&3OEaJ;83ImGy{(E0}^B|RA0GhAW99l)3=+)rN;Tu|3~A+92J$(gx@x0Ho9+~8^E#f^weZB%Siga1gs{qu zHB~LFvFXmrhE^v}$;L*Pv$E!glvFwEn;Kcus)qU>y6T-9SxZ&pni|$pQ`=It+R0iP zt6}cyrp9X4y1KCvetOhfb4d#}pBYO~&;e_l5NxfODQ73|oSZnhH)>_nMb$$ptLo^a zhDoYPzle0;2QVA((JA*S_9+(P6NsSCwtw;wR1@FC`|TgnaQR0E&Ep@kWc=e(PW(7v z>*b$cMEj_%2~?E%JYgL#RpgX^ef&_^uo>`E1ZgQg-LNS!W;3Uh>8ef z#K-aj^4;?F@@4XTdA8ilKiSAHlCP3C0KWsZd*#o`UzQ)0AD5q!e=HxC%Om6wYJ7AN z(Gj1?UzE4WZ!~+pmDYhyy zl`ksuBKJocC$&sEGwDWEzUud?ZdFh2Rv`)&N8OI{@~DESWloOu)CWtQpeGQ`OPR;K$ zUufn>KOX%>baBjcF?#Ji+E2ArQ+uagKdp1x7t<=IADli-SEbvhi_mB5oAi(B-_Vch z)34fc)hkySu5P^g;MLO&<%Wk0uNpovM8(dEofrFj?BUp?8J+y|`HW>V58z|Oxr{&C z4|&UO%VlM^G3@%|0JB0co-5wean^vCQ{n_cC=V_N^J%4!p2VGy?z4n0fC)>OJbc_04&)vGbM|%%n{pZ1f zJijS&>x1suUf|_({^dS9`7SG1~gruW?oT!4M3WdE%0jWhF5 ze)75dZ|g3li<>v&L;Bl7_Z;FpDjFqcqe1aMEMz#*;5H8>@urd-ry%Tx?cvWYAjw}s>pPUw||WRT5* zR`3b?1)Z=?(uUuwaLIyGNFhzcFUjCV{t|5!7LM1F4xv$S5$Qy)2tN{5Z45IzP;F}Oea<2jIFbpO-G=e-6%IuLozc<3TNp2Uk3_ydTuy z3NnbF)13!)ICw5N2{|QvM*bZMUV#2#KqQ1jqD(dsj`Cz1#R8>d8;t=pzQoDE|{0e&@?18WcuH*q3|G|NQv9?QV#e9qT=^OYcO!9>wURjJanX5;?we zO2+qA$(+{Ab&x-toURel8YWnAxoi{oWo#j6*KkU*z8PL1tJbhOND<#%PNXSAExx(} z&pM<6LtJFttBp??K0^$_Wn`iM%x6PMbM3`q_6u#o?XIsbZ4Qwwf_r>T#tFR5=r z*~R@o(Z5MNiim%_{&H^#UrD+aqpdZNQ_n4(s4JiQr5yN{u@;O+8TQD~#hCB}^?w7m zcf3!caDxMa@Duhx*aKk?ggp@UK-dFe4}?7s_CVMJVGsPzc|eQb`^y+hHQ#K$&-}3Y zm*(G?UoamsA2GjamZ!{0NltO3d@rRWWogPCDXUZNOu0K{cgmiWU!}Z|(vxyH7m#13uC>@&W?g2ju-i1dnE0*X@5>T zmNu03b($hwlRiB?Ha#IdIsNAJh3QMuE7NPz8`C$W-<$49e=z;Y^nK|^(g)H%O=lTX zGtx7PGL~nIX3WY=%6uksU*^%wg;}Lpw`Wylth=O7FbFwotB?k1}yJc&RZ^8jMmxkt5?0 ztbXg4R#}=c&7QV6?Y6X^rahnbcG`PspQT+)GsAmT>D$tOmwr5bW=3j;J)<o2?Eh{0*4lnM=+MRVeD?Pg< zdvo@&?7zcPvvS&V9?j9s`|iBR-0O19xoNrf+>+ed+ zn`DczU2VI@mSDTdR%lyftFTqu*4kXQdu=;x57{2GJ!yLyUh1;-*-qF#w4Jq0vzzQ~ s_D7|Qp#Qm%64o5{K-dFe4}?7s_CVMJVGo2o5cWXW17Q#Rf9-+)0&o2?TL1t6 diff --git a/EqmodNStarAlignment/DataTypes/AxisPosition.cs b/EqmodNStarAlignment/DataTypes/AxisPosition.cs deleted file mode 100644 index ca9cf786..00000000 --- a/EqmodNStarAlignment/DataTypes/AxisPosition.cs +++ /dev/null @@ -1,184 +0,0 @@ -/* -BSD 2-Clause License - -Copyright (c) 2019, LunaticSoftware.org, Email: phil@lunaticsoftware.org -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -using System; -using Newtonsoft.Json; - -namespace EqmodNStarAlignment.DataTypes -{ - /// - /// A structure to represent telescope mount axis positions - /// - public struct AxisPosition - { - private double _ra; - private double _dec; - - [JsonProperty] - public double RA - { - get => _ra; - set => _ra = value; - } - - [JsonProperty] - public double Dec - { - get => _dec; - set => _dec = value; - } - - - public AxisPosition(double[] axes) : this(axes[0], axes[1]) - { } - - /// - /// Create a new axis position - /// - /// RA axis encoder value - /// Dec axis encoder value - public AxisPosition(double ra, double dec) - { - _ra = ra; - _dec = dec; - } - - - public AxisPosition(string axisPositions) - { - var positions = axisPositions.Split('|'); - try - { - _ra = double.Parse(positions[0]); - _dec = double.Parse(positions[1]); - } - catch - { - throw new ArgumentException("Badly formed axis position string"); - } - } - - - public static implicit operator double[](AxisPosition axes) - { - return new[] { axes[0], axes[1] }; - } - - public static implicit operator AxisPosition(double[] axes) - { - return new AxisPosition(axes); - } - - /// - /// The axis position in degrees - /// - /// - /// - public double this[int index] - { - get - { - if (index < 0 || index > 2) - { - throw new ArgumentOutOfRangeException(); - } - return (index == 0 ? _ra : _dec); - } - set - { - if (index < 0 || index > 2) - { - throw new ArgumentOutOfRangeException(); - } - if (index == 0) - { - _ra = value; - } - else - { - _dec = value; - } - } - } - - /// - /// Compares the two specified sets of Axis positions. - /// - public static bool operator ==(AxisPosition pos1, AxisPosition pos2) - { - return (pos1.RA == pos2.RA && pos1.Dec == pos2.Dec); - } - - public static bool operator !=(AxisPosition pos1, AxisPosition pos2) - { - return !(pos1 == pos2); - } - - public static AxisPosition operator -(AxisPosition pos1, AxisPosition pos2) - { - return new AxisPosition(pos1.RA - pos2.RA, pos1.Dec - pos2.Dec); - } - - public static AxisPosition operator +(AxisPosition pos1, AxisPosition pos2) - { - return new AxisPosition(pos1.RA + pos2.RA, pos1.Dec + pos2.Dec); - } - - public override int GetHashCode() - { - unchecked // Overflow is fine, just wrap - { - var hash = 17; - // Suitable nullity checks etc, of course :) - hash = hash * 23 + _ra.GetHashCode(); - hash = hash * 23 + _dec.GetHashCode(); - return hash; - } - } - - public override bool Equals(object obj) - { - return (obj is AxisPosition position - && this == position); - } - - - public bool Equals(AxisPosition obj, double toleranceDegrees) - { - var deltaRa = Math.Abs(obj.RA - RA); - deltaRa = (deltaRa + 180) % 360 - 180; - var deltaDec = Math.Abs(obj.Dec - Dec); - deltaDec = (deltaDec + 180) % 360 - 180; - return (deltaRa <= toleranceDegrees - && deltaDec <= toleranceDegrees); - } - - - - } -} diff --git a/EqmodNStarAlignment/DataTypes/EncoderPosition.cs b/EqmodNStarAlignment/DataTypes/EncoderPosition.cs deleted file mode 100644 index 586fbc63..00000000 --- a/EqmodNStarAlignment/DataTypes/EncoderPosition.cs +++ /dev/null @@ -1,185 +0,0 @@ -/* -BSD 2-Clause License - -Copyright (c) 2019, LunaticSoftware.org, Email: phil@lunaticsoftware.org -All rights reserved. - -Redistribution and use in source and binary forms, with or without -modification, are permitted provided that the following conditions are met: - -* Redistributions of source code must retain the above copyright notice, this - list of conditions and the following disclaimer. - -* Redistributions in binary form must reproduce the above copyright notice, - this list of conditions and the following disclaimer in the documentation - and/or other materials provided with the distribution. - -THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" -AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE -DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE -FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR -SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER -CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -*/ - -using System; -using Newtonsoft.Json; - -namespace EqmodNStarAlignment.DataTypes -{ - /// - /// A structure to represent telescope mount axis positions - /// - public struct EncoderPosition - { - private long _ra; - private long _dec; - - [JsonProperty] - public long RA - { - get => _ra; - set => _ra = value; - } - - [JsonProperty] - public long Dec - { - get => _dec; - set => _dec = value; - } - - - public EncoderPosition(double[] axes) : this((long)Math.Round(axes[0],0), (long)Math.Round(axes[1],0)) - { } - - public EncoderPosition(long[] axes) : this(axes[0], axes[1]) - { } - - /// - /// Create a new axis position - /// - /// RA axis encoder value - /// Dec axis encoder value - public EncoderPosition(long ra, long dec) - { - _ra = ra; - _dec = dec; - } - - - public EncoderPosition(string axisPositions) - { - var positions = axisPositions.Split('|'); - try - { - _ra = long.Parse(positions[0]); - _dec = long.Parse(positions[1]); - } - catch - { - throw new ArgumentException("Badly formed axis position string"); - } - } - - - public static implicit operator long[](EncoderPosition axes) - { - return new[] { axes[0], axes[1] }; - } - - public static implicit operator EncoderPosition(long[] axes) - { - return new EncoderPosition(axes); - } - - /// - /// The axis position in degrees - /// - /// - /// - public long this[long index] - { - get - { - if (index < 0 || index > 2) - { - throw new ArgumentOutOfRangeException(); - } - return (index == 0 ? _ra : _dec); - } - set - { - if (index < 0 || index > 2) - { - throw new ArgumentOutOfRangeException(); - } - if (index == 0) - { - _ra = value; - } - else - { - _dec = value; - } - } - } - - /// - /// Compares the two specified sets of Axis positions. - /// - public static bool operator ==(EncoderPosition pos1, EncoderPosition pos2) - { - return (pos1.RA == pos2.RA && pos1.Dec == pos2.Dec); - } - - public static bool operator !=(EncoderPosition pos1, EncoderPosition pos2) - { - return !(pos1 == pos2); - } - - public static EncoderPosition operator -(EncoderPosition pos1, EncoderPosition pos2) - { - return new EncoderPosition(pos1.RA - pos2.RA, pos1.Dec - pos2.Dec); - } - - public static EncoderPosition operator +(EncoderPosition pos1, EncoderPosition pos2) - { - return new EncoderPosition(pos1.RA + pos2.RA, pos1.Dec + pos2.Dec); - } - - public override int GetHashCode() - { - unchecked // Overflow is fine, just wrap - { - var hash = 17; - // Suitable nullity checks etc, of course :) - hash = hash * 23 + _ra.GetHashCode(); - hash = hash * 23 + _dec.GetHashCode(); - return hash; - } - } - - public override bool Equals(object obj) - { - return (obj is EncoderPosition position - && this == position); - } - - - public bool Equals(EncoderPosition obj, double toleranceDegrees) - { - var deltaRa = Math.Abs(obj.RA - RA); - var deltaDec = Math.Abs(obj.Dec - Dec); - return (deltaRa <= toleranceDegrees - && deltaDec <= toleranceDegrees); - } - - - - } -} diff --git a/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs b/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs deleted file mode 100644 index 72be9563..00000000 --- a/EqmodNStarAlignment/DataTypes/EqascomDataTypes.cs +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -// based on original work -// Copyright © 2006 Raymund Sarmiento -// -// Permission is hereby granted to use this Software for any purpose -// including combining with commercial products, creating derivative -// works, and redistribution of source or binary code, without -// limitation or consideration. Any redistributed copies of this -// Software must include the above Copyright Notice. -// -// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO -// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS -// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -// -// DISCLAIMER: - -// You can use the information on this site COMPLETELY AT YOUR OWN RISK. -// The modification steps and other information on this site is provided -// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, -// implied or otherwise, including without limitation any warranty of -// merchantability or fitness for any particular or intended purpose. -// In no event the author will be liable for any direct, indirect, -// punitive, special, incidental or consequential damages or loss of any -// kind whether or not the author has been advised of the possibility -// of such loss. -//--------------------------------------------------------------------- - -using System; -using System.Collections.Generic; -using System.Text; - -namespace EqmodNStarAlignment.DataTypes -{ - public struct Coord - { - public double x; //x = X Coordinate - public double y; //y = Y Coordinate - public double z; - } - - //[Serializable] - //public struct Tdatholder - //{ - // public double dat; - // public short idx; - // public Coord cc; // cartesian coordinate - // public static Tdatholder CreateInstance() - // { - // Tdatholder result = new Tdatholder(); - // return result; - // } - //} - - //[Serializable] - //public struct THolder - //{ - // public double a; - // public double b; - // public double c; - //} - - - public struct Matrix - { - public double[,] Element; //2D array of elements - public static Matrix CreateInstance() - { - Matrix result = new Matrix(); - result.Element = new double[3, 3]; - return result; - } - } - - //[Serializable] - //public struct Matrix2 - //{ - // public double[,] Element; //2D array of elements - // public static Matrix2 CreateInstance() - // { - // Matrix2 result = new Matrix2(); - // result.Element = new double[4, 4]; - // return result; - // } - //} - - //public struct Coordt - //{ - // public double x; //x = X Coordinate - // public double y; //y = Y Coordinate - // public double z; - // public short f; - //} - - public struct CartesCoord - { - public double x; //x = X Coordinate - public double y; //y = Y Coordinate - public double z; //z = Z coordinate - public double r; // Radius Sign - public double ra; // Radius Alpha - - public CartesCoord(double xValue, double yValue, double zValue, double rValue, double raValue) - { - x = xValue; - y = yValue; - z = zValue; - r = rValue; - ra = raValue; - } - } - - public struct SphericalCoord - { - public double x; //x = X Coordinate - public double y; //y = Y Coordinate - public double r; //r = RA Range Flag - - public SphericalCoord(double xValue, double yValue, double rValue) - { - x = xValue; - y = yValue; - r = rValue; - } - } - - - public struct TriangleCoord - { - public double i; // Offset 1 - public double j; // Offset 2 - public double k; // offset 3 - - } -} diff --git a/EqmodNStarAlignment/DataTypes/MapResult.cs b/EqmodNStarAlignment/DataTypes/MapResult.cs deleted file mode 100644 index e21fb418..00000000 --- a/EqmodNStarAlignment/DataTypes/MapResult.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; - -namespace EqmodNStarAlignment.DataTypes -{ - public class MapResult - { - public EncoderPosition EncoderPosition { get; set;} - - public bool InTriangle { get;set;} = false; - } -} diff --git a/EqmodNStarAlignment/EqmodNStarAlignment.csproj b/EqmodNStarAlignment/EqmodNStarAlignment.csproj deleted file mode 100644 index 596d685d..00000000 --- a/EqmodNStarAlignment/EqmodNStarAlignment.csproj +++ /dev/null @@ -1,88 +0,0 @@ - - - - - Debug - AnyCPU - {2B12E1E9-A2BB-4FA8-9E49-4888B2874233} - Library - Properties - EqmodNStarAlignment - EqmodNStarAlignment - v4.7.2 - 512 - true - - - - true - full - false - ..\Builds\Debug\ - TRACE - prompt - 4 - 1701;1702 - x86 - ;NU1605 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - true - - - Resources\ASCOM.snk - - - false - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - {c2bc2641-3b32-4940-b124-61adec0dac28} - GS.Principles - - - - - 13.0.1 - - - - \ No newline at end of file diff --git a/EqmodNStarAlignment/Model/AlignmentModel.cs b/EqmodNStarAlignment/Model/AlignmentModel.cs deleted file mode 100644 index d9355d2a..00000000 --- a/EqmodNStarAlignment/Model/AlignmentModel.cs +++ /dev/null @@ -1,450 +0,0 @@ -using EqmodNStarAlignment.Utilities; -using EqmodNStarAlignment.DataTypes; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.IO; -using System.Reflection; -using System.Text; -using System.Threading; -using System.Linq; - -namespace EqmodNStarAlignment.Model -{ - public enum NotificationType - { - Information, - Data, - Warning, - Error - } - - [TypeConverter(typeof(EnumTypeConverter))] - public enum PierSideEnum - { - [Description("Unknown")] - Unknown = -1, - [Description("East")] - EastLookingWest, - [Description("West")] - WestLookingEast, - } - - [TypeConverter(typeof(EnumTypeConverter))] - public enum ActivePointsEnum - { - [Description("All")] - All, - [Description("Pierside Only")] - PierSide, - [Description("Local Quadrant")] - LocalQuadrant - } - - [TypeConverter(typeof(EnumTypeConverter))] - public enum ThreePointAlgorithmEnum - { - [Description("Best Centre")] - BestCentre, - [Description("Closest Points")] - ClosestPoints - } - - [TypeConverter(typeof(EnumTypeConverter))] - public enum AlignmentModeEnum - { - [Description("N-Star + Nearest")] - NStarPlusNearest, - [Description("Nearest")] - Nearest - } - - - public enum HemisphereEnum - { - Northern, - Southern - } - - public class NotificationEventArgs : EventArgs - { - public NotificationType NotificationType { get; set; } - public string Method { get; set; } - - public int Thread { get; set; } - public string Message { get; set; } - - - public NotificationEventArgs(NotificationType notificationType, string method, string message) - { - this.NotificationType = notificationType; - this.Method = method; - this.Message = message; - this.Thread = System.Threading.Thread.CurrentThread.ManagedThreadId; - } - } - - public partial class AlignmentModel - { - #region Events ... - - public event EventHandler Notification = delegate { }; - - private void RaiseNotification(NotificationType notificationType, string method, string message) - { - Volatile.Read(ref Notification).Invoke(this, new NotificationEventArgs(notificationType, method, message)); - } - - #endregion - - #region variables ... - private readonly List _exceptionMessages = new List(); - - private bool _threeStarEnabled = false; - #endregion - - #region Properties ... - public bool IsAlignmentOn { get; set; } - - private double _proximityLimit = 0.5; - /// - /// How close existing alignment points have to be to the new alignment point - /// before they are removed and replaced with the new one (degrees) - /// - public double ProximityLimit - { - get => _proximityLimit; - set - { - if (_proximityLimit == value) return; - _proximityLimit = value; - RefreshProximitySteps(); - } - } - - private void RefreshProximitySteps() - { - _proximityStepsRa = (long)this.ProximityLimit * (this.StepsPerRev.RA / 360); - _proximityStepsDec = (long)this.ProximityLimit * (this.StepsPerRev.Dec / 360); - } - - private long _proximityStepsRa = 12533; /// Approimately 0.5 degrees (if steps per rev = 9024000) - private long _proximityStepsDec = 12533; /// Approimately 0.5 degrees (if steps per rev = 9024000) - - private double _siteLongitude; - public double SiteLongitude - { - get => _siteLongitude; - set - { - if (_siteLongitude == value) return; - _siteLongitude = value; - SendToMatrix(); - } - } - - private double _siteLatitude; - public double SiteLatitude - { - get => _siteLatitude; - set - { - if (_siteLatitude == value) return; - _siteLatitude = value; - Hemisphere = (_siteLatitude >= 0 ? HemisphereEnum.Northern : HemisphereEnum.Southern); - SendToMatrix(); // Refresh the matrices as these are affected by the site latitude - } - } - - public HemisphereEnum Hemisphere { get; private set; } = HemisphereEnum.Northern; - - public double SiteElevation { get; set; } - - public bool CheckLocalPier { get; set; } - - public AlignmentModeEnum AlignmentMode { get; set; } = AlignmentModeEnum.NStarPlusNearest; - - public ThreePointAlgorithmEnum ThreePointAlgorithm { get; set; } = ThreePointAlgorithmEnum.BestCentre; - - public EncoderPosition HomeEncoder { get; private set; } - - private long[] _reportedHomePosition = new long[]{ 0, 0 }; - - public void SetHomePosition(long RAEncoder, long decEncoder) - { - _reportedHomePosition[0] = RAEncoder; - _reportedHomePosition[1] = decEncoder; - // EQMod expects the RA Home position to have a step value of 0x800000 (0 hours) - // and the Dec Home position to be 0xA26C80 (90 degrees) - - // Set the home position to the internal zero position for RA and internal zero + 90 degrees for Dec - HomeEncoder = new EncoderPosition(_homeZeroPosition, _homeZeroPosition + this.StepsPerRev.Dec / 4); // Set the dec at 90 degrees. - - // Calculate the correction for mapping mount encoder positions to internal encoder positions - EncoderMappingOffset = new EncoderPosition(HomeEncoder.RA - RAEncoder, HomeEncoder.Dec - decEncoder); - // To convert: Mount = Internal - EncoderMappingOffset - // Internal = Mount + EncoderMappingOffset - SendToMatrix(); - } - - private EncoderPosition _stepsPerRev; - public EncoderPosition StepsPerRev - { - get => _stepsPerRev; - set - { - if (_stepsPerRev == value) - { - return; - } - _stepsPerRev = value; - SetHomePosition(_reportedHomePosition[0], _reportedHomePosition[1]); - } - } - - public ActivePointsEnum ActivePoints { get; set; } - - public AlignmentPointCollection AlignmentPoints { get; } = new AlignmentPointCollection(); - - public AlignmentPoint SelectedAlignmentPoint { get; private set; } - - public DateTime? LastAccessDateTime { get; private set; } - - public int NStarMaxCombinationCount { get; set; } = 50; - - // String builder for building more detailed messages. - private readonly StringBuilder _stringBuilder = new StringBuilder(); - - private readonly object _accessLock = new object(); - - private readonly string _configFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\Points.config"); - - private readonly string _timeStampFile = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), @"EqmodNStarAlignment\TimeStamp.config"); - - private const long _homeZeroPosition = 0x800000; // As per EQMOD - - public EncoderPosition EncoderMappingOffset { get; private set; } // Mapping from Mount encoder positions to internal encoder positions - - /// - /// RA/Dec encoder adjustments for when there is only one star/point logged. - /// - private EncoderPosition _oneStarAdjustment = new EncoderPosition(0, 0); - - #endregion - - #region Constructor ... - public AlignmentModel(double siteLatitude, double siteLongitude, double siteElevation) - { - SiteLatitude = siteLatitude; - SiteLongitude = siteLongitude; - SiteElevation = siteElevation; - RefreshProximitySteps(); - - } - #endregion - - public void Connect(bool clearPointsOnStartup = false) - { - try - { - // Load the last access time property. - ReadLastAccessTime(); - // Re-load alignment points unless clear points on start up is specified - // In case of lost connections or restarts the points are only cleared if the last time the model was accessed is more than an hour ago. - if (!clearPointsOnStartup || (LastAccessDateTime != null && - (LastAccessDateTime.Value > DateTime.Now - new TimeSpan(1, 0, 0)))) - { - LoadAlignmentPoints(); - } - } - catch (Exception ex) - { - LogException(ex, true); - } - } - - #region Alignment point management ... - public bool SyncToRaDec(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) - { - try - { - lock (_accessLock) - { - - // AlignmentPoints.Add(new AlignmentPoint(encoder, origRaDec, target, syncTime)); - if (EQ_NPointAppend(new AlignmentPoint(encoder + this.EncoderMappingOffset, origRaDec, target + this.EncoderMappingOffset, syncTime))) - { - - } - //_currentChecksum = int.MinValue; // Reset checksum so that offsets are recalculated - - //OneStarAdjustment[0] = observedAxes[0] - mountAxes[0]; - //OneStarAdjustment[1] = observedAxes[1] - mountAxes[1]; - SaveAlignmentPoints(); - - return true; - } - } - catch (Exception ex) - { - LogException(ex, true); - } - return false; - } - - - public bool RemoveAlignmentPoint(AlignmentPoint pointToDelete) - { - try - { - bool result = AlignmentPoints.Remove(pointToDelete); - if (result) - { - SaveAlignmentPoints(); - } - - return result; - } - catch (Exception ex) - { - LogException(ex, true); - return false; - } - } - - - public void SaveAlignmentPoints(string filename) - { - File.WriteAllText(filename, JsonConvert.SerializeObject(AlignmentPoints, Formatting.Indented)); - } - - private void SaveAlignmentPoints() - { - var dir = Path.GetDirectoryName(_configFile); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - SaveAlignmentPoints(_configFile); - ReportAlignmentPoints(); - } - - - public void LoadAlignmentPoints(string filename) - { - AlignmentPoints.Clear(); - using (var file = File.OpenText(filename)) - { - var serializer = new JsonSerializer(); - try - { - var loaded = - (AlignmentPointCollection)serializer.Deserialize(file, typeof(AlignmentPointCollection)); - if (loaded != null) - { - foreach (var alignmentPoint in loaded) - { - AlignmentPoints.Add(alignmentPoint); - _oneStarAdjustment = alignmentPoint.Delta; - } - SendToMatrix(); // Updates the cartesean values. - } - } - catch (Exception ex) - { - LogException(ex); - } - } - - } - - private void LoadAlignmentPoints() - { - var dir = Path.GetDirectoryName(_configFile); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - if (File.Exists(_configFile)) - { - LoadAlignmentPoints(_configFile); - } - ReportAlignmentPoints(); - } - - public void ClearAlignmentPoints() - { - try - { - AlignmentPoints.Clear(); - SaveAlignmentPoints(); - } - catch (Exception ex) - { - LogException(ex, true); - } - } - - #endregion - - - #region Access time related ... - private void WriteLastAccessTime() - { - LastAccessDateTime = DateTime.Now; - var dir = Path.GetDirectoryName(_timeStampFile); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - File.WriteAllText(_timeStampFile, JsonConvert.SerializeObject(LastAccessDateTime, Formatting.Indented)); - } - - private void ReadLastAccessTime() - { - var dir = Path.GetDirectoryName(_timeStampFile); - if (!string.IsNullOrEmpty(dir) && !Directory.Exists(dir)) - { - Directory.CreateDirectory(dir); - } - if (File.Exists(_timeStampFile)) - { - using (var file = File.OpenText(_timeStampFile)) - { - var serializer = new JsonSerializer(); - DateTime? loaded = (DateTime?)serializer.Deserialize(file, typeof(DateTime?)); - LastAccessDateTime = loaded; - } - } - } - #endregion - - #region Helper methods ... - private void ReportAlignmentPoints() - { - _stringBuilder.Clear(); - _stringBuilder.AppendLine("=============== Alignment points ==============="); - _stringBuilder.AppendLine("ID \tEncoder Ra/Dec \tOrig Ra/Dec \tTarget RaDec \tObserved time"); - foreach (var pt in AlignmentPoints) - { - _stringBuilder.AppendLine( - $"{pt.Id:D3}\t{pt.Encoder.RA}/{pt.Encoder.Dec}\t{pt.OrigRaDec.RA}/{pt.OrigRaDec.Dec}\t{pt.Target.RA}/{pt.Target.Dec}\t{pt.AlignTime}"); - } - RaiseNotification(NotificationType.Data, MethodBase.GetCurrentMethod()?.Name, _stringBuilder.ToString()); - _stringBuilder.Clear(); - } - - private void LogException(Exception ex, bool allowDuplicates = false) - { - if (allowDuplicates || !_exceptionMessages.Contains(ex.Message)) - { - _exceptionMessages.Add(ex.Message); - string message = $"{ex.Message}|{ex.StackTrace}"; - RaiseNotification(NotificationType.Error, MethodBase.GetCurrentMethod()?.Name, message); - } - } - - #endregion - } -} diff --git a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs deleted file mode 100644 index 61358359..00000000 --- a/EqmodNStarAlignment/Model/AlignmentModel_EqModVector.cs +++ /dev/null @@ -1,1597 +0,0 @@ -/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -//--------------------------------------------------------------------- -// based on original work -// Copyright � 2006 Raymund Sarmiento -// -// Permission is hereby granted to use this Software for any purpose -// including combining with commercial products, creating derivative -// works, and redistribution of source or binary code, without -// limitation or consideration. Any redistributed copies of this -// Software must include the above Copyright Notice. -// -// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO -// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS -// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -//--------------------------------------------------------------------- -// -// EQMODVECTOR.BAS - Matrix Transformation Routines for 3-Star Alignment -// (Renamed EQTakiAffine.cs) -// Written: 10-Dec-06 Raymund Sarmiento -// -// Edits: -// -// When Who What -// --------- --- -------------------------------------------------- -// 10-Dec-06 rcs Initial edit for EQ Mount 3-Star Matrix Transformation -// 14-Dec-06 rcs Added Taki Method on top of Affine Mapping Method for Comparison -// Taki Routines based on John Archbold's Excel computation -// 08-Apr-07 rcs N-star implementation -// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# -//--------------------------------------------------------------------- -// -// - -// DISCLAIMER: - -// You can use the information on this site COMPLETELY AT YOUR OWN RISK. -// The modification steps and other information on this site is provided -// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, -// implied or otherwise, including without limitation any warranty of -// merchantability or fitness for any particular or intended purpose. -// In no event the author will be liable for any direct, indirect, -// punitive, special, incidental or consequential damages or loss of any -// kind whether or not the author has been advised of the possibility -// of such loss. - -// WARNING: - -// Circuit modifications implemented on your setup could invalidate -// any warranty that you may have with your product. Use this -// information at your own risk. The modifications involve direct -// access to the stepper motor controls of your mount. Any "mis-control" -// or "mis-command" / "invalid parameter" or "garbage" data sent to the -// mount could accidentally activate the stepper motors and allow it to -// rotate "freely" damaging any equipment connected to your mount. -// It is also possible that any garbage or invalid data sent to the mount -// could cause its firmware to generate mis-steps pulse sequences to the -// motors causing it to overheat. Make sure that you perform the -// modifications and testing while there is no physical "load" or -// dangling wires on your mount. Be sure to disconnect the power once -// this event happens or if you notice any unusual sound coming from -// the motor assembly. -// - -using EqmodNStarAlignment.DataTypes; -using EqmodNStarAlignment.Utilities; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; - -namespace EqmodNStarAlignment.Model -{ - partial class AlignmentModel - { - - - - - //Define Affine Matrix - - public static Matrix EQMP = Matrix.CreateInstance(); - public static Matrix EQMQ = Matrix.CreateInstance(); - - public static Matrix EQMI = Matrix.CreateInstance(); - public static Matrix EQMM = Matrix.CreateInstance(); - public static Coord EQCO = new Coord(); - - - //Define Taki Matrix - - public static Matrix EQLMN1 = Matrix.CreateInstance(); - public static Matrix EQLMN2 = Matrix.CreateInstance(); - - public static Matrix EQMI_T = Matrix.CreateInstance(); - public static Matrix EQMT = Matrix.CreateInstance(); - public static Coord EQCT = new Coord(); - - - - //Function to put coordinate values into a LMN/lmn matrix array - - private Matrix GETLMN(Coord p1, Coord p2, Coord p3) - { - - Matrix temp = Matrix.CreateInstance(); - Matrix UnitVect = Matrix.CreateInstance(); - - - temp.Element[0, 0] = p2.x - p1.x; - temp.Element[1, 0] = p3.x - p1.x; - - temp.Element[0, 1] = p2.y - p1.y; - temp.Element[1, 1] = p3.y - p1.y; - - temp.Element[0, 2] = p2.z - p1.z; - temp.Element[1, 2] = p3.z - p1.z; - - - - - UnitVect.Element[0, 0] = (temp.Element[0, 1] * temp.Element[1, 2]) - (temp.Element[0, 2] * temp.Element[1, 1]); - UnitVect.Element[0, 1] = (temp.Element[0, 2] * temp.Element[1, 0]) - (temp.Element[0, 0] * temp.Element[1, 2]); - UnitVect.Element[0, 2] = (temp.Element[0, 0] * temp.Element[1, 1]) - (temp.Element[0, 1] * temp.Element[1, 0]); - UnitVect.Element[1, 0] = Math.Pow(UnitVect.Element[0, 0], 2) + Math.Pow(UnitVect.Element[0, 1], 2) + Math.Pow(UnitVect.Element[0, 2], 2); - UnitVect.Element[1, 1] = Math.Sqrt(UnitVect.Element[1, 0]); - if (UnitVect.Element[1, 1] != 0) - { - UnitVect.Element[1, 2] = 1 / UnitVect.Element[1, 1]; - } - - - - temp.Element[2, 0] = UnitVect.Element[1, 2] * UnitVect.Element[0, 0]; - temp.Element[2, 1] = UnitVect.Element[1, 2] * UnitVect.Element[0, 1]; - temp.Element[2, 2] = UnitVect.Element[1, 2] * UnitVect.Element[0, 2]; - - - - - return temp; - - } - - //Function to put coordinate values into a P/Q Affine matrix array - - private Matrix GETPQ(Coord p1, Coord p2, Coord p3) - { - - Matrix temp = Matrix.CreateInstance(); - - temp.Element[0, 0] = p2.x - p1.x; - temp.Element[1, 0] = p3.x - p1.x; - temp.Element[0, 1] = p2.y - p1.y; - temp.Element[1, 1] = p3.y - p1.y; - - return temp; - - } - - // Subroutine to draw the Transformation Matrix (Taki Method) - - private bool EQ_AssembleMatrix_Taki(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) - { - - - double Det = 0; - - - // Get the LMN Matrix - - EQLMN1 = GETLMN(a1, a2, a3); - - // Get the lmn Matrix - - EQLMN2 = GETLMN(m1, m2, m3); - - - - - // Get the Determinant - - Det = EQLMN1.Element[0, 0] * ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])); - Det -= (EQLMN1.Element[0, 1] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 2]))); - Det += (EQLMN1.Element[0, 2] * ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1]))); - - - // Compute for the Matrix Inverse of EQLMN1 - - if (Det == 0) - { - throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); - } - else - { - - EQMI_T.Element[0, 0] = ((EQLMN1.Element[1, 1] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[1, 2])) / Det; - EQMI_T.Element[0, 1] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[0, 1] * EQLMN1.Element[2, 2])) / Det; - EQMI_T.Element[0, 2] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[1, 2]) - (EQLMN1.Element[1, 1] * EQLMN1.Element[0, 2])) / Det; - EQMI_T.Element[1, 0] = ((EQLMN1.Element[1, 2] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 2] * EQLMN1.Element[1, 0])) / Det; - EQMI_T.Element[1, 1] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[2, 2]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[0, 2])) / Det; - EQMI_T.Element[1, 2] = ((EQLMN1.Element[0, 2] * EQLMN1.Element[1, 0]) - (EQLMN1.Element[1, 2] * EQLMN1.Element[0, 0])) / Det; - EQMI_T.Element[2, 0] = ((EQLMN1.Element[1, 0] * EQLMN1.Element[2, 1]) - (EQLMN1.Element[2, 0] * EQLMN1.Element[1, 1])) / Det; - EQMI_T.Element[2, 1] = ((EQLMN1.Element[0, 1] * EQLMN1.Element[2, 0]) - (EQLMN1.Element[2, 1] * EQLMN1.Element[0, 0])) / Det; - EQMI_T.Element[2, 2] = ((EQLMN1.Element[0, 0] * EQLMN1.Element[1, 1]) - (EQLMN1.Element[1, 0] * EQLMN1.Element[0, 1])) / Det; - } - - - - // Get the M Matrix by Multiplying EQMI and EQLMN2 - // EQMI_T - Matrix A - // EQLMN2 - Matrix B - - - EQMT.Element[0, 0] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 0]); - EQMT.Element[0, 1] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 1]); - EQMT.Element[0, 2] = (EQMI_T.Element[0, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[0, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[0, 2] * EQLMN2.Element[2, 2]); - - EQMT.Element[1, 0] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 0]); - EQMT.Element[1, 1] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 1]); - EQMT.Element[1, 2] = (EQMI_T.Element[1, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[1, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[1, 2] * EQLMN2.Element[2, 2]); - - EQMT.Element[2, 0] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 0]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 0]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 0]); - EQMT.Element[2, 1] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 1]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 1]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 1]); - EQMT.Element[2, 2] = (EQMI_T.Element[2, 0] * EQLMN2.Element[0, 2]) + (EQMI_T.Element[2, 1] * EQLMN2.Element[1, 2]) + (EQMI_T.Element[2, 2] * EQLMN2.Element[2, 2]); - - - // Get the Coordinate Offset Vector and store it at EQCO Matrix - - EQCT.x = m1.x - ((a1.x * EQMT.Element[0, 0]) + (a1.y * EQMT.Element[1, 0]) + (a1.z * EQMT.Element[2, 0])); - EQCT.y = m1.y - ((a1.x * EQMT.Element[0, 1]) + (a1.y * EQMT.Element[1, 1]) + (a1.z * EQMT.Element[2, 1])); - EQCT.z = m1.z - ((a1.x * EQMT.Element[0, 2]) + (a1.y * EQMT.Element[1, 2]) + (a1.z * EQMT.Element[2, 2])); - - - if ((x + Y) == 0) - { - return false; - } - else - { - return EQ_CheckPoint_in_Triangle(x, Y, a1.x, a1.y, a2.x, a2.y, a3.x, a3.y); - } - - - } - - - /// - /// Function to transform the Coordinates (Taki Method) using the MT Matrix and Offset Vector - /// - /// - /// - private CartesCoord EQ_Transform_Taki(CartesCoord pos) - { - CartesCoord result = new CartesCoord(); - result.x = EQCT.x + ((pos.x * EQMT.Element[0, 0]) + (pos.y * EQMT.Element[1, 0]) + (pos.z * EQMT.Element[2, 0])); - result.y = EQCT.y + ((pos.x * EQMT.Element[0, 1]) + (pos.y * EQMT.Element[1, 1]) + (pos.z * EQMT.Element[2, 1])); - result.z = EQCT.z + ((pos.x * EQMT.Element[0, 2]) + (pos.y * EQMT.Element[1, 2]) + (pos.z * EQMT.Element[2, 2])); - return result; - } - - /// - /// Subroutine to draw the Transformation Matrix (Affine Mapping Method) - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - private bool EQ_AssembleMatrix_Affine(double x, double Y, Coord a1, Coord a2, Coord a3, Coord m1, Coord m2, Coord m3) - { - - double Det = 0; - - // Get the P Matrix - EQMP = GETPQ(a1, a2, a3); - - // Get the Q Matrix - EQMQ = GETPQ(m1, m2, m3); - - // Get the Inverse of P - // Get the EQMP Determinant for Inverse Computation - Det = (EQMP.Element[0, 0] * EQMP.Element[1, 1]) - (EQMP.Element[0, 1] * EQMP.Element[1, 0]); - - // Make sure Determinant is NON ZERO - if (Det == 0) - { - throw new System.Exception("999, AssembleMatrix, Cannot invert matrix with Determinant = 0"); - } - else - { - //Perform the Matrix Inversion, put result to EQMI matrix - EQMI.Element[0, 0] = (EQMP.Element[1, 1]) / Det; - EQMI.Element[0, 1] = (-EQMP.Element[0, 1]) / Det; - EQMI.Element[1, 0] = (-EQMP.Element[1, 0]) / Det; - EQMI.Element[1, 1] = (EQMP.Element[0, 0]) / Det; - } - - // Get the M Matrix by Multiplying EQMI and EQMQ - // EQMI - Matrix A - // EQMQ - Matrix B - EQMM.Element[0, 0] = (EQMI.Element[0, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 0]); - EQMM.Element[0, 1] = (EQMI.Element[0, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[0, 1] * EQMQ.Element[1, 1]); - EQMM.Element[1, 0] = (EQMI.Element[1, 0] * EQMQ.Element[0, 0]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 0]); - EQMM.Element[1, 1] = (EQMI.Element[1, 0] * EQMQ.Element[0, 1]) + (EQMI.Element[1, 1] * EQMQ.Element[1, 1]); - - // Get the Coordinate Offset Vector and store it at EQCO Matrix - EQCO.x = m1.x - ((a1.x * EQMM.Element[0, 0]) + (a1.y * EQMM.Element[1, 0])); - EQCO.y = m1.y - ((a1.x * EQMM.Element[0, 1]) + (a1.y * EQMM.Element[1, 1])); - - if ((x + Y) == 0) - { - return false; - } - else - { - return EQ_CheckPoint_in_Triangle(x, Y, m1.x, m1.y, m2.x, m2.y, m3.x, m3.y); - } - - } - - - /// - /// Function to transform the Coordinates (Affine Mapping) using the M Matrix and Offset Vector - /// - /// - /// - private CartesCoord EQ_Transform_Affine(CartesCoord pos) - { - CartesCoord result = new CartesCoord(); - result.x = EQCO.x + ((pos.x * EQMM.Element[0, 0]) + (pos.y * EQMM.Element[1, 0])); - result.y = EQCO.y + ((pos.x * EQMM.Element[0, 1]) + (pos.y * EQMM.Element[1, 1])); - return result; - } - - //Function to convert spherical coordinates to Cartesian using the Coord structure - - public Coord EQ_sp2Cs(EncoderPosition pos) - { - Coord result = new Coord(); - - CartesCoord tmpobj = new CartesCoord(); - SphericalCoord tmpobj4 = new SphericalCoord(); - - tmpobj4 = EQ_SphericalPolar(pos); - tmpobj = EQ_Polar2Cartes(tmpobj4); - result.x = tmpobj.x; - result.y = tmpobj.y; - result.z = 1; - - return result; - } - - - ////Function to convert spherical coordinates to Cartesian using the Coord structure - - //internal Coord EQ_sp2Cs2(Coord obj) - //{ - // Coord result = new Coord(); - // double gDECEncoder_Home_pos = 0; - // double gLatitude = 0; - // double gTot_step = 0; - // object HC = null; - // double RAEncoder_Home_pos = 0; - - // CartesCoord tmpobj = new CartesCoord(); - // SphericalCoord tmpobj4 = new SphericalCoord(); - - // if (PolarEnable) - // { - // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, this.StepsPerRev, this.HomeEncoder, Math.Abs(gLatitude)); - // tmpobj = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - // result.x = tmpobj.x; - // result.y = tmpobj.y; - // result.z = 1; - // } - // else - // { - // result.x = obj.x; - // result.y = obj.y; - // result.z = 1; - // } - - // return result; - //} - - - ////Function to convert polar coordinates to Cartesian using the Coord structure - - - //internal Coord EQ_pl2Cs(Coord obj) - //{ - // Coord result = new Coord(); - // double gDECEncoder_Home_pos = 0; - // double gTot_step = 0; - // object HC = null; - // double RAEncoder_Home_pos = 0; - - // CartesCoord tmpobj = new CartesCoord(); - - // if (PolarEnable) - // { - // tmpobj = EQ_Polar2Cartes(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - - // result.x = tmpobj.x; - // result.y = tmpobj.y; - // result.z = 1; - // } - // else - // { - // result.x = obj.x; - // result.y = obj.y; - // result.z = 1; - // } - - // return result; - //} - - - /// - /// Implement an Affine transformation on a Polar coordinate system - /// This is done by converting the Polar Data to Cartesian, Apply affine transformation - /// Then restore the transformed Cartesian Coordinates back to polar - /// - /// - /// - internal EncoderPosition EQ_plAffine(EncoderPosition pos) - { - EncoderPosition result = new EncoderPosition(); - CartesCoord tmpobj1 = new CartesCoord(); - CartesCoord tmpobj3 = new CartesCoord(); - SphericalCoord tmpobj2 = new SphericalCoord(); - SphericalCoord tmpobj4 = new SphericalCoord(); - - tmpobj4 = EQ_SphericalPolar(pos); - tmpobj1 = EQ_Polar2Cartes(tmpobj4); - - tmpobj3 = EQ_Transform_Affine(tmpobj1); - - tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); - result = EQ_PolarSpherical(tmpobj2, tmpobj4); - return result; - } - - - //internal Coord EQ_plAffine2(Coord obj) - //{ - // Coord result = new Coord(); - // double gDECEncoder_Home_pos = 0; - // double gLatitude = 0; - // double gTot_step = 0; - // object HC = null; - // double RAEncoder_Home_pos = 0; - - // CartesCoord tmpobj1 = new CartesCoord(); - // Coord tmpobj2 = new Coord(); - // Coord tmpobj3 = new Coord(); - // SphericalCoord tmpobj4 = new SphericalCoord(); - - // if (PolarEnable) - // { - // tmpobj4 = EQ_SphericalPolar(obj.x, obj.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude); - - // tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - - // tmpobj2.x = tmpobj1.x; - // tmpobj2.y = tmpobj1.y; - // tmpobj2.z = 1; - - // tmpobj3 = EQ_Transform_Affine(tmpobj2); - - // tmpobj2 = EQ_Cartes2Polar(tmpobj3.x, tmpobj3.y, tmpobj1.r, tmpobj1.ra, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos); - - - // result = EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, tmpobj4.r); - - // } - // else - // { - // tmpobj3 = EQ_Transform_Affine(obj); - // result.x = tmpobj3.x; - // result.y = tmpobj3.y; - // result.z = 1; - // } - - // return result; - //} - - - /// - /// Implement a TAKI transformation on a Polar coordinate system - /// This is done by converting the Polar Data to Cartesian, Apply TAKI transformation - /// Then restore the transformed Cartesian Coordinates back to polar - /// - /// - /// - internal EncoderPosition EQ_plTaki(EncoderPosition pos) - { - EncoderPosition result = new EncoderPosition(); - CartesCoord tmpobj1 = new CartesCoord(); - CartesCoord tmpobj3 = new CartesCoord(); - SphericalCoord tmpobj2 = new SphericalCoord(); - SphericalCoord tmpobj4 = new SphericalCoord(); - - tmpobj4 = EQ_SphericalPolar(pos); - tmpobj1 = EQ_Polar2Cartes(tmpobj4); - - tmpobj3 = EQ_Transform_Taki(tmpobj1); - - tmpobj2 = EQ_Cartes2Polar(tmpobj3, tmpobj1); - result = EQ_PolarSpherical(tmpobj2, tmpobj4); - - - return result; - } - - /// - /// Function to Convert Polar RA/DEC Stepper coordinates to Cartesian Coordinates - /// - /// - /// - private CartesCoord EQ_Polar2Cartes(SphericalCoord polar) - { - CartesCoord result = new CartesCoord(); - double i = 0; - - // make angle stays within the 360 bound - if (polar.x > this.HomeEncoder.RA) - { - i = ((polar.x - this.HomeEncoder.RA) / this.StepsPerRev.RA) * 360; - } - else - { - i = ((this.HomeEncoder.RA - polar.x) / this.StepsPerRev.RA) * 360; - i = 360 - i; - } - - double theta = AstroConvert.DegToRad(Range.Range360(i)); - - //treat y as the radius of the polar coordinate - - double radius = polar.y - this.HomeEncoder.Dec; - - double radpeak = 0; - - - // Avoid division 0 errors - - if (radius == 0) - { - radius = 1; - } - - // Get the cartesian coordinates - - result.x = Math.Cos(theta) * radius; - result.y = Math.Sin(theta) * radius; - result.ra = radpeak; - - // if radius is a negative number, pass this info on the next conversion routine - - if (radius > 0) - { - result.r = 1; - } - else - { - result.r = -1; - } - - return result; - } - - ////Function to convert the Cartesian Coordinate data back to RA/DEC polar - - private SphericalCoord EQ_Cartes2Polar(CartesCoord cart, CartesCoord rads) - { - SphericalCoord result = new SphericalCoord(); - - // Ah the famous radius formula - double radiusder = Math.Sqrt((cart.x * cart.x) + (cart.y * cart.y)) * rads.r; - - - // And the nasty angle compute routine (any simpler way to impelent this ?) - - double angle = 0; - if (cart.x > 0) - { - angle = Math.Atan(cart.y / cart.x); - } - if (cart.x < 0) - { - if (cart.y >= 0) - { - angle = Math.Atan(cart.y / cart.x) + Math.PI; - - } - else - { - angle = Math.Atan(cart.y / cart.x) - Math.PI; - } - } - if (cart.x == 0) - { - if (cart.y > 0) - { - angle = Math.PI / 2d; - } - else - { - angle = -1 * (Math.PI / 2d); - } - } - - // Convert angle to degrees - - angle = AstroConvert.RadToDeg(angle); - - if (angle < 0) - { - angle = 360 + angle; - } - - if (rads.r < 0) - { - angle = Range.Range360((angle + 180)); - } - - if (angle > 180) - { - result.x = this.HomeEncoder.RA - (((360 - angle) / 360d) * this.StepsPerRev.RA); - } - else - { - result.x = ((angle / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; - } - - //treat y as the polar coordinate radius (ra var not used - always 0) - - result.y = radiusder + this.HomeEncoder.Dec + rads.ra; - - return result; - } - - internal bool EQ_UpdateTaki(EncoderPosition pos) - { - bool result = false; - List nearestPoints = new List(); - - // Adjust only if there are four alignment stars - if (this.AlignmentPoints.Count < 3) - { - return result; - } - - - switch (this.ThreePointAlgorithm) - { - case ThreePointAlgorithmEnum.BestCentre: - // find the 50 nearest points - then find the nearest enclosing triangle - nearestPoints = EQ_ChooseNearest3Points(pos); - break; - default: - // find the 50 nearest points - then find the enclosing triangle with the nearest centre point - nearestPoints = EQ_Choose_3Points(pos); - break; - } - - if (nearestPoints.Count < 3) - { - return false; - } - - Coord tmpCoord = EQ_sp2Cs(pos); - - return EQ_AssembleMatrix_Taki(tmpCoord.x, tmpCoord.y, - nearestPoints[0].TargetCartesian, - nearestPoints[1].TargetCartesian, - nearestPoints[2].TargetCartesian, - nearestPoints[0].EncoderCartesian, - nearestPoints[1].EncoderCartesian, - nearestPoints[2].EncoderCartesian); - - } - - internal bool EQ_UpdateAffine(EncoderPosition pos) - { - bool result = false; - - List nearestPoints = new List(); - - if (this.AlignmentPoints.Count < 3) - { - return result; - } - - switch (this.ThreePointAlgorithm) - { - case ThreePointAlgorithmEnum.BestCentre: - // find the 50 nearest points - then find the nearest enclosing triangle - nearestPoints = EQ_ChooseNearest3Points(pos); - break; - default: - // find the 50 nearest points - then find the enclosing triangle with the nearest centre point - nearestPoints = EQ_Choose_3Points(pos); - break; - } - - - if (nearestPoints.Count < 3) - { - return false; - } - - Coord tmpcoord = EQ_sp2Cs(pos); - - return EQ_AssembleMatrix_Affine(tmpcoord.x, tmpcoord.y, - nearestPoints[0].EncoderCartesian, - nearestPoints[1].EncoderCartesian, - nearestPoints[2].EncoderCartesian, - nearestPoints[0].TargetCartesian, - nearestPoints[1].TargetCartesian, - nearestPoints[2].TargetCartesian); - } - - //// Subroutine to implement find Array index with the lowest value - //private int EQ_FindLowest(double[] List, int min, int max) - //{ - // double val = 0; - // double newval = 0; - // int i = 0; - - // int idx = -1; - // int tempForEndVar = 0; - // if (!(min >= max || max > List.GetUpperBound(0))) - // { - - // val = List[min]; - // tempForEndVar = max; - // for (i = min; i <= tempForEndVar; i++) - // { - // newval = List[i]; - // if (newval <= val) - // { - // val = newval; - // idx = i; - // } - // } - - // } - - // return idx; - //} - - //private void EQ_FindLowest3(double[] List, int[] Sublist, int min, int max) - //{ - // double val = 0; - // double min1 = 0; - // double min2 = 0; - // double min3 = 0; - // int i = 0; - - // int tempForEndVar = 0; - // if (!(min >= max || max > List.GetUpperBound(0))) - // { - - // if (List[1] <= List[2] && List[1] <= List[3]) - // { - // //List 1 is first - // min1 = List[1]; - // if (List[2] <= List[3]) - // { - // //List2 is second - // //List3 is third - // min2 = List[2]; - // min3 = List[3]; - // } - // else - // { - // //List3 is second - // //List2 is third - // min2 = List[3]; - // min3 = List[2]; - // } - // } - // else - // { - // if (List[2] <= List[1] && List[2] <= List[3]) - // { - // //List 2 is first - // min1 = List[2]; - // if (List[1] <= List[3]) - // { - // //List1 is second - // //List3 is third - // min2 = List[1]; - // min3 = List[3]; - // } - // else - // { - // //List3 is second - // //List1 is third - // min2 = List[3]; - // min3 = List[1]; - // } - // } - // else - // { - // if (List[3] <= List[1] && List[3] <= List[2]) - // { - // //List 3 is first - // min1 = List[3]; - // if (List[1] <= List[2]) - // { - // //List1 is second - // //List2 is third - // min2 = List[1]; - // min3 = List[2]; - // } - // else - // { - // //List2 is second - // //List1 is third - // min2 = List[2]; - // min3 = List[1]; - // } - // } - // } - // } - - // val = List[min]; - - // tempForEndVar = max; - // for (i = min; i <= tempForEndVar; i++) - // { - // val = List[i]; - // if (val < min1) - // { - // min1 = val; - // Sublist[3] = Sublist[2]; - // Sublist[2] = Sublist[1]; - // Sublist[1] = i; - // } - // else - // { - // if (val < min2) - // { - // min2 = val; - // Sublist[3] = Sublist[2]; - // Sublist[2] = i; - // } - // else - // { - // if (val < min3) - // { - // Sublist[3] = i; - // } - // } - // } - // } - - // } - - - //} - - - - - //// Subroutine to implement an Array sort - //private void EQ_Quicksort(double[] List, double[] Sublist, int min, int max) - //{ - - - - // if (min >= max) - // { - // return; - // } - - // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); - // double med_value = List[i]; - // double submed = Sublist[i]; - - // List[i] = List[min]; - // Sublist[i] = Sublist[min]; - - // int lo = min; - // int hi = max; - // do - // { - - // while (List[hi] >= med_value) - // { - // hi--; - // if (hi <= lo) - // { - // break; - // } - // }; - // if (hi <= lo) - // { - // List[lo] = med_value; - // Sublist[lo] = submed; - // break; - // } - - // List[lo] = List[hi]; - // Sublist[lo] = Sublist[hi]; - - // lo++; - - // while (List[lo] < med_value) - // { - // lo++; - // if (lo >= hi) - // { - // break; - // } - // }; - - // if (lo >= hi) - // { - // lo = hi; - // List[hi] = med_value; - // Sublist[hi] = submed; - // break; - // } - - // List[hi] = List[lo]; - // Sublist[hi] = Sublist[lo]; - - // } - // while (true); - - // EQ_Quicksort(List, Sublist, min, lo - 1); - // EQ_Quicksort(List, Sublist, lo + 1, max); - - //} - - - //// Subroutine to implement an Array sort - - //private void EQ_Quicksort2(Tdatholder[] List, int min, int max) - //{ - - // if (min >= max) - // { - // return; - // } - - // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); - // Tdatholder med_value = Tdatholder.CreateInstance(); - - // List[i] = List[min]; - - // int lo = min; - // int hi = max; - - // do - // { - - // while (List[hi].dat >= med_value.dat) - // { - // hi--; - // if (hi <= lo) - // { - // break; - // } - // }; - // if (hi <= lo) - // { - // List[lo] = med_value; - // break; - // } - - // List[lo] = List[hi]; - - // lo++; - - // while (List[lo].dat < med_value.dat) - // { - // lo++; - // if (lo >= hi) - // { - // break; - // } - // }; - // if (lo >= hi) - // { - // lo = hi; - // List[hi] = med_value; - // break; - // } - - // List[hi] = List[lo]; - // } - // while (true); - - // EQ_Quicksort2(List, min, lo - 1); - // EQ_Quicksort2(List, lo + 1, max); - - //} - - //// Subroutine to implement an Array sort with three sublists - - //private void EQ_Quicksort3(double[] List, double[] Sublist1, double[] Sublist2, double[] Sublist3, int min, int max) - //{ - - // if (min >= max) - // { - // return; - // } - - // int i = Convert.ToInt32(Math.Floor((double)((max - min + 1) * GetRnd() + min))); - // double med_value = List[i]; - // double submed1 = Sublist1[i]; - // double submed2 = Sublist2[i]; - // double submed3 = Sublist3[i]; - - // List[i] = List[min]; - // Sublist1[i] = Sublist1[min]; - // Sublist2[i] = Sublist2[min]; - // Sublist3[i] = Sublist3[min]; - - // int lo = min; - // int hi = max; - // do - // { - - - // while (List[hi] >= med_value) - // { - // hi--; - // if (hi <= lo) - // { - // break; - // } - // }; - // if (hi <= lo) - // { - // List[lo] = med_value; - // Sublist1[lo] = submed1; - // Sublist2[lo] = submed2; - // Sublist3[lo] = submed3; - // break; - // } - - - // List[lo] = List[hi]; - // Sublist1[lo] = Sublist1[hi]; - // Sublist2[lo] = Sublist2[hi]; - // Sublist3[lo] = Sublist3[hi]; - - // lo++; - - // while (List[lo] < med_value) - // { - // lo++; - // if (lo >= hi) - // { - // break; - // } - // }; - // if (lo >= hi) - // { - // lo = hi; - // List[hi] = med_value; - // Sublist1[hi] = submed1; - // Sublist2[hi] = submed2; - // Sublist3[hi] = submed3; - // break; - // } - - // List[hi] = List[lo]; - // Sublist1[hi] = Sublist1[lo]; - // Sublist2[hi] = Sublist2[lo]; - // Sublist3[hi] = Sublist3[lo]; - // } - // while (true); - - // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, min, lo - 1); - // EQ_Quicksort3(List, Sublist1, Sublist2, Sublist3, lo + 1, max); - - //} - - // Function to compute for an area of a triangle - - private double EQ_Triangle_Area(double px1, double py1, double px2, double py2, double px3, double py3) - { - - - //True formula is this - // EQ_Triangle_Area = Abs(((px2 * py1) - (px1 * py2)) + ((px3 * py2) - (px2 * py3)) + ((px1 * py3) - (px3 * py1))) / 2 - - // Make LARGE numerical value safe for Windows by adding a scaling factor - - double ta = (((px2 * py1) - (px1 * py2)) / 10000d) + (((px3 * py2) - (px2 * py3)) / 10000d) + (((px1 * py3) - (px3 * py1)) / 10000d); - - return Math.Abs(ta) / 2d; - - } - - // Function to check if a point is inside the triangle. Computed based sum of areas method - - private bool EQ_CheckPoint_in_Triangle(double px, double py, double px1, double py1, double px2, double py2, double px3, double py3) - { - - - double ta = EQ_Triangle_Area(px1, py1, px2, py2, px3, py3); - double t1 = EQ_Triangle_Area(px, py, px2, py2, px3, py3); - double t2 = EQ_Triangle_Area(px1, py1, px, py, px3, py3); - double t3 = EQ_Triangle_Area(px1, py1, px2, py2, px, py); - - - if (Math.Abs(ta - t1 - t2 - t3) < 2) - { - return true; - } - else - { - return false; - } - - } - - - - /// - /// Returns the centroid of a triangle. - /// - /// - /// - /// - /// - private Coord EQ_GetCenterPoint(Coord p1, Coord p2, Coord p3) - { - - Coord result = new Coord(); - double p2x = 0d; - double p2y = 0d; - double p4x = 0d; - double p4y = 0d; - - // Get the two line 4 point data - - double p1x = p1.x; - double p1y = p1.y; - - - if (p3.x > p2.x) - { - p2x = ((p3.x - p2.x) / 2d) + p2.x; - } - else - { - p2x = ((p2.x - p3.x) / 2d) + p3.x; - } - - if (p3.y > p2.y) - { - p2y = ((p3.y - p2.y) / 2d) + p2.y; - } - else - { - p2y = ((p2.y - p3.y) / 2d) + p3.y; - } - - double p3x = p2.x; - double p3y = p2.y; - - - if (p1.x > p3.x) - { - p4x = ((p1.x - p3.x) / 2d) + p3.x; - } - else - { - p4x = ((p3.x - p1.x) / 2d) + p1.x; - } - - if (p1.y > p3.y) - { - p4y = ((p1.y - p3.y) / 2d) + p3.y; - } - else - { - p4y = ((p3.y - p1.y) / 2d) + p1.y; - } - - - double XD1 = p2x - p1x; - double XD2 = p4x - p3x; - double YD1 = p2y - p1y; - double YD2 = p4y - p3y; - double XD3 = p1x - p3x; - double YD3 = p1y - p3y; - - - double dv = (YD2 * XD1) - (XD2 * YD1); - - if (dv == 0) - { - dv = 0.00000001d; - } //avoid div 0 errors - - - double ua = ((XD2 * YD3) - (YD2 * XD3)) / dv; - double ub = ((XD1 * YD3) - (YD1 * XD3)) / dv; - - result.x = p1x + (ua * XD1); - result.y = p1y + (ub * YD1); - - return result; - } - - - private SphericalCoord EQ_SphericalPolar(EncoderPosition spherical) - { - //Debug.WriteLine($"Spherical -> Polar"); - //Debug.WriteLine($"Input = {spherical.RA}/{spherical.Dec}"); - SphericalCoord result = new SphericalCoord(); - - double haRad = AstroConvert.HrsToRad(Get_EncoderHours(spherical.RA)); - double decRad = AstroConvert.DegToRad(Range.Range360(Get_EncoderDegrees(spherical.Dec) + 270)); - double latRad = AstroConvert.DegToRad(this.SiteLatitude); - //Debug.WriteLine($"lat/ha/dec (Radians) = {latRad}/{haRad}/{decRad}"); - double[] altAzRad = AstroConvert.GetAltAz(latRad, haRad, decRad); - //Debug.WriteLine($"alt/Az (Radians) = {altAzRad[0]}/{altAzRad[1]}"); - double[] altAz = new double[] { AstroConvert.RadToDeg(altAzRad[0]), AstroConvert.RadToDeg(altAzRad[1]) }; - //Debug.WriteLine($"alt/Az = {altAz[0]}/{altAz[1]}"); - - result.x = (((altAz[1] - 180) / 360d) * this.StepsPerRev.RA) + this.HomeEncoder.RA; - result.y = (((altAz[0] + 90) / 180d) * this.StepsPerRev.Dec) + this.HomeEncoder.Dec; - - // Check if RA value is within allowed visible range - double quadrant = this.StepsPerRev.RA / 4d; - if ((spherical.RA <= (this.HomeEncoder.RA + quadrant)) && (spherical.RA >= (this.HomeEncoder.RA - quadrant))) - { - result.r = 1; - } - else - { - result.r = 0; - } - //Debug.WriteLine($"Output = {result.x}/{result.y}/{result.r}"); - return result; - } - - private EncoderPosition EQ_PolarSpherical(SphericalCoord pos, SphericalCoord range) - { - //Debug.WriteLine($"Polar -> Spherical"); - //Debug.WriteLine($"Input = {pos.x}/{pos.y}/{range.r}"); - EncoderPosition result = new EncoderPosition(); - double az = (((pos.x - this.HomeEncoder.RA) / this.StepsPerRev.RA) * 360) + 180; - double azRad = AstroConvert.DegToRad(az); - double alt = (((pos.y - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 180) - 90; - double altRad = AstroConvert.DegToRad(alt); - double latRad = AstroConvert.DegToRad(this.SiteLatitude); - //Debug.WriteLine($"az/alt (Degrees) = {az}/{alt}"); - //Debug.WriteLine($"lat/alt/Az (Radians) = {latRad}/{altRad}/{azRad}"); - double[] haDecRad = AstroConvert.GetHaDec(latRad, altRad, azRad); - //Debug.WriteLine($"ha/dec (Radians) = {haDecRad[0]}/{haDecRad[1]}"); - double[] haDec = new double[] { AstroConvert.RadToHrs(haDecRad[0]), AstroConvert.RadToDeg(haDecRad[1]) }; - //Debug.WriteLine($"ha/dec = {haDec[0]}/{haDec[1]}"); - - if (az > 180) - { - if (range.r == 0) - { - haDec[1] = Range.Range360(180 - haDec[1]); - } - else - { - haDec[1] = Range.Range360(haDec[1]); - } - } - else - { - if (range.r == 0) - { - haDec[1] = Range.Range360(haDec[1]); - } - else - { - haDec[1] = Range.Range360(180 - haDec[1]); - } - } - - alt = Range.Range360(haDec[1] + 90); - - if (alt < 180) - { - if (range.r == 1) - { - haDec[0] = Range.Range24(haDec[0]); - } - else - { - haDec[0] = Range.Range24(24 + haDec[0]); - } - } - else - { - haDec[0] = Range.Range24(12 + haDec[0]); - } - - //Debug.WriteLine($"X/Y = {haDec[0]}/{haDec[1]}"); - - result.RA = Get_EncoderfromHours(haDec[0]); - result.Dec = Get_EncoderfromDegrees(haDec[1] + 90); - - //Debug.WriteLine($"Output = {result.RA}/{result.Dec}"); - return result; - } - - - //private CartesCoord EQ_Spherical2Cartes(double RA, double DEC, double TOT, double RACENTER, double DECCENTER) - //{ - // CartesCoord result = new CartesCoord(); - // double gLatitude = 0; - - - // SphericalCoord tmpobj4 = EQ_SphericalPolar(RA, DEC, TOT, RACENTER, DECCENTER, gLatitude); - - // CartesCoord tmpobj1 = EQ_Polar2Cartes(tmpobj4.x, tmpobj4.y, TOT, RACENTER, DECCENTER); - - // result.x = tmpobj1.x; - // result.y = tmpobj1.y; - // result.ra = tmpobj1.ra; - // result.r = tmpobj1.r; - - // return result; - //} - - //private Coord EQ_Cartes2Spherical(double x, double Y, double r, double RA, double range, double TOT, double RACENTER, double DECCENTER) - //{ - // double gDECEncoder_Home_pos = 0; - // double gLatitude = 0; - // double gTot_step = 0; - // double RAEncoder_Home_pos = 0; - - // Coord tmpobj2 = EQ_Cartes2Polar(x, Y, r, RA, TOT, RACENTER, DECCENTER); - // return EQ_PolarSpherical(tmpobj2.x, tmpobj2.y, gTot_step, RAEncoder_Home_pos, gDECEncoder_Home_pos, gLatitude, range); - - //} - - /// - /// Returns the 3 points making up at triangle with the centre nearest the position - /// - /// - /// List of 3 points or an empty list - internal List EQ_Choose_3Points(EncoderPosition pos) - { - Dictionary distances = new Dictionary(); - List results = new List(); - // Adjust only if there are three alignment stars - - if (AlignmentPoints.Count <= 3) - { - foreach (AlignmentPoint pt in this.AlignmentPoints) - { - pt.SelectedForGoto = true; - results.Add(pt); - } - return results.OrderBy(p => p.AlignTime).ToList(); - } - - Coord posCartesean = EQ_sp2Cs(pos); - - // first find out the distances to the alignment stars - foreach (AlignmentPoint pt in this.AlignmentPoints) - { - pt.SelectedForGoto = false; - switch (this.ActivePoints) - { - case ActivePointsEnum.All: - // all points - - break; - case ActivePointsEnum.PierSide: - // only consider points on this side of the meridian - if (pt.EncoderCartesian.y * posCartesean.y < 0) - { - continue; - } - - break; - case ActivePointsEnum.LocalQuadrant: - // local quadrant - if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.EncoderCartesian))) - { - continue; - } - - break; - } - - if (CheckLocalPier) - { - // calculate polar distance - distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); - } - else - { - // calculate cartesian disatnce - distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); - } - } - - if (distances.Count < 3) - { - return results; // Empty list. - } - - // now sort the distances so the closest stars are at the top - //Just use the nearest 50 stars (or max) - saves processing time - List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); - - var tmp1 = sortedIds.Count - 1; - var tmp2 = tmp1 - 1; - - // iterate through all the triangles posible using the nearest alignment points - double minCentreDistance = double.MaxValue; - double centreDistance; - Coord triangleCentre; - for (int i = 0; i <= tmp2; i++) - { - var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); - for (int j = i + 1; j < tmp1; j++) - { - var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); - for (int k = (j + 1); k < sortedIds.Count; k++) - { - var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); - - - if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, - p1.EncoderCartesian.x, p1.EncoderCartesian.y, - p2.EncoderCartesian.x, p2.EncoderCartesian.y, - p3.EncoderCartesian.x, p3.EncoderCartesian.y)) - { - // Compute for the center point - triangleCentre = EQ_GetCenterPoint(p1.EncoderCartesian, p2.EncoderCartesian, p3.EncoderCartesian); - // don't need full pythagoras - sum of squares is good enough - centreDistance = Math.Pow(triangleCentre.x - posCartesean.x, 2) + Math.Pow(triangleCentre.y - posCartesean.y, 2); - if (centreDistance < minCentreDistance) - { - results = new List { p3, p2, p1 }; // Reversed to match EQMOD sort order - minCentreDistance = centreDistance; - } - } - } - } - } - results.ForEach(p => p.SelectedForGoto = true); - return results.ToList(); - - } - - - - /// - /// Returns the nearest 3 alignment points that form and enclosing triangle around a position. - /// - /// - /// List of 3 points or an empty list. - internal List EQ_ChooseNearest3Points(EncoderPosition pos) - { - Dictionary distances = new Dictionary(); - List results = new List(); - // Adjust only if there are three alignment stars - - if (AlignmentPoints.Count <= 3) - { - foreach (AlignmentPoint pt in this.AlignmentPoints) - { - pt.SelectedForGoto = true; - results.Add(pt); - } - return results.OrderBy(p => p.AlignTime).ToList(); - } - - Coord posCartesean = EQ_sp2Cs(pos); - - // first find out the distances to the alignment stars - foreach (AlignmentPoint pt in this.AlignmentPoints) - { - pt.SelectedForGoto = false; - switch (ActivePoints) - { - case ActivePointsEnum.All: - // all points - - break; - case ActivePointsEnum.PierSide: - // only consider points on this side of the meridian - if (pt.EncoderCartesian.y * posCartesean.y < 0) - { - continue; - } - - break; - case ActivePointsEnum.LocalQuadrant: - // local quadrant - if (!GetQuadrant(posCartesean).Equals(GetQuadrant(pt.EncoderCartesian))) - { - continue; - } - - break; - } - - if (CheckLocalPier) - { - // calculate polar distance - distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); - } - else - { - // calculate cartesian disatnce - distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); - } - } - - if (distances.Count < 3) - { - return results; // Empty list. - } - - // now sort the distances so the closest stars are at the top - //Just use the nearest 50 stars (or max) - saves processing time - List sortedIds = distances.OrderBy(d => d.Value).Select(d => d.Key).Take(this.NStarMaxCombinationCount).ToList(); - - var tmp1 = sortedIds.Count - 1; - var tmp2 = tmp1 - 1; - bool done = false; - - - // iterate through all the triangles posible using the nearest alignment points - for (int i = 0; i <= tmp2; i++) - { - var p1 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[i]); - for (int j = i + 1; j < tmp1; j++) - { - var p2 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[j]); - for (int k = (j + 1); k < sortedIds.Count; k++) - { - var p3 = this.AlignmentPoints.First(pt => pt.Id == sortedIds[k]); - - - if (EQ_CheckPoint_in_Triangle(posCartesean.x, posCartesean.y, - p1.EncoderCartesian.x, p1.EncoderCartesian.y, - p2.EncoderCartesian.x, p2.EncoderCartesian.y, - p3.EncoderCartesian.x, p3.EncoderCartesian.y)) - { - results.Add(p1); - results.Add(p2); - results.Add(p3); - done = true; - } - if (done) break; - } - if (done) break; - } - if (done) break; - } - results.ForEach(p => p.SelectedForGoto = true); - return results.ToList(); - - } - - //public static float GetRnd() - //{ - // Random r = new Random(); - // return (float)(r.Next(1, 1000) / 1000.0); - //} - - } -} - - diff --git a/EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs b/EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs deleted file mode 100644 index 274dae03..00000000 --- a/EqmodNStarAlignment/Model/AlignmentModel_EqmodAlignment.cs +++ /dev/null @@ -1,81 +0,0 @@ -using EqmodNStarAlignment.Utilities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace EqmodNStarAlignment.Model -{ - partial class AlignmentModel - { - public bool EQ_NPointAppend(AlignmentPoint data) - { - bool eq_NPointAppend = true; - _oneStarAdjustment = data.Delta; - - if (AlignmentPoints.Count < 3) - { - // Less than three alignment points so just add the incoming one. - AlignmentPoints.Add(data); - } - else - { - if (AlignmentPoints.Count == 3) - { - AlignmentPoints.Add(data); - // Update the matrices - SendToMatrix(); - } - else - { - // Now have more than 3 so see if this point is a replacement - var nearPoints = this.AlignmentPoints.Where(ap => Math.Abs(ap.Encoder.RA - data.Encoder.RA) < _proximityStepsRa - || Math.Abs(ap.Encoder.Dec - data.Encoder.Dec) < _proximityStepsDec).ToList(); - foreach (AlignmentPoint ap in nearPoints) - { - this.AlignmentPoints.Remove(ap); - } - - // Add the incoming point - AlignmentPoints.Add(data); - - // Update the matrices - SendToMatrix(); - } - } - return eq_NPointAppend; - } - public void SendToMatrix() - { - if (AlignmentPoints.Count < 3) - { - return; - } - foreach (AlignmentPoint pt in AlignmentPoints) - { - pt.EncoderCartesian = EQ_sp2Cs(pt.Encoder); - pt.TargetCartesian = EQ_sp2Cs(pt.Target); - - } - - ActivateMatrix(); - } - - private void ActivateMatrix() - { - _threeStarEnabled = false; - if (AlignmentPoints.Count >= 3) - { - - _ = EQ_AssembleMatrix_Taki(0, 0, - AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian, - AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian, AlignmentPoints[2].EncoderCartesian); - _ = EQ_AssembleMatrix_Affine(0, 0, - AlignmentPoints[0].EncoderCartesian, AlignmentPoints[1].EncoderCartesian, AlignmentPoints[2].EncoderCartesian, - AlignmentPoints[0].TargetCartesian, AlignmentPoints[1].TargetCartesian, AlignmentPoints[2].TargetCartesian); - _threeStarEnabled = true; - } - } - // /pec /showalignment - } -} diff --git a/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs b/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs deleted file mode 100644 index 71819453..00000000 --- a/EqmodNStarAlignment/Model/AlignmentModel_Goto.cs +++ /dev/null @@ -1,80 +0,0 @@ -using EqmodNStarAlignment.DataTypes; -using System; -using System.Collections.Generic; -using System.Text; - -namespace EqmodNStarAlignment.Model -{ - public partial class AlignmentModel - { - - /// - /// Returns the encoder steps for a given target. - /// Based on code from EQMOD's EncoderTimer.Timer event. - /// Used when reporting current position - /// - /// - /// - public EncoderPosition GetEncoderSteps(EncoderPosition encoder) - { - MapResult result; - if (!_threeStarEnabled) - { - SelectedAlignmentPoint = null; - result = Delta_Map(encoder); - } - else - { - switch (this.AlignmentMode) - { - case AlignmentModeEnum.Nearest: - result = DeltaSync_Matrix_Map(encoder); - break; - default: - result = Delta_Matrix_Reverse_Map(encoder); - if (!result.InTriangle) - { - result = DeltaSync_Matrix_Map(encoder); - } - break; - } - } - return result.EncoderPosition; - } - - /// - /// Returns the target steps to go to to an aligned target. - /// Used for goto. - /// - /// The steps for the target - /// - public EncoderPosition GetTargetSteps(EncoderPosition target) - { - MapResult result; - if (!_threeStarEnabled) - { - SelectedAlignmentPoint = null; - result = DeltaReverse_Map(target); - - } - { - switch (this.AlignmentMode) - { - case AlignmentModeEnum.Nearest: - result = DeltaSyncReverse_Matrix_Map(target); - break; - default: - result = Delta_Matrix_Map(target); - if (!result.InTriangle) - { - result = DeltaSyncReverse_Matrix_Map(target); - } - break; - } - } - return result.EncoderPosition; - } - - - } -} diff --git a/EqmodNStarAlignment/Model/AlignmentModel_Math.cs b/EqmodNStarAlignment/Model/AlignmentModel_Math.cs deleted file mode 100644 index f69da3ed..00000000 --- a/EqmodNStarAlignment/Model/AlignmentModel_Math.cs +++ /dev/null @@ -1,1007 +0,0 @@ -/* Copyright(C) 2020 Phil Crompton (phil@lunaticsoftware.org) - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -//--------------------------------------------------------------------- -// based on original work -// Copyright © 2006 Raymund Sarmiento -// -// Permission is hereby granted to use this Software for any purpose -// including combining with commercial products, creating derivative -// works, and redistribution of source or binary code, without -// limitation or consideration. Any redistributed copies of this -// Software must include the above Copyright Notice. -// -// THIS SOFTWARE IS PROVIDED "AS IS". THE AUTHOR OF THIS CODE MAKES NO -// WARRANTIES REGARDING THIS SOFTWARE, EXPRESS OR IMPLIED, AS TO ITS -// SUITABILITY OR FITNESS FOR A PARTICULAR PURPOSE. -//--------------------------------------------------------------------- -// -// EQMATH.bas - Math functions for EQMOD ASCOM RADECALTAZ computations -// -// -// Written: 07-Oct-06 Raymund Sarmiento -// -// Edits: -// -// When Who What -// --------- --- -------------------------------------------------- -// 04-Nov-06 rcs Initial edit for EQ Mount Driver Function Prototype -// 20-Nov-06 rcs wrote a new function for now_lst that will generate millisecond -// granularity -// 21-Nov-06 rcs Append RA GOTO Compensation to minimize discrepancy -// 19-Mar-07 rcs Initial Edit for Three star alignment -// 05-Apr-07 rcs Add MAXSYNC -// 08-Apr-07 rcs N-star implementation -// 13-Jun-20 jpc Copied into NPoint code base and converted from vb6 to C# -//--------------------------------------------------------------------- -// -// -// DISCLAIMER: - -// You can use the information on this site COMPLETELY AT YOUR OWN RISK. -// The modification steps and other information on this site is provided -// to you "AS IS" and WITHOUT WARRANTY OF ANY KIND, express, statutory, -// implied or otherwise, including without limitation any warranty of -// merchantability or fitness for any particular or intended purpose. -// In no event the author will be liable for any direct, indirect, -// punitive, special, incidental or consequential damages or loss of any -// kind whether or not the author has been advised of the possibility -// of such loss. - -using EqmodNStarAlignment.DataTypes; -using EqmodNStarAlignment.Utilities; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -namespace EqmodNStarAlignment.Model -{ - partial class AlignmentModel - { - - //private const double DEG_RAD = 0.0174532925d; - //private const double RAD_DEG = 57.2957795d; - //private const double HRS_RAD = 0.2617993881d; - //private const double RAD_HRS = 3.81971863d; - - //private const double SID_RATE = 15.041067d; - //private const double SOL_RATE = 15; - //private const double LUN_RATE = 14.511415d; - - //private const double gEMUL_RATE = 20.98d; // 0.2 * 9024000/( (23*60*60)+(56*60)+4) - // // 0.2 = 200ms - - //private const double gEMUL_RATE2 = 104.730403903004d; // (9024000/86164.0905) - - //// 104.73040390300411747513310083625 - - //private const double gARCSECSTEP = 0.144d; // .144 arcesconds / step - - //// Iterative GOTO Constants - ////Public Const NUM_SLEW_RETRIES As Long = 5 ' Iterative MAX retries - //private const double gRA_Allowed_diff = 10; // Iterative Slew minimum difference - - - //// Home Position of the mount (pointing at NCP/SCP) - - //private const double RAEncoder_Home_pos = 0x800000; // Start at 0 Hour - //private const double DECEncoder_Home_pos = 0xA26C80; // Start at 90 Degree position - - //private const double gRAEncoder_Zero_pos = 0x800000; // ENCODER 0 Hour initial position - //private const double gDECEncoder_Zero_pos = 0x800000; // ENCODER 0 Degree Initial position - - //private const double gDefault_step = 9024000; // Total Encoder count (EQ5/6) - - - - ////Public Const EQ_MAXSYNC As Double = &H111700 - - //// Public Const EQ_MAXSYNC_Const As Double = &H88B80 ' Allow a 45 degree discrepancy - - - //private const double EQ_MAXSYNC_Const = 0x113640; // Allow a 45 degree discrepancy - - ////------------------------------------------------------------------------------------------------ - - //// Define all Global Variables - - - //public static double gXshift = 0; - //public static double gYshift = 0; - //public static double gXmouse = 0; - //public static double gYmouse = 0; - - - //public static double gEQ_MAXSYNC = 0; // Max Sync Diff - //public static double gSiderealRate = 0; // Sidereal rate arcsecs/sec - //public static double gMount_Ver = 0; // Mount Version - //public static int gMount_Features = 0; // Mount Features - - //public static double gRA_LastRate = 0; // Last PEC Rate - //public static int gpl_interval = 0; // Pulseguide Interval - - //public static double eqres = 0; - //public static double gTot_step = 0; // Total Common RA-Encoder Steps - //public static double gTot_RA = 0; // Total RA Encoder Steps - //public static double gTot_DEC = 0; // Total DEC Encoder Steps - //public static double gRAWormSteps = 0; // Steps per RA worm revolution - //public static double gRAWormPeriod = 0; // Period of RA worm revolution - //public static double gDECWormSteps = 0; // Steps per DEC worm revolution - //public static double gDECWormPeriod = 0; // Period of DEC worm revolution - - //public static double gLatitude = 0; // Site Latitude - //public static double gLongitude = 0; // Site Longitude - //public static double gElevation = 0; // Site Elevation - //public static int gHemisphere = 0; - - //public static double gDECEncoder_Home_pos = 0; // DEC HomePos - Varies with different mounts - - //public static double gRA_Encoder = 0; // RA Current Polled RA Encoder value - //public static double gDec_Encoder = 0; // DEC Current Polled Encoder value - //public static double gRA_Hours = 0; // RA Encoder to Hour position - //public static double gDec_Degrees = 0; // DEC Encoder to Degree position Ranged to -90 to 90 - //public static double gDec_DegNoAdjust = 0; // DEC Encoder to actual degree position - //public static double gRAStatus = 0; // RA Polled Motor Status - //public static bool gRAStatus_slew = false; // RA motor tracking poll status - //public static double gDECStatus = 0; // DEC Polloed motor status - - //public static double gRA_Limit_East = 0; // RA Limit at East Side - //public static double gRA_Limit_West = 0; // RA Limit at West Side - - //public static double gRA1Star = 0; // Initial RA Alignment adjustment - //public static double gDEC1Star = 0; // Initial DEC Alignment adjustment - - //public static double gRASync01 = 0; // Initial RA sync adjustment - //public static double gDECSync01 = 0; // Initial DEC sync adjustment - - //public static double gRA = 0; - //public static double gDec = 0; - //public static double gAlt = 0; - //public static double gAz = 0; - //public static double gha = 0; - //public static double gSOP = 0; - - //public static string gPort = ""; - //public static int gBaud = 0; - //public static int gTimeout = 0; - //public static int gRetry = 0; - - //public static int gTrackingStatus = 0; - //public static bool gSlewStatus = false; - - //public static double gRAMoveAxis_Rate = 0; - //public static double gDECMoveAxis_Rate = 0; - - - //// Added for emulated Stepper Counters - //public static double gEmulRA = 0; - //public static double gEmulDEC = 0; - //public static bool gEmulOneShot = false; - //public static bool gEmulNudge = false; - - //public static double gCurrent_time = 0; - //public static double gLast_time = 0; - //public static double gEmulRA_Init = 0; - - //public enum PierSide2 - //{ - // pierUnknown2 = -1, - // PierEast2 = 0, - // PierWest2 = 1 - //} - - //public static PierSide2 gSideofPier = PierSide2.PierEast2; - - - //public static int gRAEncoderPolarHomeGoto = 0; - //public static int gDECEncoderPolarHomeGoto = 0; - //public static int gRAEncoderUNPark = 0; - //public static int gDECEncoderUNPark = 0; - //public static int gRAEncoderPark = 0; - //public static int gDECEncoderPark = 0; - //public static int gRAEncoderlastpos = 0; - //public static int gDECEncoderlastpos = 0; - //public static int gEQparkstatus = 0; - - //public static int gEQRAPulseDuration = 0; - //public static int gEQDECPulseDuration = 0; - //public static int gEQRAPulseEnd = 0; - //public static int gEQDECPulseEnd = 0; - //public static int gEQDECPulseStart = 0; - //public static int gEQRAPulseStart = 0; - //public static bool gEQPulsetimerflag = false; - - //public static double gEQTimeDelta = 0; - - - - //// Public variables for Custom Tracking rates - - //public static double gDeclinationRate = 0; - //public static double gRightAscensionRate = 0; - - - //// Public Variables for Spiral Slew - - //public static int gSPIRAL_JUMP = 0; - //public static double gDeclination_Start = 0; - //public static double gRightAscension_Start = 0; - //public static double gDeclination_Dir = 0; - //public static double gRightAscension_Dir = 0; - //public static int gDeclination_Len = 0; - //public static int gRightAscension_Len = 0; - - //public static double gSpiral_AxisFlag = 0; - - - - //// Public variables for debugging - - //public static double gAffine1 = 0; - //public static double gAffine2 = 0; - //public static double gAffine3 = 0; - - //public static double gTaki1 = 0; - //public static double gTaki2 = 0; - //public static double gTaki3 = 0; - - - ////Pulseguide Indicators - - //public const int gMAX_plotpoints = 100; - //public static int gMAX_RAlevel = 0; - //public static int gMAX_DEClevel = 0; - //public static int gPlot_ra_pos = 0; - //public static int gPlot_dec_pos = 0; - //public static double gplot_ra_cur = 0; - //public static double gPlot_dec_cur = 0; - //public static double gRAHeight = 0; - //public static double gDecHeight = 0; - - //// Polar Alignment Variables - - //public static double gPolarAlign_RA = 0; - //public static double gPolarAlign_DEC = 0; - - ////UPGRADE_NOTE: (2041) The following line was commented. More Information: https://www.mobilize.net/vbtonet/ewis/ewi2041 - //////UPGRADE_TODO: (1050) Structure SYSTEMTIME may require marshalling attributes to be passed as an argument in this Declare statement. More Information: https://www.mobilize.net/vbtonet/ewis/ewi1050 - ////[DllImport("kernel32.dll", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)] - ////extern public static void GetSystemTime(ref UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME lpSystemTime); - - - - private double Get_EncoderHours(long encoderPosition) - { - double pos = encoderPosition * 1d; - double hours; - - // Compute in Hours the encoder value based on 0 position value (RAOffset0) - // and Total 360 degree rotation microstep count (Tot_Enc - - if (pos > this.HomeEncoder.RA) - { - hours = ((pos - this.HomeEncoder.RA) / StepsPerRev.RA) * 24d; - hours = 24 - hours; - } - else - { - hours = ((this.HomeEncoder.RA - pos) / StepsPerRev.RA) * 24d; - } - - if (Hemisphere == HemisphereEnum.Northern) - { - return Range.Range24(hours + 6d); // Set to true Hours which is perpendicula to RA Axis - } - else - { - return Range.Range24((24 - hours) + 6d); - } - - } - - private long Get_EncoderfromHours(double hourval) - { - - hourval = Range.Range24(hourval - 6d); // Re-normalize from a perpendicular position - if (this.Hemisphere == HemisphereEnum.Northern) - { - if (hourval < 12) - { - return (long)Math.Round(this.HomeEncoder.RA - ((hourval / 24d) * this.StepsPerRev.RA)); - } - else - { - return (long)Math.Round((((24 - hourval) / 24d) * this.StepsPerRev.RA) + this.HomeEncoder.RA); - } - } - else - { - if (hourval < 12) - { - return (long)Math.Round(((hourval / 24d) * this.StepsPerRev.RA) + this.HomeEncoder.RA); - } - else - { - return (long)Math.Round(this.HomeEncoder.RA - (((24 - hourval) / 24d) * this.StepsPerRev.RA)); - } - } - - } - - private long Get_EncoderfromDegrees(double degval) - { - - if (this.Hemisphere == HemisphereEnum.Southern) - { - degval = 360 - degval; - } - if ((degval > 180)) // && (Pier == 0)) - { - return (long)Math.Round(this.HomeEncoder.Dec - (((360 - degval) / 360d) * this.StepsPerRev.Dec)); - } - else - { - return (long)Math.Round(((degval / 360d) * this.StepsPerRev.Dec) + this.HomeEncoder.Dec); - } - - } - - - private double Get_EncoderDegrees(long encoderPosition) - { - double pos = encoderPosition * 1.0d;// Convert to double to prevent truncation - double decDegrees = 0; - - // Compute in Hours the encoder value based on 0 position value (EncOffset0) - // and Total 360 degree rotation microstep count (Tot_Enc - - if (pos > this.HomeEncoder.Dec) - { - decDegrees = ((pos - this.HomeEncoder.Dec) / this.StepsPerRev.Dec) * 360d; - } - else - { - decDegrees = ((double)(this.HomeEncoder.Dec - pos) / this.StepsPerRev.Dec) * 360d; - decDegrees = 360 - decDegrees; - } - - if (this.Hemisphere == HemisphereEnum.Northern) - { - return Range.Range360(decDegrees); - } - else - { - return Range.Range360(360 - decDegrees); - } - } - - //// Function that will ensure that the DEC value will be between -90 to 90 - //// Even if it is set at the other side of the pier - - //private double Range_DEC(double decdegrees) - //{ - - // if ((decdegrees >= 270) && (decdegrees <= 360)) - // { - // return decdegrees - 360; - // } - - // if ((decdegrees >= 180) && (decdegrees < 270)) - // { - // return 180 - decdegrees; - // } - - // if ((decdegrees >= 90) && (decdegrees < 180)) - // { - // return 180 - decdegrees; - // } - - // return decdegrees; - - //} - - - - //internal int Get_RAEncoderfromRA(double ra_in_hours, double dec_in_degrees, double pLongitude, double encOffset0, double Tot_enc, int hmspr) - //{ - - - // double i = ra_in_hours - SiderealTime.GetLocalSiderealTime(SiteLongitude); // EQnow_lst(pLongitude * DEG_RAD); - - // if (hmspr == 0) - // { - // if ((dec_in_degrees > 90) && (dec_in_degrees <= 270)) - // { - // i -= 12d; - // } - // } - // else - // { - // if ((dec_in_degrees > 90) && (dec_in_degrees <= 270)) - // { - // i += 12d; - // } - // } - - // i = Range24(i); - - // return Get_EncoderfromHours(encOffset0, ref i, Tot_enc, hmspr); - - //} - - //private int Get_RAEncoderfromAltAz(double Alt_in_deg, double Az_in_deg, double pLongitude, double pLatitude, double encOffset0, double Tot_enc, int hmspr) - //{ - // object[,,,,] aa_hadec = null; - - // double ttha = 0; - // double ttdec = 0; - - // object tempAuxVar = aa_hadec[Convert.ToInt32(pLatitude * DEG_RAD), Convert.ToInt32(Alt_in_deg * DEG_RAD), Convert.ToInt32((360d - Az_in_deg) * DEG_RAD), Convert.ToInt32(ttha), Convert.ToInt32(ttdec)]; - // double i = (ttha * RAD_HRS); - // i = Range24(i); - // return Get_EncoderfromHours(encOffset0, ref i, Tot_enc, hmspr); - - //} - - //private int Get_DECEncoderfromAltAz(double Alt_in_deg, double Az_in_deg, double pLongitude, double pLatitude, double encOffset0, double Tot_enc, double Pier, int hmspr) - //{ - // object[,,,,] aa_hadec = null; - - // double ttha = 0; - // double ttdec = 0; - - // object tempAuxVar = aa_hadec[Convert.ToInt32(pLatitude * DEG_RAD), Convert.ToInt32(Alt_in_deg * DEG_RAD), Convert.ToInt32((360d - Az_in_deg) * DEG_RAD), Convert.ToInt32(ttha), Convert.ToInt32(ttdec)]; - // double i = ttdec * RAD_DEG; // tDec was in Radians - // if (Pier == 1) - // { - // i = 180 - i; - // } - // return Get_EncoderfromDegrees(encOffset0, ref i, Tot_enc, Pier, hmspr); - - //} - - //private int Get_DECEncoderfromDEC(double dec_in_degrees, double Pier, double encOffset0, double Tot_enc, int hmspr) - //{ - - - // double i = dec_in_degrees; - // if (Pier == 1) - // { - // i = 180 - i; - // } - // return Get_EncoderfromDegrees(encOffset0, ref i, Tot_enc, Pier, hmspr); - - //} - - //private string printhex(double inpval) - //{ - - // return " " + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF00000) / 1048576d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF0000) / 65536d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF000) / 4096d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF00) / 256d) & 0xF).ToString("X") + (Convert.ToInt32((Convert.ToInt32(inpval) & 0xF0) / 16d) & 0xF).ToString("X") + (Convert.ToInt32(inpval) & 0xF).ToString("X"); - - //} - - ////private string FmtSexa(double N, bool ShowPlus) - ////{ - //// string result = ""; - - //// string sg = "+"; // Assume positive - //// if (N < 0) - //// { // Check neg. - //// N = -N; // Make pos. - //// sg = "-"; // Remember sign - //// } - - //// int m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Units (deg or hr) - //// string us = StringsHelper.Format(m, "00"); - - //// N = (N - m) * 60d; - //// m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Minutes - //// string ms = StringsHelper.Format(m, "00"); - - //// N = (N - m) * 60d; - //// m = Convert.ToInt32((N > 0) ? Math.Floor(N) : Math.Ceiling(N)); // Minutes - //// string ss = StringsHelper.Format(m, "00"); - - //// result = us + ":" + ms + ":" + ss; - //// if (ShowPlus || (sg == "-")) - //// { - //// result = sg + result; - //// } - - //// return result; - ////} - - ////private double EQnow_lst(double plong) - ////{ - //// object mjd_hr = null; - //// object mjd_day = null; - //// double[] vb_mjd = null; - //// object[, ] obliq = null; - //// double[] radhr = null; - //// object[, ] range = null; - //// object[, , ] utc_gst = null; - //// object[, , ] nut = null; - - //// UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME typTime = new UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME(); - //// double eps = 0; - //// double lst = 0; - //// double deps = 0; - //// double dpsi = 0; - - //// // mjd = vb_mjd(CDbl(Now) + gGPSTimeDelta) - - //// UpgradeSolution1Support.PInvoke.SafeNative.kernel32.GetSystemTime(ref typTime); - //// double mjd = vb_mjd[Convert.ToInt32(DateTime.Now.AddDays(gEQTimeDelta).AddDays(typTime.wMilliseconds / 86400000d).ToOADate())]; - //// object tempAuxVar = utc_gst[ReflectionHelper.GetPrimitiveValue(((Array) mjd_day).GetValue(Convert.ToInt32(mjd))), ReflectionHelper.GetPrimitiveValue(((Array) mjd_hr).GetValue(Convert.ToInt32(mjd))), Convert.ToInt32(lst)]; - //// lst += radhr[Convert.ToInt32(plong)]; - //// object tempAuxVar2 = obliq[Convert.ToInt32(mjd), Convert.ToInt32(eps)]; - //// object tempAuxVar3 = nut[Convert.ToInt32(mjd), Convert.ToInt32(deps), Convert.ToInt32(dpsi)]; - //// lst += radhr[Convert.ToInt32(dpsi * Math.Cos(eps + deps))]; - //// object tempAuxVar4 = range[Convert.ToInt32(lst), 24L]; - - //// return lst; - //// // EQnow_lst = now_lst(plong) - - ////} - - - ////private double EQnow_lst_norange() - ////{ - - //// UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME typTime = new UpgradeSolution1Support.PInvoke.UnsafeNative.Structures.SYSTEMTIME(); - - //// UpgradeSolution1Support.PInvoke.SafeNative.kernel32.GetSystemTime(ref typTime); - //// double mjd = (typTime.wMinute * 60) + (typTime.wSecond) + (typTime.wMilliseconds / 1000d); - //// double MTMP = (typTime.wHour); - //// MTMP *= 3600; - //// mjd = mjd + MTMP + (typTime.wDay * 86400); - - //// return mjd; - - ////} - - - ////private double EQnow_lst_time(double plong, double ptime) - ////{ - //// object mjd_hr = null; - //// object mjd_day = null; - //// double[] vb_mjd = null; - //// object[, ] obliq = null; - //// double[] radhr = null; - //// object[, ] range = null; - //// object[, , ] utc_gst = null; - //// object[, , ] nut = null; - - //// double eps = 0; - //// double lst = 0; - //// double deps = 0; - //// double dpsi = 0; - - //// double mjd = vb_mjd[Convert.ToInt32(ptime)]; - //// object tempAuxVar = utc_gst[ReflectionHelper.GetPrimitiveValue(((Array) mjd_day).GetValue(Convert.ToInt32(mjd))), ReflectionHelper.GetPrimitiveValue(((Array) mjd_hr).GetValue(Convert.ToInt32(mjd))), Convert.ToInt32(lst)]; - //// lst += radhr[Convert.ToInt32(plong)]; - //// object tempAuxVar2 = obliq[Convert.ToInt32(mjd), Convert.ToInt32(eps)]; - //// object tempAuxVar3 = nut[Convert.ToInt32(mjd), Convert.ToInt32(deps), Convert.ToInt32(dpsi)]; - //// lst += radhr[Convert.ToInt32(dpsi * Math.Cos(eps + deps))]; - //// object tempAuxVar4 = range[Convert.ToInt32(lst), 24L]; - - //// return lst; - - ////} - - - //private PierSide2 SOP_DEC(double DEC) - //{ - - // DEC = Math.Abs(DEC - 180); - - // if (DEC <= 90) - // { - // return PierSide2.PierEast2; - // } - // else - // { - // return PierSide2.PierWest2; - // } - - //} - - ////private PierSide2 SOP_Physical(double vha) - ////{ - //// object gAscomCompatibility = null; - - //// double ha = RangeHA(vha - 6d); - - //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPhysicalSideOfPier")) - //// { - //// return (ha >= 0) ? PierSide2.PierWest2 : PierSide2.PierEast2; - //// } - //// else - //// { - //// return (ha >= 0) ? PierSide2.PierEast2 : PierSide2.PierWest2; - //// } - - - - ////} - - ////private PierSide2 SOP_Pointing(double DEC) - ////{ - //// PierSide2 result = PierSide2.PierEast2; - //// object gAscomCompatibility = null; - - //// if (DEC <= 90 || DEC >= 270) - //// { - //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPointingSideOfPier")) - //// { - //// result = PierSide2.PierEast2; - //// } - //// else - //// { - //// result = PierSide2.PierWest2; - //// } - //// } - //// else - //// { - //// if (ReflectionHelper.GetMember(gAscomCompatibility, "SwapPointingSideOfPier")) - //// { - //// result = PierSide2.PierWest2; - //// } - //// else - //// { - //// result = PierSide2.PierEast2; - //// } - //// } - - //// // in the south east is west and west is east! - //// if (gHemisphere == 1) - //// { - //// if (result == PierSide2.PierWest2) - //// { - //// result = PierSide2.PierEast2; - //// } - //// else - //// { - //// result = PierSide2.PierWest2; - //// } - //// } - - //// return result; - ////} - ////private PierSide2 SOP_RA(double vRA, double pLongitude) - ////{ - - //// double i = vRA - EQnow_lst(pLongitude * DEG_RAD); - //// i = RangeHA(i - 6d); - //// return (i < 0) ? PierSide2.PierEast2 : PierSide2.PierWest2; - - ////} - - //private double Range24(double vha) - //{ - - // while (vha < 0d) - // { - // vha += 24d; - // } - // while (vha >= 24d) - // { - // vha -= 24d; - // } - - // return vha; - - //} - - //private double Range360(double vdeg) - //{ - - // while (vdeg < 0d) - // { - // vdeg += 360d; - // } - // while (vdeg >= 360d) - // { - // vdeg -= 360d; - // } - - // return vdeg; - - //} - //private double Range90(double vdeg) - //{ - - // while (vdeg < -90d) - // { - // vdeg += 360d; - // } - // while (vdeg >= 360d) - // { - // vdeg -= 90d; - // } - - // return vdeg; - - //} - - - //private double GetSlowdown(double deltaval) - //{ - - // double i = deltaval - 80000; - // if (i < 0) - // { - // i = deltaval * 0.5d; - // } - // return i; - - //} - - private long Delta_RA_Map(long raEncoder) - { - - return raEncoder + this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) - - } - - private long Delta_DEC_Map(long decEncoder) - { - - return decEncoder + this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) - - } - - private MapResult Delta_Map(EncoderPosition original) - { - return new MapResult() - { - EncoderPosition = new EncoderPosition(Delta_RA_Map(original.RA), Delta_DEC_Map(original.Dec)) - }; - } - - private long DeltaReverse_RA_Map(long raTarget) - { - - return raTarget - this._oneStarAdjustment.RA; // + gRASync01 (Eqmod has an ASCOM Sync mode which would set this value) - - } - - private long DeltaReverse_DEC_Map(long decTarget) - { - - return decTarget - this._oneStarAdjustment.Dec; // + gDECSync01 (Eqmod has an ASCOM Sync mode which would set this value) - - } - - private MapResult DeltaReverse_Map(EncoderPosition original) - { - return new MapResult() - { - EncoderPosition = new EncoderPosition(DeltaReverse_RA_Map(original.RA), DeltaReverse_DEC_Map(original.Dec)) - }; - } - - - private MapResult Delta_Matrix_Map(EncoderPosition pos) - { - MapResult result = new MapResult(); - - if ((pos.RA >= 0x1000000) || (pos.Dec >= 0x1000000)) - { - result.EncoderPosition = new EncoderPosition(pos.RA, pos.Dec); - return result; - } - - // re transform based on the nearest 3 stars - bool inTriangle = EQ_UpdateTaki(pos); - - EncoderPosition obtmp2 = EQ_plTaki(pos); - result.EncoderPosition = new EncoderPosition(obtmp2.RA, obtmp2.Dec); - result.InTriangle = inTriangle; - - return result; - } - - - private MapResult Delta_Matrix_Reverse_Map(EncoderPosition pos) - { - - MapResult result = new MapResult(); - - if ((pos.RA >= 0x1000000) || (pos.Dec >= 0x1000000)) - { - result.EncoderPosition = new EncoderPosition(pos.RA, pos.Dec); - return result; - } - - - // re transform using the 3 nearest stars - bool inTriangle = EQ_UpdateAffine(pos); - EncoderPosition obtmp2 = EQ_plAffine(pos); - - result.EncoderPosition = new EncoderPosition(obtmp2.RA, obtmp2.Dec); - result.InTriangle = inTriangle; - - - return result; - } - - /// - /// Maps an encoder position to the calculate target position - /// - /// - /// - private MapResult DeltaSync_Matrix_Map(EncoderPosition encoderPosition) - { - MapResult result = new MapResult(); - - if ((encoderPosition.RA >= 0x1000000) || (encoderPosition.Dec >= 0x1000000)) - { - result.EncoderPosition = encoderPosition; - } - else - { - this.SelectedAlignmentPoint = GetNearest(encoderPosition); - if (this.SelectedAlignmentPoint != null) - { - result.EncoderPosition = new EncoderPosition( - encoderPosition.RA + (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA), // + gRASync01; - encoderPosition.Dec + (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec) - ); // + gDecSync01; - // result.z = 1; - // result.f = 0; - } - else - { - result.EncoderPosition = encoderPosition; - // result.z = 0; - // result.f = 0; - } - } - return result; - } - - /// - /// Reverse map from an aligned target position to the encoder position - /// - /// - /// - private MapResult DeltaSyncReverse_Matrix_Map(EncoderPosition targetPosition) - { - MapResult result = new MapResult(); - - if ((targetPosition.RA >= 0x1000000) || (targetPosition.Dec >= 0x1000000) || this.AlignmentPoints.Count == 0) - { - result.EncoderPosition = targetPosition; - } - else - { - this.SelectedAlignmentPoint = GetNearest(targetPosition); - if (this.SelectedAlignmentPoint != null) - { - result.EncoderPosition = new EncoderPosition( - targetPosition.RA - (this.SelectedAlignmentPoint.Target.RA - this.SelectedAlignmentPoint.Encoder.RA), // + gRASync01; - targetPosition.Dec - (this.SelectedAlignmentPoint.Target.Dec - this.SelectedAlignmentPoint.Encoder.Dec) - ); - } - else - { - result.EncoderPosition = targetPosition; - } - } - return result; - } - - //TODO: Improve GetQuadrant to return an Enum value (NW, NE, SW or SE) instead of an int. - - /// - /// Returns a quadrant based on a cartesean coordinate - /// - /// - /// - private int GetQuadrant(Coord tmpcoord) - { - int ret = 0; - - if (tmpcoord.x >= 0) - { - if (tmpcoord.y >= 0) - { - ret = 0; - } - else - { - ret = 1; - } - } - else - { - if (tmpcoord.y >= 0) - { - ret = 2; - } - else - { - ret = 3; - } - } - - return ret; - - } - - - /// - /// Return the nearest alignment point to an encoder position - /// - /// - /// - private AlignmentPoint GetNearest(EncoderPosition pos) - { - Dictionary distances = new Dictionary(); - int[] datholder2 = new int[this.AlignmentPoints.Count]; - - Coord posCartesean = EQ_sp2Cs(pos); - - foreach (AlignmentPoint pt in this.AlignmentPoints) - { - switch (ActivePoints) - { - case ActivePointsEnum.All: - // all points - break; - case ActivePointsEnum.PierSide: - // only consider points on this side of the meridian - if (pt.EncoderCartesian.y * posCartesean.y < 0) - { - continue; - } - break; - case ActivePointsEnum.LocalQuadrant: - // local quadrant - if (GetQuadrant(posCartesean) != GetQuadrant(pt.EncoderCartesian)) - { - continue; - } - break; - } - - if (CheckLocalPier) - { - // calculate polar distance - distances.Add(pt.Id, Math.Pow(pt.Encoder.RA - pos.RA, 2) + Math.Pow(pt.Encoder.Dec - pos.Dec, 2)); - } - else - { - // calculate cartesian disatnce - distances.Add(pt.Id, Math.Pow(pt.EncoderCartesian.x - posCartesean.x, 2) + Math.Pow(pt.EncoderCartesian.y - posCartesean.y, 2)); - } - } - - if (distances.Count == 0) - { - return null; - } - else - { - int nearestId = distances.OrderBy(kvp => kvp.Value).Select(kvp => kvp.Key).First(); - return AlignmentPoints.FirstOrDefault(pt => pt.Id == nearestId); - } - - } - - - } -} - - diff --git a/EqmodNStarAlignment/Model/AlignmentPoint.cs b/EqmodNStarAlignment/Model/AlignmentPoint.cs deleted file mode 100644 index dba7304b..00000000 --- a/EqmodNStarAlignment/Model/AlignmentPoint.cs +++ /dev/null @@ -1,140 +0,0 @@ -using EqmodNStarAlignment.DataTypes; -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; -using System.ComponentModel; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Text; - -namespace EqmodNStarAlignment.Model -{ - public class AlignmentPoint : INotifyPropertyChanged - { - /// - /// Unique ID for alignment point - /// - public int Id { get; set; } - - /// - /// Alignment date and time of the sync - /// - public DateTime AlignTime { get; set; } - - /// - /// The Encoder positions at sync time - /// - public EncoderPosition Encoder { get; set; } - - /// - /// The Cartesian equivalent of the EncoderPosition - /// - public Coord EncoderCartesian { get; set; } - - - /// - /// The Target Ra/Dec in hours/degrees - /// - public AxisPosition OrigRaDec { get; set; } - - - /// - /// The unadjusted encoder positions - /// - public EncoderPosition Target { get; set; } - - /// - /// The cartesean version of the unadjusted encoder positions - /// - public Coord TargetCartesian { get; set; } - - [JsonIgnore] - public EncoderPosition Delta => (Target - Encoder); - - - [JsonIgnore] - public string Synched => $"{AlignTime:G}"; - - private bool _selected; - - /// - /// Selected for correcting display - /// - [JsonIgnore] - public bool Selected - { - get => _selected; - set - { - if (value == _selected) return; - _selected = value; - OnPropertyChanged(); - } - } - - private bool _selectedForGoto; - - /// - /// Selected for slew/goto calculation - /// - [JsonIgnore] - public bool SelectedForGoto - { - get => _selectedForGoto; - set - { - if (value == _selectedForGoto) return; - _selectedForGoto = value; - OnPropertyChanged(); - } - } - - - public AlignmentPoint() - { - - } - - public AlignmentPoint(long[] encoder, double[] origRaDec, long[] target, DateTime syncTime) - { - Encoder = new EncoderPosition(encoder); - OrigRaDec = new AxisPosition(origRaDec); - Target = new EncoderPosition(target); - AlignTime = syncTime; - } - - #region INotifyPropertyChanged interface ... - public event PropertyChangedEventHandler PropertyChanged; - - protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } - #endregion - - } - - public class AlignmentPointCollection : ObservableCollection - { - protected override void InsertItem(int index, AlignmentPoint item) - { - if (item != null && item.Id == 0) - { - if (Items.Any()) - { - item.Id = Items.Max(i => i.Id) + 1; - } - else - { - item.Id = 1; - } - } - base.InsertItem(index, item); - } - - - } - - -} diff --git a/EqmodNStarAlignment/Properties/AssemblyInfo.cs b/EqmodNStarAlignment/Properties/AssemblyInfo.cs deleted file mode 100644 index cd38b6a1..00000000 --- a/EqmodNStarAlignment/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("EqmodNStarAlignment")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("EqmodNStarAlignment")] -[assembly: AssemblyCopyright("Copyright © 2022")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("2b12e1e9-a2bb-4fa8-9e49-4888b2874233")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/EqmodNStarAlignment/Resources/ASCOM.snk b/EqmodNStarAlignment/Resources/ASCOM.snk deleted file mode 100644 index 5b911b2dd45ff55f837f84759f53f5684dbae07d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 596 zcmV-a0;~N80ssI2Bme+XQ$aES1ONa500986qTcbIbGIsd@kxk`lk9?xw_Z(18(d{7 zq%;?&c8SiBQH4C=0(itr|4OA^o4OCb;U~R zn@*akkTPyBlA4(cTw%6(RzpMoAyj?|ZLz5iP(hp$!;oYah9?09Vh>UMeU$H1zV7JN zNKHfH*e=}%t5noW{9Y56(0dtniA@C{okBzV#FovIIT9fiPC!oU+!<#VNXI-Lq7;@W zkvbyA`Qj1TcB1`rzmP#0CKrlWIY_O?=rna3DoT?rlsK=2;65r?>95VAa6lM#$Np5N z5bd5^vHVrAjbf-nfGJ#7UxNw3+8XQSg{d|+hJEG5y;|mnlkXw)93|`l{vh5q9PenAhY4?(uF;IQ8d93Xi#Y*be_?|ovHm^m2^0bBmK@g8(s$y^? zx7YiBvQ8?2`4Wceb0XE}sR<_6S(LibU;|fyvFDfjYOYzAM2Ge>n(R%2g#0}Fc6AXB4FC9Gq diff --git a/EqmodNStarAlignment/Utilities/AstroConvert.cs b/EqmodNStarAlignment/Utilities/AstroConvert.cs deleted file mode 100644 index 14a4feea..00000000 --- a/EqmodNStarAlignment/Utilities/AstroConvert.cs +++ /dev/null @@ -1,184 +0,0 @@ -/* -MIT License - -Copyright (c) 2017 Phil Crompton - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - Portions - Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -*/ - -using System; -using System.Diagnostics; -using System.Runtime.InteropServices; - -namespace EqmodNStarAlignment.Utilities -{ - - public static class AstroConvert - { - /// - /// Radians per degree - /// - private const double DegRad = 0.0174532925; // Radians per degree - /// - /// Degrees per radian - /// - private const double RadDeg = 57.2957795; // Degrees per Radian - - /// - /// Radians per hour - /// - private const double HrsRad = 0.2617993881; // Radians per hour - - #region Unit convertsions ... - - public static double DegToRad(double degrees) { return (degrees * DegRad); } - public static double HrsToRad(double hours) { return (hours * HrsRad); } - - public static double RadToHrs(double radians) { return (radians / HrsRad); } - - public static double RadToDeg(double rad) { return (rad * RadDeg); } - - #endregion - - #region Astro32.dll functions ... - /* - * The methods in this region are created using the code that I believe was originally used - * to create the astro32.dll that was shipped with EQMOD. - * Source: http://mmto.org/~dclark/Reports/MountDoxygen/html/aa__hadec_8c_source.html - */ - - static double lastLatitide; - static double sinLatitude = 0.0; - static double cosLatitude = 0.0; - - - /* given geographical latitude (n+, radians), lt, altitude (up+, radians), - * alt, and azimuth (angle round to the east from north+, radians), - * return hour angle (radians), ha, and declination (radians), dec. - * Originally called aa_hadec - */ - - public static double[] GetHaDec(double lt, double alt, double az) - { - double ha = 0d, dec = 0d; - aaha_aux(lt, az, alt, ref ha, ref dec); - if (ha > Math.PI) - ha -= 2 * Math.PI; - return new double[] { ha, dec }; - } - - /* given geographical (n+, radians), lt, hour angle (radians), ha, and - * declination (radians), dec, return altitude (up+, radians), alt, and - * azimuth (angle round to the east from north+, radians), - * Originally caled hadec_aa - */ - public static double[] GetAltAz(double lt, double ha, double dec) - { - double alt = 0d, az = 0d; - aaha_aux(lt, ha, dec, ref az, ref alt); - return new double[] { alt, az }; - } - - static void aaha_aux(double latitude, double x, double y, ref double p, ref double q) - { - lastLatitide = double.MinValue; - double cap = 0.0; - double B = 0.0; - - if (latitude != lastLatitide) - { - sinLatitude = Math.Sin(latitude); - cosLatitude = Math.Cos(latitude); - lastLatitide = latitude; - } - - solve_sphere(-x, Math.PI / 2 - y, sinLatitude, cosLatitude, ref cap, ref B); - p = B; - q = Math.PI / 2 - Math.Acos(cap); - } - - /* solve a spherical triangle: - * A - * / \ - * / \ - * c / \ b - * / \ - * / \ - * B ____________ C - * a - * - * given A, b, c find B and a in range 0..B..2PI and 0..a..PI, respectively.. - * cap and Bp may be NULL if not interested in either one. - * N.B. we pass in cos(c) and sin(c) because in many problems one of the sides - * remains constant for many values of A and b. - */ - static void solve_sphere(double A, double b, double cc, double sc, ref double cap, ref double Bp) - { - double cb = Math.Cos(b), sb = Math.Sin(b); - double sA, cA = Math.Cos(A); - double x, y; - double ca; - double B; - - ca = cb * cc + sb * sc * cA; - if (ca > 1.0) - { - ca = 1.0; - } - if (ca < -1.0) - { - ca = -1.0; - } - cap = ca; - - if (sc < 1e-7) - { - B = cc < 0 ? A : Math.PI - A; - } - else - { - sA = Math.Sin(A); - y = sA * sb * sc; - x = cb - ca * cc; - B = Math.Atan2(y, x); - } - - Bp = Range.ZeroToValue(B, Math.PI * 2); - } - #endregion - - } -} diff --git a/EqmodNStarAlignment/Utilities/EnumTypeConverter.cs b/EqmodNStarAlignment/Utilities/EnumTypeConverter.cs deleted file mode 100644 index 7e2a1cb2..00000000 --- a/EqmodNStarAlignment/Utilities/EnumTypeConverter.cs +++ /dev/null @@ -1,57 +0,0 @@ -using System; -using System.ComponentModel; -using System.Globalization; -using System.Reflection; - -namespace EqmodNStarAlignment.Utilities -{ - public class EnumTypeConverter : EnumConverter - { - private Type m_EnumType; - public EnumTypeConverter(Type type) - : base(type) - { - m_EnumType = type; - } - - public override bool CanConvertTo(ITypeDescriptorContext context, Type destType) - { - return destType == typeof(string); - } - - public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destType) - { - DescriptionAttribute dna = null; - if (value != null) - { - FieldInfo fi = m_EnumType.GetField(Enum.GetName(m_EnumType, value)); - dna = - (DescriptionAttribute)Attribute.GetCustomAttribute( - fi, typeof(DescriptionAttribute)); - } - if (dna != null) - return dna.Description; - else - return (value != null ? value.ToString() : ""); - } - - public override bool CanConvertFrom(ITypeDescriptorContext context, Type srcType) - { - return srcType == typeof(string); - } - - public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) - { - foreach (FieldInfo fi in m_EnumType.GetFields()) - { - DescriptionAttribute dna = - (DescriptionAttribute)Attribute.GetCustomAttribute( - fi, typeof(DescriptionAttribute)); - - if ((dna != null) && ((string)value == dna.Description)) - return Enum.Parse(m_EnumType, fi.Name); - } - return Enum.Parse(m_EnumType, (string)value ?? string.Empty); - } - } -} diff --git a/EqmodNStarAlignment/Utilities/Range.cs b/EqmodNStarAlignment/Utilities/Range.cs deleted file mode 100644 index ab816ebc..00000000 --- a/EqmodNStarAlignment/Utilities/Range.cs +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright(C) 2019-2022 Rob Morgan (robert.morgan.e@gmail.com), - Phil Crompton (phil@unitysoftware.co.uk) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; - -namespace EqmodNStarAlignment.Utilities -{ - /// - /// Forces parameters to be within a certain range - /// - /// Attention to the order of parameters (AltAz vs AzAlt) in the method names - public static class Range - { - ///* insure 0 <= *v < r. - // 233 void - // 234 range(double* v, double r) - // 235 { - // 236 *v -= r* floor(*v/r); - // 237 } - public static double ZeroToValue(double d, double range) - { - while ((d >= range) || (d < 0.0)) - { - if (d < 0.0) d += range; - if (d >= range) d -= range; - } - return d; - - } - - /// - /// Returns double in the range -12 to +12 - /// - /// 90.169444444444451 - /// -5.8305555555555486 - public static double Range12(double d) - { - while ((d > 12.0) || (d <= -12.0)) - { - if (d <= -12.0) d += 24.0; - if (d > 12.0) d -= 24.0; - } - return d; - } - - /// - /// Returns double in the range 0 to 24.0 - /// - /// 90.169444444444451 - /// 18.169444444444451 - public static double Range24(double d) - { - while ((d >= 24.0) || (d < 0.0)) - { - if (d < 0.0) d += 24.0; - if (d >= 24.0) d -= 24.0; - } - return d; - } - - /// - /// Returns double in the range -90 to 90 - /// - /// 90.169444444444451 - /// 89.830555555555549 - public static double Range90(double d) - { - while ((d > 90.0) || (d < -90.0)) - { - if (d < -90.0) d += 180.0; - if (d > 90.0) d = 180.0 - d; - } - return d; - } - - /// - /// Returns double in the range 0 to 360 - /// - /// 590.169444444444451 - /// 230.16944444444448 - public static double Range360(double d) - { - while ((d >= 360.0) || (d < 0.0)) - { - if (d < 0.0) d += 360.0; - if (d >= 360.0) d -= 360.0; - } - return d; - } - - /// - /// Returns double in the range -180 to 180 - /// - /// 590.169444444444451 - /// 230.16944444444448 - public static double RangePlusOrMinus180(double d) - { - while (d <= 180.0) - { - d = d + 360.0; - } - - while (d > 180) - { - d = d - 360.0; - } - return d; - } - - public static double RangeHa(double ha) - { - - while (ha < -12d) - { - ha += 24d; - } - while (ha >= 12d) - { - ha -= 24d; - } - - return ha; - - } - - } -} diff --git a/EqmodNStarAlignment/Utilities/SiderealTime.cs b/EqmodNStarAlignment/Utilities/SiderealTime.cs deleted file mode 100644 index 75ff83a0..00000000 --- a/EqmodNStarAlignment/Utilities/SiderealTime.cs +++ /dev/null @@ -1,22 +0,0 @@ -using GS.Principles; -using System; -using System.Collections.Generic; -using System.Text; - -namespace EqmodNStarAlignment.Utilities -{ - public static class SiderealTime - { - public static double GetLocalSiderealTime(double longitude) - { - return GetLocalSiderealTime(HiResDateTime.UtcNow, longitude); - } - - public static double GetLocalSiderealTime(DateTime utcNow, double longitude) - { - var gsjd = JDate.Ole2Jd(utcNow); - return Time.Lst(JDate.Epoch2000Days(), gsjd, false, longitude); - } - - } -} diff --git a/NStarAlignment.Tests/MatrixTests.cs b/NStarAlignment.Tests/MatrixTests.cs deleted file mode 100644 index 5bfdc53e..00000000 --- a/NStarAlignment.Tests/MatrixTests.cs +++ /dev/null @@ -1,79 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using System; -using NStarAlignment.DataTypes; -using NStarAlignment.Model; - -namespace NStarAlignment.Tests -{ - [TestClass] - public class MatrixTests - { - [TestMethod] - public void TestInvert() - { - double[][] values = new[] - { - new[] {1.00000, 18894.75675, 14226.78803}, - new[] {1.00000, 12831.49749, 16721.15369}, - new[] {1.00000, 9661.92668, 13113.96006} - }; - double[][] expectedValues = new[] - { - new[] {0.225445485, -3.705052597, 4.479607112}, - new[] {0.000121139, -0.000037372, -0.000083767}, - new[] {-0.000106442, 0.000310061, -0.000203619} - }; - - - Matrix initial = Matrix.CreateInstance(values); - System.Diagnostics.Debug.WriteLine(initial.ToString()); - Matrix expected = Matrix.CreateInstance(expectedValues); - System.Diagnostics.Debug.WriteLine(expected.ToString()); - - Matrix inverse = initial.Invert(); - System.Diagnostics.Debug.WriteLine(inverse.ToString()); - Assert.IsTrue(inverse.IsEqualTo(expected, 0.0001)); - } - - - [TestMethod] - public void TestSolveNormalEquation() - { - double[][] featuresData = new[] - { - new[] {1.00000, 18894.75675, 14226.78803}, - new[] {1.00000, 12831.49749, 16721.15369}, - new[] {1.00000, 9661.92668, 13113.96006} - }; - - double[][] valuesdata = new[] - { - new[] {2.1449, 2.1487}, - new[] {3.1759, 1.5399}, - new[] {4.9241, 1.6036} - }; - - double[][] expectedData = new[] - { - new[] {10.77471486, 1.962502184}, - new []{-0.00027134, 0.000068413}, - new []{-0.00024623, -0.000077773 } - }; - Matrix samples = Matrix.CreateInstance(featuresData); - Matrix values = Matrix.CreateInstance(valuesdata); - Matrix expected = Matrix.CreateInstance(expectedData); - Matrix result = AlignmentModel.SolveNormalEquation(samples, values); - System.Diagnostics.Debug.WriteLine(samples.ToString()); - System.Diagnostics.Debug.WriteLine(values.ToString()); - System.Diagnostics.Debug.WriteLine(expected.ToString()); - System.Diagnostics.Debug.WriteLine(result.ToString()); - Assert.IsTrue(result.IsEqualTo(expected, 0.0001)); - - - } - } -} - - - - diff --git a/NStarAlignment.Tests/NStarAlignment.Tests.csproj b/NStarAlignment.Tests/NStarAlignment.Tests.csproj deleted file mode 100644 index 2ff63f60..00000000 --- a/NStarAlignment.Tests/NStarAlignment.Tests.csproj +++ /dev/null @@ -1,80 +0,0 @@ - - - - - - Debug - AnyCPU - {9086D8E2-53F8-4432-8AFF-32B675B14EE7} - Library - Properties - NStarAlignment.Tests - NStarAlignment.Tests - v4.7.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 15.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - ..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.dll - - - ..\packages\MSTest.TestFramework.2.1.0\lib\net45\Microsoft.VisualStudio.TestPlatform.TestFramework.Extensions.dll - - - - - - - - - - - - - - - - - - {1d17f8ba-f10f-493e-a7b5-941510a59679} - NStarAlignment - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - \ No newline at end of file diff --git a/NStarAlignment.Tests/NStarTriangleCentre.cs b/NStarAlignment.Tests/NStarTriangleCentre.cs deleted file mode 100644 index c811cd44..00000000 --- a/NStarAlignment.Tests/NStarTriangleCentre.cs +++ /dev/null @@ -1,182 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NStarAlignment.Model; -using System; -using NStarAlignment.DataTypes; - -namespace NStarAlignment.Tests -{ - [TestClass] - public class NStarTriangleCentre - { - private const double latitude = 52.6666666666667; - private const double longitude = -1.33333333333333; - private const double elevation = 201.0; - private const double tolerance = 0.05; - - private AlignmentModel model; - private TimeSpan utcOffset; - [TestInitialize] - public void Initialise() - { - model = new AlignmentModel(latitude, longitude, elevation) - { - IsAlignmentOn = true - }; - model.ClearAlignmentPoints(); - utcOffset = new TimeSpan(); - - // NW - DateTime syncTime = new DateTime(2020, 06, 28, 16, 43, 18); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 1.45234227180481, 60.3347473144531 }, new double[] { 144.945062700193, 60.3347473144531 }, new double[] { 149.723756536623, 59.1249432487836 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 43, 48); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 2.86930561065674, 55.9740562438965 }, new double[] { 123.819627432618, 55.9740562438965 }, new double[] { 128.404096999038, 55.283421763509 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 44, 08); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 2.08612251281738, 72.5127334594727 }, new double[] { 135.650906194933, 72.5127334594727 }, new double[] { 143.329091832532, 71.5666812294945 }, time); - //model.AddAlignmentPoint(new double[]{1.93080902099609, 63.763801574707}, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - //// SW - - syncTime = new DateTime(2020, 06, 28, 16, 45, 06); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 7.5975866317749 , 31.8432216644287 }, new double[] { 53.2216111482121, 31.8432216644287 }, new double[] { 56.0429603483716, 31.4201609110561 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 45, 43); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 5.93735456466675, 7.40935134887695}, new double[] { 78.2768689906225, 7.40935134887695 }, new double[] { 81.0690819058243, 7.01751946987766 },time); - - syncTime = new DateTime(2020, 06, 28, 16, 46, 09); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 7.67223644256592, 5.17215204238892}, new double[] { 52.3623042968102, 5.17215204238892 }, new double[] { 54.9750315780859, 4.46534644056118 }, time); - // model.AddAlignmentPoint(new double[]{7.32045793533325, 16.5029945373535}, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - ////SE - - syncTime = new DateTime(2020, 06, 28, 16, 47, 51); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 13.0530576705933, 10.8525428771973 }, new double[] { 152.075877884869, 169.147457122803 }, new double[] { 152.72162571714, 171.563163746142 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 48, 09); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 12.3489561080933, -0.778456687927246 }, new double[] { 162.71580699319, 180.778456687927 }, new double[] { 163.926678775838, 183.082432087453 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 48, 28); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 13.5954742431641, -0.697973549365997 }, new double[] { 144.097740196623, 180.697973549366 }, new double[] { 144.925319826158, 183.236913318592 }, time); - // model.AddAlignmentPoint(new double[]{12.9437046051025, 3.28892135620117}, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - ////NE - - syncTime = new DateTime(2020, 06, 28, 16, 51, 39); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 16.405143737793, 61.4716148376465 }, new double[] { 102.750476080924, 118.528385162354 }, new double[] { 100.26112572701, 120.586627285499 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 52, 00); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 15.4235200881958, 58.8995513916016 }, new double[] { 117.558254360687, 121.100448608398 }, new double[] { 114.734222729235, 122.861582942981 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 52, 22); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 15.9716958999634, 54.6963729858398 }, new double[] { 109.430551501457, 125.30362701416 }, new double[] { 107.541470813369, 127.418045303378 }, time); - // model.AddAlignmentPoint(new double[]{16.0384006500244, 58.5149154663086}, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - } - - [TestMethod] - public void TestSyncedNW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 44, 27); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(1.93080902099609, 63.763801574707, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 138.060159151908, 63.763801574707 }, time); - double[] expectedAxis = new double[] { 143.482011096669, 62.7368181631223 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSyncedSW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 46, 31); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(7.32045793533325, 16.5029945373535, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 57.7312421342358, 16.5029945373535 }, time); - double[] expectedAxis = new double[] { 60.4098738774835, 15.9579469987893 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSynchedSE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 48, 45); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(12.9437046051025, 3.28892135620117, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 153.945157337934, 176.711078643799 }, time); - double[] expectedAxis = new double[] { 154.854211281482, 179.129744501857 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSynchedNE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 52, 43); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(16.0384006500244, 58.5149154663086, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 108.51725186361, 121.485084533691 }, time); - double[] expectedAxis = new double[] { 106.174079618103, 123.499884590653 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalNW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 44, 27); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(1.93080902099609, 63.763801574707, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 143.482011096669, 62.7368181631223 }, time); - double[] expectedAxis = new double[] { 138.060159151908, 63.763801574707 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalSW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 46, 31); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(7.32045793533325, 16.5029945373535, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 60.4098738774835, 15.9579469987893 }, time); - double[] expectedAxis = new double[] { 57.7312421342358, 16.5029945373535 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalSE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 48, 45); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(12.9437046051025, 3.28892135620117, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 154.854211281482, 179.129744501857 }, time); - double[] expectedAxis = new double[] { 153.945157337934, 176.711078643799 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalNE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 52, 43); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(16.0384006500244, 58.5149154663086, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 106.174079618103, 123.499884590653 }, time); - double[] expectedAxis = new double[] { 108.51725186361, 121.485084533691 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - } -} diff --git a/NStarAlignment.Tests/NearestTriangleCentre.cs b/NStarAlignment.Tests/NearestTriangleCentre.cs deleted file mode 100644 index f8aee284..00000000 --- a/NStarAlignment.Tests/NearestTriangleCentre.cs +++ /dev/null @@ -1,182 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NStarAlignment.DataTypes; -using NStarAlignment.Model; -using System; - -namespace NStarAlignment.Tests -{ - [TestClass] - public class NearestTriangleCentre - { - private const double latitude = 52.6666666666667; - private const double longitude = -1.33333333333333; - private const double elevation = 201.0; - private const double tolerance = 0.75; - - private AlignmentModel model; - private TimeSpan utcOffset; - - [TestInitialize] - public void Initialise() - { - model = new AlignmentModel(latitude, longitude, elevation) - { - IsAlignmentOn = true - }; - model.ClearAlignmentPoints(); - utcOffset = new TimeSpan(); - - //// NW - DateTime syncTime = new DateTime(2020, 06, 28, 16, 43, 18); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] {1.45234227180481, 60.3347473144531}, new double[] { 144.945062700193, 60.3347473144531 }, new double[] { 149.723756536623, 59.1249432487836 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 43, 48); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] {2.86930561065674, 55.9740562438965}, new double[] { 123.819627432618, 55.9740562438965 }, new double[] { 128.404096999038, 55.283421763509 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 44, 08); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 2.08612251281738, 72.5127334594727 }, new double[] { 135.650906194933, 72.5127334594727 }, new double[] { 143.329091832532, 71.5666812294945 }, time); - - //model.AddAlignmentPoint(new double[] {1.93080902099609, 63.763801574707}, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - //// SW - syncTime = new DateTime(2020, 06, 28, 16, 45, 06); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 7.5975866317749, 31.8432216644287 }, new double[] { 53.2216111482121, 31.8432216644287 }, new double[] { 56.0429603483716, 31.4201609110561 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 45, 43); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 5.93735456466675, 7.40935134887695 }, new double[] { 78.2768689906225, 7.40935134887695 }, new double[] { 81.0690819058243, 7.01751946987766 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 46, 09); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 7.67223644256592, 5.17215204238892 }, new double[] { 52.3623042968102, 5.17215204238892 }, new double[] { 54.9750315780859, 4.46534644056118 }, time); - // model.AddAlignmentPoint(new double[] {7.32045793533325, 16.5029945373535}, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - ////SE - syncTime = new DateTime(2020, 06, 28, 16, 47, 51); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 13.0530576705933, 10.8525428771973 }, new double[] { 152.075877884869, 169.147457122803 }, new double[] { 152.72162571714, 171.563163746142 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 48, 09); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 12.3489561080933, -0.778456687927246 }, new double[] { 162.71580699319, 180.778456687927 }, new double[] { 163.926678775838, 183.082432087453 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 48, 28); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 13.5954742431641, -0.697973549365997 }, new double[] { 144.097740196623, 180.697973549366 }, new double[] { 144.925319826158, 183.236913318592 }, time); - // model.AddAlignmentPoint(new double[] {12.9437046051025, 3.28892135620117}, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - ////NE - syncTime = new DateTime(2020, 06, 28, 16, 51, 39); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 16.405143737793, 61.4716148376465 }, new double[] { 102.750476080924, 118.528385162354 }, new double[] { 100.26112572701, 120.586627285499 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 52, 00); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 15.4235200881958, 58.8995513916016 }, new double[] { 117.558254360687, 121.100448608398 }, new double[] { 114.734222729235, 122.861582942981 }, time); - - syncTime = new DateTime(2020, 06, 28, 16, 52, 22); - time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - model.AddAlignmentPoint(new double[] { 15.9716958999634, 54.6963729858398 }, new double[] { 109.430551501457, 125.30362701416 }, new double[] { 107.541470813369, 127.418045303378 }, time); - // model.AddAlignmentPoint(new double[] {16.0384006500244, 58.5149154663086}, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - } - - [TestMethod] - public void TestSyncedNW() - { - - DateTime syncTime = new DateTime(2020, 06, 28, 16, 44, 27); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(1.93080902099609, 63.763801574707, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 138.060159151908, 63.763801574707 }, time); - double[] expectedAxis = new double[] { 143.482011096669, 62.7368181631223 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSyncedSW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 46, 31); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(7.32045793533325, 16.5029945373535, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 57.7312421342358, 16.5029945373535 }, time); - double[] expectedAxis = new double[] { 60.4098738774835, 15.9579469987893 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSynchedSE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 48, 45); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(12.9437046051025, 3.28892135620117, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 153.945157337934, 176.711078643799 }, time); - double[] expectedAxis = new double[] { 154.854211281482, 179.129744501857 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestSynchedNE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 52, 43); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(16.0384006500244, 58.5149154663086, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - double[] adjustedAxis = model.GetSkyAxes(new double[] { 108.51725186361, 121.485084533691 }, time); - double[] expectedAxis = new double[] { 106.174079618103, 123.499884590653 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalNW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 44, 27); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(1.93080902099609, 63.763801574707, new double[] { 138.060159151908, 63.763801574707 }, new double[] { 143.482011096669, 62.7368181631223 }, new DateTime(2020, 06, 28, 16, 44, 27)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 143.482011096669, 62.7368181631223 }, time); - double[] expectedAxis = new double[] { 138.060159151908, 63.763801574707 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalSW() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 46, 31); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(7.32045793533325, 16.5029945373535, new double[] { 57.7312421342358, 16.5029945373535 }, new double[] { 60.4098738774835, 15.9579469987893 }, new DateTime(2020, 06, 28, 16, 46, 31)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 60.4098738774835, 15.9579469987893 }, time); - double[] expectedAxis = new double[] { 57.7312421342358, 16.5029945373535 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalSE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 48, 45); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(12.9437046051025, 3.28892135620117, new double[] { 153.945157337934, 176.711078643799 }, new double[] { 154.854211281482, 179.129744501857 }, new DateTime(2020, 06, 28, 16, 48, 45)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 154.854211281482, 179.129744501857 }, time); - double[] expectedAxis = new double[] { 153.945157337934, 176.711078643799 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - [TestMethod] - public void TestTheoreticalNE() - { - DateTime syncTime = new DateTime(2020, 06, 28, 16, 52, 43); - TimeRecord time = new TimeRecord(syncTime, TimeUtils.GetLocalSiderealTime(syncTime, utcOffset, longitude)); - // model.AddAlignmentPoint(16.0384006500244, 58.5149154663086, new double[] { 108.51725186361, 121.485084533691 }, new double[] { 106.174079618103, 123.499884590653 }, new DateTime(2020, 06, 28, 16, 52, 43)); - double[] adjustedAxis = model.GetMountAxes(new double[] { 106.174079618103, 123.499884590653 }, time); - double[] expectedAxis = new double[] { 108.51725186361, 121.485084533691 }; - Assert.AreEqual(expectedAxis[0], adjustedAxis[0], tolerance); - Assert.AreEqual(expectedAxis[1], adjustedAxis[1], tolerance); - } - - } -} diff --git a/NStarAlignment.Tests/Properties/AssemblyInfo.cs b/NStarAlignment.Tests/Properties/AssemblyInfo.cs deleted file mode 100644 index 892510bc..00000000 --- a/NStarAlignment.Tests/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,19 +0,0 @@ -using System.Reflection; -using System.Runtime.InteropServices; - -[assembly: AssemblyTitle("NStarAlignment.Tests")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("NStarAlignment.Tests")] -[assembly: AssemblyCopyright("Copyright © 2020")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -[assembly: ComVisible(false)] - -[assembly: Guid("9086d8e2-53f8-4432-8aff-32b675b14ee7")] - -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/NStarAlignment.Tests/SphericalPolarTests.cs b/NStarAlignment.Tests/SphericalPolarTests.cs deleted file mode 100644 index 42da83e7..00000000 --- a/NStarAlignment.Tests/SphericalPolarTests.cs +++ /dev/null @@ -1,479 +0,0 @@ -using Microsoft.VisualStudio.TestTools.UnitTesting; -using NStarAlignment.DataTypes; -using NStarAlignment.Model; -using NStarAlignment.Utilities; -using System; - -namespace NStarAlignment.Tests -{ - [TestClass] - public class SphericalPolarTests - { - private const double latitude = 52.6666666666667; - private const double longitude = -1.33333333333333; - private const double elevation = 201.0; - private readonly DateTime utcTime = new DateTime(2020, 1, 1, 00, 00, 00).ToUniversalTime(); - private TimeRecord timeRecord; - private AlignmentModel model; - private double tolerance = 0.002F; - - [TestInitialize] - public void Initialise() - { - model = new AlignmentModel(latitude, longitude, elevation); - model.ClearAlignmentPoints(); - timeRecord = new TimeRecord(this.utcTime, longitude); - - } - - - [TestCleanup] - public void Cleanup() - { - model = null; - } - - - - - [DataTestMethod] - [DataRow(0.00, 0.00)] - [DataRow(0.00, 30.00)] - [DataRow(0.00, 60.00)] - [DataRow(0.00, 90.00)] - [DataRow(0.00, 120.00)] - [DataRow(0.00, 150.00)] - [DataRow(0.00, 180.00)] - [DataRow(0.00, 210.00)] - [DataRow(0.00, 240.00)] - [DataRow(0.00, 270.00)] - [DataRow(0.00, 300.00)] - [DataRow(0.00, 330.00)] - [DataRow(30.00, 0.00)] - [DataRow(30.00, 30.00)] - [DataRow(30.00, 60.00)] - [DataRow(30.00, 90.00)] - [DataRow(30.00, 120.00)] - [DataRow(30.00, 150.00)] - [DataRow(30.00, 180.00)] - [DataRow(30.00, 210.00)] - [DataRow(30.00, 240.00)] - [DataRow(30.00, 270.00)] - [DataRow(30.00, 300.00)] - [DataRow(30.00, 330.00)] - [DataRow(60.00, 0.00)] - [DataRow(60.00, 30.00)] - [DataRow(60.00, 60.00)] - [DataRow(60.00, 90.00)] - [DataRow(60.00, 120.00)] - [DataRow(60.00, 150.00)] - [DataRow(60.00, 180.00)] - [DataRow(60.00, 210.00)] - [DataRow(60.00, 240.00)] - [DataRow(60.00, 270.00)] - [DataRow(60.00, 300.00)] - [DataRow(60.00, 330.00)] - [DataRow(90.00, 0.00)] - [DataRow(90.00, 30.00)] - [DataRow(90.00, 60.00)] - [DataRow(90.00, 90.00)] - [DataRow(90.00, 120.00)] - [DataRow(90.00, 150.00)] - [DataRow(90.00, 180.00)] - [DataRow(90.00, 210.00)] - [DataRow(90.00, 240.00)] - [DataRow(90.00, 270.00)] - [DataRow(90.00, 300.00)] - [DataRow(90.00, 330.00)] - public void RoundTripAxesToSpherical(double x, double y) - { - SphericalCoordinate spherical = model.AxesToSpherical(new double[] { x, y }, timeRecord); - double[] axes = model.SphericalToAxes(spherical, timeRecord, spherical.WeightsDown); - double cosx = Math.Cos(Angle.DegreesToRadians(x)); - double cosy = Math.Cos(Angle.DegreesToRadians(y)); - double cosa0 = Math.Cos(Angle.DegreesToRadians(axes[0])); - double cosa1 = Math.Cos(Angle.DegreesToRadians(axes[1])); - - Assert.AreEqual(cosx, cosa0, tolerance); - Assert.AreEqual(cosy, cosa1, tolerance); - } - - [DataTestMethod] - [DataRow(0.0, 45.0)] - [DataRow(10.0, 45.0)] - [DataRow(15.0, 45.0)] - [DataRow(45.0, 45.0)] - [DataRow(60.0, 45.0)] - [DataRow(89.99, 45.0)] - [DataRow(120.0, 45.0)] - public void RoundTripPolarCartesTests(double alt, double az) - { - SphericalCoordinate inSpherical = new SphericalCoordinate() - { - X = az, - Y = alt, - WeightsDown = false - }; - CarteseanCoordinate outCart = model.SphericalToCartesean(inSpherical); - SphericalCoordinate outSpherical = model.CarteseanToSpherical(outCart); - Assert.AreEqual(inSpherical, outSpherical); - - } - - [DataTestMethod] - [DataRow(0.00, 0.00)] - [DataRow(0.00, 30.00)] - [DataRow(0.00, 60.00)] - [DataRow(0.00, 90.00)] - [DataRow(0.00, 120.00)] - [DataRow(0.00, 150.00)] - [DataRow(0.00, 180.00)] - [DataRow(0.00, 210.00)] - [DataRow(0.00, 240.00)] - [DataRow(0.00, 270.00)] - [DataRow(0.00, 300.00)] - [DataRow(0.00, 330.00)] - [DataRow(30.00, 0.00)] - [DataRow(30.00, 30.00)] - [DataRow(30.00, 60.00)] - [DataRow(30.00, 90.00)] - [DataRow(30.00, 120.00)] - [DataRow(30.00, 150.00)] - [DataRow(30.00, 180.00)] - [DataRow(30.00, 210.00)] - [DataRow(30.00, 240.00)] - [DataRow(30.00, 270.00)] - [DataRow(30.00, 300.00)] - [DataRow(30.00, 330.00)] - [DataRow(60.00, 0.00)] - [DataRow(60.00, 30.00)] - [DataRow(60.00, 60.00)] - [DataRow(60.00, 90.00)] - [DataRow(60.00, 120.00)] - [DataRow(60.00, 150.00)] - [DataRow(60.00, 180.00)] - [DataRow(60.00, 210.00)] - [DataRow(60.00, 240.00)] - [DataRow(60.00, 270.00)] - [DataRow(60.00, 300.00)] - [DataRow(60.00, 330.00)] - [DataRow(89.99, 0.00)] - [DataRow(89.99, 30.00)] - [DataRow(89.99, 60.00)] - [DataRow(89.99, 90.00)] - [DataRow(89.99, 120.00)] - [DataRow(89.99, 150.00)] - [DataRow(89.99, 180.00)] - [DataRow(89.99, 210.00)] - [DataRow(89.99, 240.00)] - [DataRow(89.99, 270.00)] - [DataRow(89.99, 300.00)] - [DataRow(89.99, 330.00)] - public void RoundTripSphericalPolarTests(double alt, double az) - { - AxisPosition axes = new AxisPosition(az, alt); - SphericalCoordinate spherical1 = model.AxesToSpherical(new double[] {az, alt}, timeRecord); - AxisPosition outAxes = model.SphericalToAxes(spherical1, timeRecord, spherical1.WeightsDown); - Assert.IsTrue(outAxes.Equals(axes, tolerance)); - - } - - [DataTestMethod] - [DataRow(0.00, 0.00)] - [DataRow(0.00, 30.00)] - [DataRow(0.00, 60.00)] - [DataRow(0.00, 90.00)] - [DataRow(0.00, 120.00)] - [DataRow(0.00, 150.00)] - [DataRow(0.00, 180.00)] - [DataRow(0.00, 210.00)] - [DataRow(0.00, 240.00)] - [DataRow(0.00, 270.00)] - [DataRow(0.00, 300.00)] - [DataRow(0.00, 330.00)] - [DataRow(30.00, 0.00)] - [DataRow(30.00, 30.00)] - [DataRow(30.00, 60.00)] - [DataRow(30.00, 90.00)] - [DataRow(30.00, 120.00)] - [DataRow(30.00, 150.00)] - [DataRow(30.00, 180.00)] - [DataRow(30.00, 210.00)] - [DataRow(30.00, 240.00)] - [DataRow(30.00, 270.00)] - [DataRow(30.00, 300.00)] - [DataRow(30.00, 330.00)] - [DataRow(60.00, 0.00)] - [DataRow(60.00, 30.00)] - [DataRow(60.00, 60.00)] - [DataRow(60.00, 90.00)] - [DataRow(60.00, 120.00)] - [DataRow(60.00, 150.00)] - [DataRow(60.00, 180.00)] - [DataRow(60.00, 210.00)] - [DataRow(60.00, 240.00)] - [DataRow(60.00, 270.00)] - [DataRow(60.00, 300.00)] - [DataRow(60.00, 330.00)] - [DataRow(90.00, 0.00)] - [DataRow(90.00, 30.00)] - [DataRow(90.00, 60.00)] - [DataRow(90.00, 90.00)] - [DataRow(90.00, 120.00)] - [DataRow(90.00, 150.00)] - [DataRow(90.00, 180.00)] - [DataRow(90.00, 210.00)] - [DataRow(90.00, 240.00)] - [DataRow(90.00, 270.00)] - [DataRow(90.00, 300.00)] - [DataRow(90.00, 330.00)] - public void AxisToRaDecTests(double dec, double ra) - { - double[] raDec = model.AxesXYToRaDec(new double[] { ra, dec }, timeRecord); - double[] axes = model.RaDecToAxesXY(raDec, timeRecord); - Assert.AreEqual(ra, axes[0], tolerance); - Assert.AreEqual(dec, axes[1], tolerance); - } - - - [DataTestMethod] - [DataRow(6.58561821949163, 0)] - [DataRow(4.58561821949163, 0)] - [DataRow(2.58561821949163, 0)] - [DataRow(0.585618219491629, 0)] - [DataRow(22.5856182194916, 0)] - [DataRow(20.5856182194916, 0)] - [DataRow(18.5856182194916, 0)] - [DataRow(16.5856182194916, 0)] - [DataRow(14.5856182194916, 0)] - [DataRow(12.5856182194916, 0)] - [DataRow(10.5856182194916, 0)] - [DataRow(8.58561821949163, 0)] - [DataRow(6.58561821949163, 30)] - [DataRow(4.58561821949163, 30)] - [DataRow(2.58561821949163, 30)] - [DataRow(0.585618219491629, 30)] - [DataRow(22.5856182194916, 30)] - [DataRow(20.5856182194916, 30)] - [DataRow(18.5856182194916, 30)] - [DataRow(16.5856182194916, 30)] - [DataRow(14.5856182194916, 30)] - [DataRow(12.5856182194916, 30)] - [DataRow(10.5856182194916, 30)] - [DataRow(8.58561821949163, 30)] - [DataRow(6.58561821949163, 60)] - [DataRow(4.58561821949163, 60)] - [DataRow(2.58561821949163, 60)] - [DataRow(0.585618219491629, 60)] - [DataRow(22.5856182194916, 60)] - [DataRow(20.5856182194916, 60)] - [DataRow(18.5856182194916, 60)] - [DataRow(16.5856182194916, 60)] - [DataRow(14.5856182194916, 60)] - [DataRow(12.5856182194916, 60)] - [DataRow(10.5856182194916, 60)] - [DataRow(8.58561821949163, 60)] - [DataRow(6.58561821949163, 89)] - [DataRow(4.58561821949163, 89)] - [DataRow(2.58561821949163, 89)] - [DataRow(0.585618219491629, 89)] - [DataRow(22.5856182194916, 89)] - [DataRow(20.5856182194916, 89)] - [DataRow(18.5856182194916, 89)] - [DataRow(16.5856182194916, 89)] - [DataRow(14.5856182194916, 89)] - [DataRow(12.5856182194916, 89)] - [DataRow(10.5856182194916, 89)] - [DataRow(8.58561821949163, 89)] - public void RADecAltAxRADecTest(double ra, double dec) - { - double lst = TimeUtils.GetLocalSiderealTime(timeRecord.UtcTime, new TimeSpan(), longitude); - double[] altAz = AstroConvert.RaDec2AltAz(ra, dec, lst, latitude); - double[] raDec = AstroConvert.AltAz2RaDec(altAz[0], altAz[1], latitude, lst); - Assert.AreEqual(ra, raDec[0], tolerance); - Assert.AreEqual(dec, raDec[1], tolerance); - } - - - - [DataTestMethod] - #region Test Data ... - [DataRow(0.00, 0.00)] - [DataRow(0.00, 30.00)] - [DataRow(0.00, 60.00)] - [DataRow(0.00, 90.00)] - [DataRow(0.00, 120.00)] - [DataRow(0.00, 150.00)] - [DataRow(0.00, 180.00)] - [DataRow(0.00, 210.00)] - [DataRow(0.00, 240.00)] - [DataRow(0.00, 270.00)] - [DataRow(0.00, 300.00)] - [DataRow(0.00, 330.00)] - [DataRow(30.00, 0.00)] - [DataRow(30.00, 30.00)] - [DataRow(30.00, 60.00)] - [DataRow(30.00, 90.00)] - [DataRow(30.00, 120.00)] - [DataRow(30.00, 150.00)] - [DataRow(30.00, 180.00)] - [DataRow(30.00, 210.00)] - [DataRow(30.00, 240.00)] - [DataRow(30.00, 270.00)] - [DataRow(30.00, 300.00)] - [DataRow(30.00, 330.00)] - [DataRow(60.00, 0.00)] - [DataRow(60.00, 30.00)] - [DataRow(60.00, 60.00)] - [DataRow(60.00, 90.00)] - [DataRow(60.00, 120.00)] - [DataRow(60.00, 150.00)] - [DataRow(60.00, 180.00)] - [DataRow(60.00, 210.00)] - [DataRow(60.00, 240.00)] - [DataRow(60.00, 270.00)] - [DataRow(60.00, 300.00)] - [DataRow(60.00, 330.00)] - [DataRow(90.00, 0.00)] - [DataRow(90.00, 30.00)] - [DataRow(90.00, 60.00)] - [DataRow(90.00, 90.00)] - [DataRow(90.00, 120.00)] - [DataRow(90.00, 150.00)] - [DataRow(90.00, 180.00)] - [DataRow(90.00, 210.00)] - [DataRow(90.00, 240.00)] - [DataRow(90.00, 270.00)] - [DataRow(90.00, 300.00)] - [DataRow(90.00, 330.00)] - [DataRow(120.00, 0.00)] - [DataRow(120.00, 30.00)] - [DataRow(120.00, 60.00)] - [DataRow(120.00, 90.00)] - [DataRow(120.00, 120.00)] - [DataRow(120.00, 150.00)] - [DataRow(120.00, 180.00)] - [DataRow(120.00, 210.00)] - [DataRow(120.00, 240.00)] - [DataRow(120.00, 270.00)] - [DataRow(120.00, 300.00)] - [DataRow(120.00, 330.00)] - [DataRow(150.00, 0.00)] - [DataRow(150.00, 30.00)] - [DataRow(150.00, 60.00)] - [DataRow(150.00, 90.00)] - [DataRow(150.00, 120.00)] - [DataRow(150.00, 150.00)] - [DataRow(150.00, 180.00)] - [DataRow(150.00, 210.00)] - [DataRow(150.00, 240.00)] - [DataRow(150.00, 270.00)] - [DataRow(150.00, 300.00)] - [DataRow(150.00, 330.00)] - [DataRow(180.00, 0.00)] - [DataRow(180.00, 30.00)] - [DataRow(180.00, 60.00)] - [DataRow(180.00, 90.00)] - [DataRow(180.00, 120.00)] - [DataRow(180.00, 150.00)] - [DataRow(180.00, 180.00)] - [DataRow(180.00, 210.00)] - [DataRow(180.00, 240.00)] - [DataRow(180.00, 270.00)] - [DataRow(180.00, 300.00)] - [DataRow(180.00, 330.00)] - [DataRow(210.00, 0.00)] - [DataRow(210.00, 30.00)] - [DataRow(210.00, 60.00)] - [DataRow(210.00, 90.00)] - [DataRow(210.00, 120.00)] - [DataRow(210.00, 150.00)] - [DataRow(210.00, 180.00)] - [DataRow(210.00, 210.00)] - [DataRow(210.00, 240.00)] - [DataRow(210.00, 270.00)] - [DataRow(210.00, 300.00)] - [DataRow(210.00, 330.00)] - [DataRow(240.00, 0.00)] - [DataRow(240.00, 30.00)] - [DataRow(240.00, 60.00)] - [DataRow(240.00, 90.00)] - [DataRow(240.00, 120.00)] - [DataRow(240.00, 150.00)] - [DataRow(240.00, 180.00)] - [DataRow(240.00, 210.00)] - [DataRow(240.00, 240.00)] - [DataRow(240.00, 270.00)] - [DataRow(240.00, 300.00)] - [DataRow(240.00, 330.00)] - [DataRow(270.00, 0.00)] - [DataRow(270.00, 30.00)] - [DataRow(270.00, 60.00)] - [DataRow(270.00, 90.00)] - [DataRow(270.00, 120.00)] - [DataRow(270.00, 150.00)] - [DataRow(270.00, 180.00)] - [DataRow(270.00, 210.00)] - [DataRow(270.00, 240.00)] - [DataRow(270.00, 270.00)] - [DataRow(270.00, 300.00)] - [DataRow(270.00, 330.00)] - [DataRow(300.00, 0.00)] - [DataRow(300.00, 30.00)] - [DataRow(300.00, 60.00)] - [DataRow(300.00, 90.00)] - [DataRow(300.00, 120.00)] - [DataRow(300.00, 150.00)] - [DataRow(300.00, 180.00)] - [DataRow(300.00, 210.00)] - [DataRow(300.00, 240.00)] - [DataRow(300.00, 270.00)] - [DataRow(300.00, 300.00)] - [DataRow(300.00, 330.00)] - [DataRow(330.00, 0.00)] - [DataRow(330.00, 30.00)] - [DataRow(330.00, 60.00)] - [DataRow(330.00, 90.00)] - [DataRow(330.00, 120.00)] - [DataRow(330.00, 150.00)] - [DataRow(330.00, 180.00)] - [DataRow(330.00, 210.00)] - [DataRow(330.00, 240.00)] - [DataRow(330.00, 270.00)] - [DataRow(330.00, 300.00)] - [DataRow(330.00, 330.00)] - #endregion - public void AxesXYToRaDecTest(double x, double y) - { - double[] raDec = model.AxesXYToRaDec(new double[]{x, y}, timeRecord); - double[] axes = model.RaDecToAxesXY(raDec, timeRecord); - System.Diagnostics.Debug.WriteLine($"Original Axes = {x}/{y}, raDec = {raDec[0]}/{raDec[1]}, axes = {axes[0]}/{axes[1]}"); - Assert.IsTrue(Angle.AreSameDegrees(x, axes[0], tolerance)); - Assert.IsTrue(Angle.AreSameDegrees(y, axes[1], tolerance)); - } - - - [DataTestMethod] - [DataRow(0, 30, 12, 0, 30, 12)] - public void GenerateAngleData(double xStart, double xIncrement, int xSteps, double yStart, double yIncrement, int ySteps) - { - System.Diagnostics.Debug.WriteLine("#region Test Data ..."); - double x = xStart; - double y = yStart; - for (int xs = 0; xs < xSteps; xs++) - { - for (int ys = 0; ys < ySteps; ys++) - { - System.Diagnostics.Debug.WriteLine($"[DataRow({x:F2}, {y:F2})]"); - y += yIncrement; - } - - y = yStart; - x += xIncrement; - } - System.Diagnostics.Debug.WriteLine("#endregion"); - Assert.IsTrue(true); - } - - } -} diff --git a/NStarAlignment.Tests/TimeUtils.cs b/NStarAlignment.Tests/TimeUtils.cs deleted file mode 100644 index d46f6912..00000000 --- a/NStarAlignment.Tests/TimeUtils.cs +++ /dev/null @@ -1,140 +0,0 @@ -/* Copyright(C) 2019-2020 Rob Morgan (robert.morgan.e@gmail.com) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published - by the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace NStarAlignment.Tests -{ - public class TimeUtils - { - public static double GetLocalSiderealTime(DateTime utcTime, TimeSpan utcDateOffset, double longitude) - { - double jd = Ole2Jd(utcTime.Add(utcDateOffset)); - return Lst(Epoch2000Days(), jd, false, longitude); - - } - /// - /// OLE Automation Date to Julian Date - /// For modern dates only - /// - /// DateTime - /// 2455002.25 - private static double Ole2Jd(DateTime date) - { - var ole2Jd = date.ToOADate() + 2415018.5; - return ole2Jd; - } - - /// - /// Days since epoch 2000 - /// - /// - private static double Epoch2000Days() - { - return 2451545.0; //J2000 1 Jan 2000, 12h 0m 0s - } - - /// - /// Local Sidereal Time - /// Adopted from the ASCOM .net telescope simulator - /// - /// 2000, 1, 1, 12, 0, 0 - /// 2009, 6, 19, 4, 40, 5, 230 - /// true - /// 81 - /// 3.9042962940932857 - private static double Lst(double ejd, double jd, bool nutation, double longitude) - { - var a = jd - ejd; // Days since epoch - var b = a / 36525; // Century to days for the epoch - var c = 280.46061837 + 360.98564736629 * a; // Greenwich Mean Sidereal Time (GMST) - var d = c + longitude; // Local Mean Sidereal Time (LMST) - if (d < 0.0) - { - while (d < 0.0) - { - d += 360.0; - } - } - else - { - while (d > 360.0) d -= 360.0; - } - if (nutation) - { - //calculate OM the longitude when the Moon passes through the plane of the ecliptic - var e = 125.04452 - 1934.136261 * b; - if (e < 0.0) - { - while (e < 0.0) e += 360.0; - } - else - { - while (e > 360.0) e -= 360.0; - } - //calculat L mean longitude of the Sun - var f = 280.4665 + 36000.7698 * b; - if (f < 0.0) - { - while (f < 0.0) f += 360.0; - } - else - { - while (f > 360.0) f -= 360.0; - } - //calculate L1 mean longitude of the Moon - var g = 218.3165 + 481267.8813 * b; - if (g < 0.0) - { - while (g < 0) g += 360.0; - } - else - { - while (g > 360.0) g -= 360.0; - } - //calculate e Obliquity of the Ecliptic - var h = 23.439 - 0.0000004 * b; - if (h < 0.0) - { - while (h < 0.0) h += 360.0; - } - else - { - while (h > 360.0) h -= 360.0; - } - var i = (-17.2 * Math.Sin(e)) - (1.32 * Math.Sin(2 * f)) - (0.23 * Math.Sin(2 * g)) + (0.21 * Math.Sin(2 * e)); - var j = (i * Math.Cos(h)) / 3600; // Nutation correction for true values - d += j; // True Local Sidereal Time (LST) - } - var m = d * 24.0 / 360.0; - var lst = Range24(m); - return lst; - } - - private static double Range24(double d) - { - while ((d >= 24.0) || (d < 0.0)) - { - if (d < 0.0) d += 24.0; - if (d >= 24.0) d -= 24.0; - } - return d; - } - } -} diff --git a/NStarAlignment.Tests/packages.config b/NStarAlignment.Tests/packages.config deleted file mode 100644 index 923499fb..00000000 --- a/NStarAlignment.Tests/packages.config +++ /dev/null @@ -1,5 +0,0 @@ - - - - - \ No newline at end of file From 455b67710caaec8b9c7800b18faae4aa0463d06c Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Mon, 16 Jan 2023 09:48:05 +0000 Subject: [PATCH 17/18] Adding reference to LiveCharts and collection properties ready fo adding graphical representation of alignment points. --- GS.Server/Alignment/AlignmentVM.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/GS.Server/Alignment/AlignmentVM.cs b/GS.Server/Alignment/AlignmentVM.cs index ef16620e..6aff0264 100644 --- a/GS.Server/Alignment/AlignmentVM.cs +++ b/GS.Server/Alignment/AlignmentVM.cs @@ -21,6 +21,8 @@ You should have received a copy of the GNU General Public License using GS.Shared; using GS.Shared.Command; using GS.Utilities.Controls.Dialogs; +using LiveCharts; +using LiveCharts.Defaults; using System; using System.Collections.Generic; using System.Collections.ObjectModel; @@ -180,6 +182,14 @@ public bool ClearModelOnStartup } } + #region Plotting properties ... + public ChartValues UnsyncedPoints { get; } = new ChartValues(); + public ChartValues SyncedPoints { get; } = new ChartValues(); + + public ChartValues SelectedPoints { get; } = new ChartValues(); + + #endregion + #region Commands ... private RelayCommand _clearAllPointsCommand; From 48cc7cc22c6df3923081ba881e7ea96b25bcb600 Mon Sep 17 00:00:00 2001 From: Phil Crompton Date: Mon, 16 Jan 2023 11:28:52 +0000 Subject: [PATCH 18/18] Made Resharper suggested alterations. --- GS.Server/Alignment/AlignmentModel_Math.cs | 3 +-- NINA/Model/MyFocuser/AscomFocuser.cs | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/GS.Server/Alignment/AlignmentModel_Math.cs b/GS.Server/Alignment/AlignmentModel_Math.cs index 903eb38e..789213f1 100644 --- a/GS.Server/Alignment/AlignmentModel_Math.cs +++ b/GS.Server/Alignment/AlignmentModel_Math.cs @@ -236,7 +236,7 @@ private MapResult DeltaSyncReverse_Matrix_Map(AxisPosition targetPosition) /// private int GetQuadrant(Coord tmpcoord) { - int ret = 0; + int ret; if (tmpcoord.x >= 0) { @@ -274,7 +274,6 @@ private int GetQuadrant(Coord tmpcoord) private AlignmentPoint GetNearest(AxisPosition pos) { Dictionary distances = new Dictionary(); - int[] datholder2 = new int[this.AlignmentPoints.Count]; Coord posCartesean = EQ_sp2Cs(pos); diff --git a/NINA/Model/MyFocuser/AscomFocuser.cs b/NINA/Model/MyFocuser/AscomFocuser.cs index a44c4cf3..8f89e689 100644 --- a/NINA/Model/MyFocuser/AscomFocuser.cs +++ b/NINA/Model/MyFocuser/AscomFocuser.cs @@ -440,7 +440,7 @@ public void SetupDialog() public async Task Connect(CancellationToken token) { - return await Task.Run(() => { + return await Task.Run(() => { try { _focuser = GetFocuser(true); @@ -451,7 +451,7 @@ public async Task Connect(CancellationToken token) // RaiseAllPropertiesChanged(); } } - catch (ASCOM.DriverAccessCOMException ex) + catch (DriverAccessCOMException ex) { // Utility.Utility.HandleAscomCOMException(ex); var monitorItem = new MonitorEntry