static void Main(string[] args) { // 球坐标转为笛卡尔坐标 var spherical0 = new Spherical(Math.PI / 4, Math.PI / 8, 100.0); var cartesian0 = new Cartesian(spherical0); Console.WriteLine("球坐标:{0};笛卡尔坐标:{1}", spherical0, cartesian0); // 笛卡尔坐标归一化 UnitCartesian unitCartesian1 = cartesian0.Normalize(); Console.WriteLine("单位矢量笛卡尔坐标:{0}", unitCartesian1); // 地图坐标转为笛卡尔坐标 var cartographic2 = new Cartographic(Trig.DegreesToRadians(120), Trig.DegreesToRadians(30), 100); EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; Cartesian cartesian2 = earth.Shape.CartographicToCartesian(cartographic2); Console.WriteLine("地图坐标:{0};笛卡尔坐标:{1}", cartographic2, cartesian2); // 笛卡尔坐标转为地图坐标 Cartographic cartographic3 = earth.Shape.CartesianToCartographic(cartesian2); Console.WriteLine("笛卡尔坐标:{0};地图坐标:{1}", cartesian2, cartographic3); // 新坐标系绕原坐标系z轴旋转90度,原向量(1,0,0) var vector4 = new Cartesian(1, 0, 0); var rotation4 = new ElementaryRotation(AxisIndicator.Third, Trig.DegreesToRadians(90)); Cartesian newVector4 = new Matrix3By3(rotation4).Multiply(vector4); Console.WriteLine("旋转前:{0};旋转后:{1}", vector4, newVector4); // 欧拉旋转 var vector5 = new Cartesian(1, 0, 0); double angle = Trig.DegreesToRadians(90); var euler = new EulerSequence(angle, angle, angle, EulerSequenceIndicator.Euler321); Cartesian newVector5 = new Matrix3By3(euler).Multiply(vector5); Console.WriteLine("旋转前:{0};旋转后:{1}", vector5, newVector5); // 偏航俯仰翻滚旋转 var vector6 = new Cartesian(1, 0, 0); double angle6 = Trig.DegreesToRadians(90); var ypr = new YawPitchRoll(angle, angle, angle, YawPitchRollIndicator.YPR); Cartesian newVector6 = new Matrix3By3(ypr).Multiply(vector6); Console.WriteLine("旋转前:{0};旋转后:{1}", vector6, newVector6); Console.Read(); }
public EntityPlatform(ExampleEntity entity, EarthCentralBody earth, string dataPath) { //id, string m_id = entity.EntityIdentifier.ToString(); //name, string string name = entity.Marking.ToString(); //Last Update, DateTime DateTime time = DateTime.Parse(entity.LastUpdateDateTime.ToString()); //Position, Cartesian string[] xyz = entity.Position.ToString().Split(','); Cartesian position = new Cartesian(Convert.ToDouble(xyz[0]), Convert.ToDouble(xyz[1]), Convert.ToDouble(xyz[2])); m_platform = new Platform(); m_platform.Name = name; m_platform.LocationPoint = new PointCartographic(earth, earth.Shape.CartesianToCartographic(position)); m_platform.OrientationAxes = new AxesVehicleVelocityLocalHorizontal(earth.FixedFrame, m_platform.LocationPoint); LabelGraphicsExtension labelExtension = new LabelGraphicsExtension(new LabelGraphics { Text = new ConstantCesiumProperty<string>(name), Scale = new ConstantCesiumProperty<double>(0.5), FillColor = new ConstantCesiumProperty<Color>(Color.White), PixelOffset = new ConstantCesiumProperty<Rectangular>(new Rectangular(35, -15)) }); m_platform.Extensions.Add(labelExtension); string symbol = entity.Symbology.ToString().Replace('*', '_') + ".png"; CesiumResource billboardResource = new CesiumResource(new Uri(dataPath + symbol), CesiumResourceBehavior.LinkTo); BillboardGraphicsExtension billboardExtension = new BillboardGraphicsExtension(new BillboardGraphics { Image = new ConstantCesiumProperty<CesiumResource>(billboardResource), Show = true, Scale = new ConstantCesiumProperty<double>(1) }); m_platform.Extensions.Add(billboardExtension); m_czmlDocument = new CzmlDocument(); m_czmlDocument.Name = "Realtime"; m_czmlDocument.RequestedInterval = new TimeInterval(new JulianDate(DateTime.Now), new JulianDate(DateTime.Now.AddDays(1.0))); m_czmlDocument.Clock = new Clock { Step = ClockStep.SystemClock }; m_czmlDocument.ObjectsToWrite.Add(m_platform); }
static void Main(string[] args) { // 显示版本号 Console.WriteLine("DisplayVersion: {0}", StkComponentsCore.DisplayVersion); Console.WriteLine("Version: {0}", StkComponentsCore.Version); // 显示当前时刻地球质心和月球质心之间的距离 DateTime now = DateTime.Now; EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; MoonCentralBody moon = CentralBodiesFacet.GetFromContext().Moon; var vector = new VectorTrueDisplacement(earth.CenterOfMassPoint, moon.CenterOfMassPoint); double distance = vector.GetEvaluator().Evaluate(new JulianDate(now)).Magnitude; Console.WriteLine("当前时间:{0:yyyy-MM-dd HH:mm:ss.fff},当前日月距离:{1:0.000}千米", now, distance / 1000); Console.Read(); }
private static void Main() { // startup data configuration // Update LeapSecond.dat, and use it in the current calculation context. LeapSecondsFacetHelper.GetLeapSeconds().UseInCurrentContext(); EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; // Load EOP Data - For fixed to inertial transformations earth.OrientationParameters = EarthOrientationParametersHelper.GetEarthOrientationParameters(); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new Main()); }
private static void Main() { // startup data configuration // Update LeapSecond.dat, and use it in the current calculation context. LeapSecondsFacetHelper.GetLeapSeconds().UseInCurrentContext(); EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; // Load EOP Data - For fixed to inertial transformations earth.OrientationParameters = EarthOrientationParametersHelper.GetEarthOrientationParameters(); // Load JPL data // Optional - Without this an analytic model is used to position central bodies string dataPath = Path.Combine(Application.StartupPath, "Data"); JplDE430 jpl = new JplDE430(Path.Combine(dataPath, "plneph.430")); jpl.UseForCentralBodyPositions(CentralBodiesFacet.GetFromContext()); Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); Application.Run(new LotsOfSatellites()); }
public static void Initialize(string dataPath, string virtualPath) { Licensing.ActivateLicense( @"<License> <Field name='Name'>Daniel Honaker</Field> <Field name='sfId'>003j000000RSOxBAAX</Field> <Component name='Dynamic Geometry Library' expiration='2015/11/18' /> <Component name='Navigation Accuracy Library' expiration='2015/11/18' /> <Component name='Terrain Analysis Library' expiration='2015/11/18' /> <Component name='Spatial Analysis Library' expiration='2015/11/18' /> <Component name='Communications Library' expiration='2015/11/18' /> <Component name='Insight3D' expiration='2015/11/18' /> <Component name='Tracking Library' expiration='2015/11/18' /> <Component name='Route Design Library' expiration='2015/11/18' /> <Component name='Orbit Propagation Library' expiration='2015/11/18' /> <Component name='Auto-Routing Library' expiration='2015/11/18' /> <Signature>SJH4qBqzoL2HKM+Q9TbP7NkFk56vYPoroBRERMWikQum8SQF9bBL35E4N0JUCxpIdMVETg2l3JSd4ddGUHmm33+r6Iamau3SYhzyZsk4dmeEztt3HpZiKZsxr4bcEuLSpCe/8qMXxoJUrbr0K34fELpeOSb5FIGHjxdExsafF1E=</Signature> </License>"); m_virtualPath = virtualPath; m_earth = CentralBodiesFacet.GetFromContext().Earth; //Make sure the default descriptor for the ExampleEntity class is set. ExampleEntity.RegisterEntityClass(); //Create the primary TransactionContext that will be used throughout the application. TransactionContext context = new TransactionContext(); context.Committed += context_Committed; //Create the master entity set that will be populated by our data feed. m_entities = new EntitySet<ExampleEntity>(context); m_entities.Changed += m_entities_Changed; //Create and start the data feed. m_provider = new ExampleEntityProvider(dataPath, m_entities); m_provider.Start(); }
private void OnLoad(object sender, EventArgs e) { // Create overlay toolbar and panels m_overlayToolbar = new OverlayToolbar(m_insight3D); m_overlayToolbar.Overlay.Origin = ScreenOverlayOrigin.BottomCenter; // Add additional toolbar buttons // Number of Satellites Button m_overlayToolbar.AddButton(GetDataFilePath("Textures/OverlayToolbar/manysatellites.png"), GetDataFilePath("Textures/OverlayToolbar/fewsatellites.png"), ToggleNumberOfSatellites); // Show/Hide Access Button m_overlayToolbar.AddButton(GetDataFilePath("Textures/OverlayToolbar/noshowaccess.png"), GetDataFilePath("Textures/OverlayToolbar/showaccess.png"), ToggleComputeAccess); // Initialize the text panel m_textPanel = new TextureScreenOverlay(0, 0, 80, 35) { Origin = ScreenOverlayOrigin.TopRight, BorderSize = 2, BorderColor = Color.Transparent, BorderTranslucency = 0.6f, Color = Color.Transparent, Translucency = 0.4f }; SceneManager.ScreenOverlays.Add(m_textPanel); // Show label for the moon Scene scene = m_insight3D.Scene; scene.CentralBodies[CentralBodiesFacet.GetFromContext().Moon].ShowLabel = true; // Create a marker primitive for the facility at Bells Beach Australia EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; Cartographic facilityPosition = new Cartographic(Trig.DegreesToRadians(144.2829), Trig.DegreesToRadians(-38.3697), 0.0); Texture2D facilityTexture = SceneManager.Textures.FromUri(GetDataFilePath(@"Markers\Facility.png")); MarkerBatchPrimitive marker = new MarkerBatchPrimitive(SetHint.Infrequent) { Texture = facilityTexture }; marker.Set(new[] { earth.Shape.CartographicToCartesian(facilityPosition) }); SceneManager.Primitives.Add(marker); PointCartographic point = new PointCartographic(earth, facilityPosition); Axes topographic = new AxesNorthEastDown(earth, point); ReferenceFrame facilityTopo = new ReferenceFrame(point, topographic); m_fixedToFacilityTopoEvaluator = GeometryTransformer.GetReferenceFrameTransformation(earth.FixedFrame, facilityTopo); Axes temeAxes = earth.TrueEquatorMeanEquinoxFrame.Axes; m_temeToFixedEvaluator = GeometryTransformer.GetAxesTransformation(temeAxes, earth.FixedFrame.Axes); m_showAccess = true; m_satellites = new Satellites(); CreateSatellites("stkSatDb"); // This Render() is needed so that the stars will show. scene.Render(); }
/// <summary> /// Construct a default instance. /// </summary> public Main() { InitializeComponent(); m_insight3D = new Insight3D(); m_insight3D.Dock = DockStyle.Fill; m_insight3DPanel.Controls.Add(m_insight3D); m_defaultStart = GregorianDate.Now; m_defaultEnd = m_defaultStart.AddDays(1); m_animation = new SimulationAnimation(); SceneManager.Animation = m_animation; m_display = new ServiceProviderDisplay(); m_forceModelSettings = new ForceModelSettings(s_jplData, GetDataFilePath("EarthGravityFile_EGM2008.grv")); m_integratorSettings = new IntegratorSettings(); m_area.Text = "20"; m_mass.Text = "500"; // Create overlay toolbar and panels m_overlayToolbar = new OverlayToolbar(m_insight3D); m_overlayToolbar.Overlay.Origin = ScreenOverlayOrigin.BottomCenter; // Initialize the text panel TextureScreenOverlay textPanel = new TextureScreenOverlay(0, 0, 220, 35) { Origin = ScreenOverlayOrigin.TopRight, BorderSize = 0, BorderColor = Color.Transparent, BorderTranslucency = 1.0f, Color = Color.Transparent, Translucency = 1.0f }; SceneManager.ScreenOverlays.Add(textPanel); m_dateTimeFont = new Font("Courier New", 12, FontStyle.Bold); Size textSize = Insight3DHelper.MeasureString(m_defaultStart.ToString(), m_dateTimeFont); m_textOverlay = new TextureScreenOverlay(0, 0, textSize.Width, textSize.Height) { Origin = ScreenOverlayOrigin.Center, BorderSize = 0 }; textPanel.Overlays.Add(m_textOverlay); // Show label for the moon m_insight3D.Scene.CentralBodies[CentralBodiesFacet.GetFromContext().Moon].ShowLabel = true; // Set the name for the element that will get propagated m_elementID = "Satellite"; // Subscribe to the time changed event SceneManager.TimeChanged += OnTimeChanged; // Set the start and stop times m_start.CustomFormat = DateFormat; m_end.CustomFormat = DateFormat; m_start.Text = m_defaultStart.ToString(DateFormat); m_end.Text = m_defaultEnd.ToString(DateFormat); m_animation.Time = m_defaultStart.ToJulianDate(); m_animation.StartTime = m_defaultStart.ToJulianDate(); m_animation.EndTime = m_defaultEnd.ToJulianDate(); // Dynamically set the camera's position and direction so that the camera will always be pointed at the daylit portion of the earth. EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; SunCentralBody sun = CentralBodiesFacet.GetFromContext().Sun; VectorTrueDisplacement earthToSunVector = new VectorTrueDisplacement(earth.CenterOfMassPoint, sun.CenterOfMassPoint); VectorEvaluator earthToSunEvaluator = earthToSunVector.GetEvaluator(); Cartesian earthToSunCartesian = earthToSunEvaluator.Evaluate(new JulianDate(m_defaultStart)); UnitCartesian earthToSunUnitCartesian = new UnitCartesian(earthToSunCartesian); UnitCartesian cameraDirection = new UnitCartesian(earthToSunUnitCartesian.Invert()); Cartesian cameraPosition = new Cartesian(earthToSunUnitCartesian.X * 50000000, earthToSunUnitCartesian.Y * 50000000, earthToSunUnitCartesian.Z * 50000000); m_insight3D.Scene.Camera.Position = cameraPosition; m_insight3D.Scene.Camera.Direction = cameraDirection; }
/// <summary> /// Method to calculate all the data required for the graphs. /// </summary> private void OnAddReceiverClick(object sender, EventArgs e) { #region CreateAndConfigureReceiver // Let's create the GPSReceiver. The receiver stores many properties and has a defined location. This location // is the point of reference for visibility calculations. receiver = new GpsReceiver(); // add receiver to the tree TreeNode newNode = new TreeNode(Localization.Receiver); rootNode.Nodes.Add(newNode); // Easy reference to Earth Central body used to initialize the ElevationAngleAccessConstraint and // to calculate the Az/El/Range Data. EarthCentralBody earth = CentralBodiesFacet.GetFromContext().Earth; // set the receiver properties based on user selections // The receiver has a receiver FrontEnd that contains the visibility and tracking constraints // Be sure to convert your angles to Radians! double minimumAngle = Trig.DegreesToRadians(Double.Parse(MaskAngle.Text)); receiver.ReceiverConstraints.Clear(); receiver.ReceiverConstraints.Add(new ElevationAngleConstraint(earth, minimumAngle)); receiver.NumberOfChannels = (int)NumberOfChannels.Value; receiver.NoiseModel = new ConstantGpsReceiverNoiseModel(0.8); // The receiver's methods of reducing the number of visible satellites to the limit imposed by the number of channels if (BestNSolType.Checked) { receiver.ReceiverSolutionType = GpsReceiverSolutionType.BestN; } else { receiver.ReceiverSolutionType = GpsReceiverSolutionType.AllInView; } // create a new location for the receiver by using the Cartographic type from AGI.Foundation.Coordinates // again, remember to convert from degrees to Radians! (except the height of course) Cartographic position = new Cartographic(Trig.DegreesToRadians(double.Parse(Longitude.Text)), Trig.DegreesToRadians(double.Parse(Latitude.Text)), double.Parse(ReceiverHeight.Text)); // Now create an antenna for the GPS receiver. We specify the location of the antenna by assigning a // PointCartographic instance to the LocationPoint property. We specify that the antenna should be oriented // according to the typically-used East-North-Up axes by assigning an instance of AxesEastNorthUp to // the OrientationAxes property. While the orientation of the antenna won't affect which satellites are visible // or tracked in this case, it will affect the DOP values. For example, the EDOP value can be found in // DilutionOfPrecision.X, but only if we've configured the antenna to use East-North-Up axes. PointCartographic antennaLocationPoint = new PointCartographic(earth, position); Platform antenna = new Platform { LocationPoint = antennaLocationPoint, OrientationAxes = new AxesEastNorthUp(earth, antennaLocationPoint) }; receiver.Antenna = antenna; #endregion // update the tree to reflect the correct receiver info newNode.Nodes.Add(new TreeNode(string.Format(Localization.FixedMaskAngle + "= {0:0.00} " + Localization.degrees, MaskAngle.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.NumberOfChannels + "= {0}", NumberOfChannels.Value))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.SolutionType + "= {0}", receiver.ReceiverSolutionType == GpsReceiverSolutionType.AllInView ? Localization.AllInView : Localization.BestN))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Latitude + "= {0:0.000000} " + Localization.degrees, Latitude.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Longitude + "= {0:0.000000} " + Localization.degrees, Longitude.Text))); newNode.Nodes.Add(new TreeNode(string.Format(Localization.Height + "= {0:0.000} " + Localization.meters, ReceiverHeight.Text))); rootNode.Expand(); newNode.Expand(); #region CalculateDataForGraphs // Now, we'll open the almanac SemAlmanac almanac; using (Stream stream = openAlmanacDialog.OpenFile()) using (StreamReader reader = new StreamReader(stream)) { // Read the SEM almanac from an almanac stream reader. almanac = SemAlmanac.ReadFrom(reader, 1); } // Now create a PlatformCollection to hold GpsSatellite object instances. The SemAlmanac method CreateSatellitesFromRecords returns // just such a collection. We'll use this set of satellites as the set from which we'll try and track. There is a // GpsSatellite object for each satellite specified in the almanac. PlatformCollection gpsSatellites = almanac.CreateSatelliteCollection(); // We provide the receiver with the complete set of gpsSatellites to consider for visibility calculations. // This is usually all SVs defined in the almanac - however you may want to remove SVs that aren't healthy. This can // be done by creating the gpsSatellites collection above using another version of the CreateSatellitesFromRecords method that // takes a SatelliteOutageFileReader. receiver.NavigationSatellites = gpsSatellites; // Optimization opportunity: Add the following code in a thread. This will help for long duration analyses. // Now that we have the receiver and location setup, we need to evaluate all the pertinent data. // using a SatelliteTrackingEvaluator, we can track satellites and using a DOP Evaluator, // we can calculate DOP at a specified time. // The receiver's GetSatelliteTrackingEvaluator method will provide a SatelliteTrackingEvaluator for you. // Similarly, the GetDilutionOfPrecisionEvaluator provides the DOP evaluator. // We create all evaluators in the same EvaluatorGroup for the best performance. EvaluatorGroup group = new EvaluatorGroup(); Evaluator <int[]> satTrackingEvaluator = receiver.GetSatelliteTrackingIndexEvaluator(group); Evaluator <DilutionOfPrecision> dopEvaluator = receiver.GetDilutionOfPrecisionEvaluator(group); // We also need to create an evaluator to compute Azimuth/Elevation for each of the SVs MotionEvaluator <AzimuthElevationRange>[] aerEvaluators = new MotionEvaluator <AzimuthElevationRange> [gpsSatellites.Count]; for (int i = 0; i < gpsSatellites.Count; ++i) { Platform satellite = receiver.NavigationSatellites[i]; VectorTrueDisplacement vector = new VectorTrueDisplacement(antenna.LocationPoint, satellite.LocationPoint); aerEvaluators[i] = earth.GetAzimuthElevationRangeEvaluator(vector, group); } // First we'll initialize the data structures used to plot the data for (int i = 0; i < DOPData.Length; i++) { // PointPairList is defined in the ZedGraph reference DOPData[i] = new PointPairList(); } // We need to know which time standard to use here. If the user has specified that GPS time is to be used // we need to create the JulianDates with the GlobalPositioningSystemTime standard. if (GPSTimeRadio.Checked) { startjd = new JulianDate(StartTime.Value, TimeStandard.GlobalPositioningSystemTime); stopjd = new JulianDate(StopTime.Value, TimeStandard.GlobalPositioningSystemTime); } else { // otherwise, the default time standard is UTC startjd = new JulianDate(StartTime.Value); stopjd = new JulianDate(StopTime.Value); } // Now we''ll create the variables we'll need for iterating through time. // The propagator requires a Duration type be used to specify the timestep. Duration dur = stopjd - startjd; double timestep = Double.Parse(TimeStep.Text); // Initialize the progressbar with appropriate values progressBar1.Maximum = (int)dur.TotalSeconds; progressBar1.Step = (int)timestep; // now we'll iterate through time by adding seconds to the start time JulianDate // creating a new JulianDate 'evaluateTime' each time step. for (double t = 0; t <= dur.TotalSeconds; t += timestep) { JulianDate evaluateTime = startjd.AddSeconds(t); // The string 'trackedSVs' is the start of a string we'll continue to build through this time // iteration. It will contain the info we'll need to put in the DOP graph tooltips for the different // DOP series (VDOP, HDOP, etc.) String trackedSVs = Localization.Tracked + ": "; // The evaluator method GetTrackedSatellites will take the current time and the initial list of satellites and // determine which satellites can be tracked based on the receiver constraints setup earlier. This method // returns a PlatformCollection object as well (though we'll cast each member of the Collection to a GPSSatellite type) int[] trackedSatellites = satTrackingEvaluator.Evaluate(evaluateTime); foreach (int satelliteIndex in trackedSatellites) { Platform satellite = receiver.NavigationSatellites[satelliteIndex]; // Now we have access to a Platform object representing a GPS satellite and calculate the azimuth and elevation // of each. Note that we're just calculating the azimuth and elevation, but could just as easily get the // range as well. AzimuthElevationRange aer = aerEvaluators[satelliteIndex].Evaluate(evaluateTime); // Get the GpsSatelliteExtension attached to the platform. The extension extends a // platform with GPS-specific information. In this case, we need the // satellites PRN. GpsSatelliteExtension extension = satellite.Extensions.GetByType <GpsSatelliteExtension>(); // Create two separate PointPairLists to hold the data stored by Time and Azimuth PointPairList thisTimePointList, thisAzPointList; // Before we can arbitrarily create new PointPair Lists, we have to see if the Data Storage structures already contain a list // for this PRN. // The variables AzElData_TimeBased and AzElData_AzimuthBased are dictionaries that hold the PointPairLists using the PRN // as a key. We use this structure to store a large amount of data for every satellite in a single, easy to access, variable. // if the satellite we're currently looking at already has a list defined in the dictionary, we'll use that one, otherwise // we'll create a new list if (AzElData_TimeBased.ContainsKey(extension.PseudoRandomNumber)) { thisTimePointList = AzElData_TimeBased[extension.PseudoRandomNumber]; AzElData_TimeBased.Remove(extension.PseudoRandomNumber); } else { thisTimePointList = new PointPairList(); } if (AzElData_AzimuthBased.ContainsKey(extension.PseudoRandomNumber)) { thisAzPointList = AzElData_AzimuthBased[extension.PseudoRandomNumber]; AzElData_AzimuthBased.Remove(extension.PseudoRandomNumber); } else { thisAzPointList = new PointPairList(); } // Now to get the actual Azimuth and elevation data // Converting your Radians to degrees here makes the data appear in a more readable format. We also constrain the azimuth // to be within the interval [0, 2*pi] double azimuth = Trig.RadiansToDegrees(Trig.ZeroToTwoPi(aer.Azimuth)); double elevation = Trig.RadiansToDegrees(aer.Elevation); #endregion // now create the point for the Azimuth based data PointPair thisAzPoint = new PointPair(azimuth, elevation); // and add the tooltip (ZedGraph uses the Tag property on a PointPair for the tooltip on that datapoint ) thisAzPoint.Tag = String.Format("PRN {0}, {1}, " + Localization.Az + ": {2:0.000}, " + Localization.El + ": {3:0.000}", extension.PseudoRandomNumber, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), azimuth, elevation); // and finally add this point to the list thisAzPointList.Add(thisAzPoint); // now we'll do the same for the time-based data, instead of adding the Az and El, we'll add the time and El. // Create a new XDate object to store the time for this point double txd = (double)new XDate(evaluateTime.ToDateTime()); // add the time and elevation data to this point PointPair thisTimePoint = new PointPair(txd, Trig.RadiansToDegrees(aer.Elevation)); // Create the tooltip tag thisTimePoint.Tag = String.Format("PRN {0}, {1}, " + Localization.Az + ": {2:0.000}, " + Localization.El + ": {3:0.000}", extension.PseudoRandomNumber, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), azimuth, elevation); // finally add this point to the list thisTimePointList.Add(thisTimePoint); //Now that this data is all calculated, we'll add the point lists to the correct data structures for the GpsSatellite we're working with AzElData_TimeBased.Add(extension.PseudoRandomNumber, thisTimePointList); AzElData_AzimuthBased.Add(extension.PseudoRandomNumber, thisAzPointList); // now update the 'trackedSVs' string to be used for the DOP data tooltip // wee need to do this inside the GpsSatellite loop because we need to get the entire list of tracked SVs for this time step. // we won't use this string until we're out of the loop however. trackedSVs += extension.PseudoRandomNumber.ToString() + ", "; } // now we're out of the GpsSatellite loop, we'll do some string manipulation to get the tooltip for the DOP data. // (gets rid of the last inserted comma) string svs = trackedSVs.Substring(0, trackedSVs.LastIndexOf(' ') - 1); try { // Now we use the evaluator to calculate the DilutionOfPrecision for us for this timestep DilutionOfPrecision dop = dopEvaluator.Evaluate(evaluateTime); // if the dop object throws an exception, there aren't enough tracked satellites to form a navigation solution (typically < 4 tracked) // in that case we leave the data for this time unfilled. The graph will then have empty spots for this time. // Here we create a new PointPair and a new XDate to add to the X-Axis PointPair pp; double txd = (double)new XDate(evaluateTime.ToDateTime()); // add the East DOP value and the time to the PointPair and set the tooltip tag property for this series. pp = new PointPair(txd, dop.X); pp.Tag = String.Format("{0}\n{1} " + Localization.EDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.X); // add the point to the 0th element of the DOPData structure DOPData[0].Add(pp); // repeat for North DOP pp = new PointPair(txd, dop.Y); pp.Tag = String.Format("{0}\n{1} " + Localization.NDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Y); DOPData[1].Add(pp); // repeat for the Vertical DOP pp = new PointPair(txd, dop.Z); pp.Tag = String.Format("{0}\n{1} " + Localization.VDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Z); DOPData[2].Add(pp); // repeat for the Horizontal DOP pp = new PointPair(txd, dop.XY); pp.Tag = String.Format("{0}\n{1} " + Localization.HDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.XY); DOPData[3].Add(pp); // repeat for the Position DOP pp = new PointPair(txd, dop.Position); pp.Tag = String.Format("{0}\n{1} " + Localization.PDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Position); DOPData[4].Add(pp); // repeat for the Time DOP pp = new PointPair(txd, dop.Time); pp.Tag = String.Format("{0}\n{1} " + Localization.TDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Time); DOPData[5].Add(pp); // repeat for the Geometric DOP pp = new PointPair(txd, dop.Geometric); pp.Tag = String.Format("{0}\n{1} " + Localization.GDOP + ": {2:0.000}", svs, evaluateTime.ToDateTime().ToString("M/d/yyyy, h:mm tt"), dop.Geometric); DOPData[6].Add(pp); // Notice here that the different DOP values (East, North, etc) were denoted by the dop.X, dop.Y etc. This is because the // DOP values could be in any coordinate system. In our case, we're in the ENU coordinate system an X represents East, Y // represents North, Z represents Vertical, XY represents horizontal. You can change the reference frame the DOP is reported in // but you will then have to understand that the dop.X value corresponds to your X-defined axis and so on. } catch { // Do Nothing here - we just won't add the data to the data list } // update the progress bar - we're done with this time step! progressBar1.PerformStep(); } // finally update the graphs UpdateDopGraph(); updateAzElGraph(); // reset the progress bar progressBar1.Value = 0; // and set the appropriate button states SetControlStates(true); }