private void CalcEndButton_Click(object sender, EventArgs e) { /// Summary /// "West is Best, East is least" /// To calculate true bearing from compass bearing (and known deviation and variation): /// Compass bearing +deviation = magnetic bearing /// Magnetic bearing + variation = true bearing /// To calculate compass bearing from true bearing(and known deviation and variation): /// True bearing -variation = Magnetic bearing /// West Variations are negative /// In the US, the agonic line is roughly along the Mississippi river /// In aviation, maps, GPS and runways use true bearings double CalcTrueBrg = CalcBrg; if (MagBrgCheckBox.Checked) { CalcTrueBrg -= CalcMag; } double[] CalcLocation = LatLongCalc.Destination(StartLat, StartLon, DistanceAdjust(CalcDist, CalcType), CalcTrueBrg, CalcType); EndLat = CalcLocation[0]; EndLon = CalcLocation[1]; EndLatitudeTextBox.Text = Conversions.Degrees2SCT(EndLat, true); EndLongitudeTextBox.Text = Conversions.Degrees2SCT(EndLon, false); EndFixTextBox.Text = string.Empty; UpdateCopyButtons(); }
public static string WriteHF(string Message, double Lat, double Lon, int Angle = 0, float Scale = 1) { // Lat is 'Y'!! Lon is 'X'!! float curLat = (float)Lat; float curLon = (float)Lon; PointF origin = new PointF(curLon, curLat); PointF nextChar = origin; float scale = Scale / 3600F; int angle = (int)InfoSection.MagneticVariation + Angle; string space = new string(' ', 27); string cr = Environment.NewLine; int AsciiC; int[] SmplxC; string Result = string.Empty; foreach (char c in Message) { AsciiC = c; if ((AsciiC - 32 >= 0) & (AsciiC - 32 < 95)) { AsciiC -= 32; } else { AsciiC = 10; // 10 is '*' for 'error' } SmplxC = RomanSimplex.Simplex[AsciiC]; Result += DrawChar(c, SmplxC, nextChar, Angle, Scale); // Use points to update here SizeF offset = new SizeF(SmplxC[1] * scale, 0); nextChar = PointF.Add(nextChar, offset); nextChar = LatLongCalc.RotatePoint(nextChar, origin, angle); origin = nextChar; } return(space + "; Label " + Message + cr + Result); }
private void UpdateDistBrg() { Distance = LatLongCalc.Distance(StartLat, StartLon, EndLat, EndLon, 'N'); DispDistTextBox.Text = decimal.Round(Convert.ToDecimal(Distance), 2, MidpointRounding.AwayFromZero).ToString(); TrueBrg = LatLongCalc.Bearing(StartLat, StartLon, EndLat, EndLon); DispBrgTextBox.Text = decimal.Round(Convert.ToDecimal(TrueBrg), 2, MidpointRounding.AwayFromZero).ToString(); }
private void Fix2CenterButton_Click(object sender, EventArgs e) { // East declination is positive; west is negative // True (map) Heading = Mag Bearing + Declination // Mag Hdg = True Brg - Declination // VOR headings are always magnetic (Hdg) if (FixListDataGridView.SelectedRows.Count > 0) { string FixText = string.Empty; double[] Coords; double Lat = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[1].Value); double Lon = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[2].Value); // VORs are in bearings and need no adjustment //double MagVar = Convert.ToDouble(MagVarTextBox.Text); if (FixOffsetCheckBox.Checked) { double Dist = Convert.ToDouble(FixDistTextBox.Text); double Brg = Convert.ToDouble(FixBrgNUD.Value); //if (FixListDataGridView.SelectedRows[0].Cells[3].Value != null) //MagVar = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[3].Value); Coords = LatLongCalc.Destination(Lat, Lon, Dist, Brg, 'N'); Lat = Coords[0]; Lon = Coords[1]; FixText = String.Format("{0:000}", FixBrgNUD.Value) + String.Format("{0:000.0}", Convert.ToDouble(FixDistTextBox.Text)); } CenterLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); CenterLat = Lat; CenterLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); CenterLon = Lon; //MagVarTextBox.Text = MagVar.ToString(); CenterFixTextBox.Text = FixListDataGridView.SelectedRows[0].Cells[0].Value.ToString() + FixText; UpdateStats(); } }
private void ImportFixToHold() { // East declination is positive; west is negative // True (map) Heading = Mag Bearing + Declination // Mag Hdg = True Brg - Declination // VOR headings are always magnetic (Hdg) if (FixListDataGridView.SelectedRows.Count > 0) { string FixText = string.Empty; double[] Coords; double Lat = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[1].Value); double Lon = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[2].Value); // VORs are in bearings and need no adjustment //double MagVar = Convert.ToDouble(MagVarTextBox.Text); if (FixOffsetCheckBox.Checked) { double Dist = Convert.ToDouble(FixOffsetDistTextBox.Text); double Brg = Convert.ToDouble(FixOffsetBrgNUD.Value); //if (FixListDataGridView.SelectedRows[0].Cells[3].Value != null) //MagVar = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[3].Value); Coords = LatLongCalc.Destination(Lat, Lon, Dist, Brg, 'N'); Lat = Coords[0]; Lon = Coords[1]; FixText = String.Format("{0:000}", FixOffsetBrgNUD.Value) + String.Format("{0:000.0}", Convert.ToDouble(FixOffsetDistTextBox.Text)); } HoldLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); HoldLat = Lat; HoldLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); HoldLon = Lon; //MagVarTextBox.Text = MagVar.ToString(); HoldFixTextBox.Text = FixListDataGridView.SelectedRows[0].Cells[0].Value.ToString() + FixText; AddFixLabelCheckBox.Enabled = AddFixSymbolCheckBox.Enabled = (HoldFixTextBox.TextLength != 0); } }
private void InsertCoordsButton_Click(object sender, EventArgs e) { if ((CenterLat == -1) || (CenterLon == -1)) { SCTcommon.SendMessage("First select the center point of the arc."); return; } if ((CalcDistanceTextBox.TextLength == 0) || (Convert.ToDouble(CalcDistanceTextBox.Text) < 1)) { SCTcommon.SendMessage("Radius of arc must be at least 1 NM"); return; } else { double[] Coords; double CenterLat = Conversions.DMS2Degrees(CenterLatitudeTextBox.Text); double CenterLon = Conversions.DMS2Degrees(CenterLongitudeTextBox.Text); double Dist = Convert.ToDouble(CalcDistanceTextBox.Text); double BrgStart = Convert.ToDouble(StartRadialNUD.Value); double BrgEnd = Convert.ToDouble(EndRadialNUD.Value); double MagVar = Convert.ToDouble(MagVarTextBox.Text); double Lat; double Lon; if (CircleCheckBox.Checked) { Coords = LatLongCalc.Destination(CenterLat, CenterLon, Dist, 90, 'N'); Lat = Coords[0]; Lon = Coords[1]; StartLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); StartLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); StartLat = Lat; StartLon = Lon; EndLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); EndLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); EndLat = Lat; EndLon = Lon; } else { if (MagBrgCheckBox.Checked == true) { BrgStart -= MagVar; BrgEnd -= MagVar; } Coords = LatLongCalc.Destination(CenterLat, CenterLon, Dist, BrgStart, 'N'); Lat = Coords[0]; Lon = Coords[1]; StartLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); StartLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); StartLat = Lat; StartLon = Lon; Coords = LatLongCalc.Destination(CenterLat, CenterLon, Dist, BrgEnd, 'N'); Lat = Coords[0]; Lon = Coords[1]; EndLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); EndLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); EndLat = Lat; EndLon = Lon; } UpdateStats(); } }
private void FixToEndButton_Click(object sender, EventArgs e) { if (FixListDataGridView.SelectedRows.Count > 0) { string FixText = string.Empty; double[] Coords; double Lat = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[1].Value); double Lon = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[2].Value); // VORs are in bearings and need no adjustment //double MagVar = Convert.ToDouble(MagVarTextBox.Text); if (FixOffsetCheckBox.Checked) { double Dist = Convert.ToDouble(FixDistTextBox.Text); double Brg = Convert.ToDouble(FixBrgNUD.Value); //if (FixListDataGridView.SelectedRows[0].Cells[3].Value != null) //MagVar = Convert.ToDouble(FixListDataGridView.SelectedRows[0].Cells[3].Value); Coords = LatLongCalc.Destination(Lat, Lon, Dist, Brg, 'N'); Lat = Coords[0]; Lon = Coords[1]; FixText = String.Format("{0:000}", FixBrgNUD.Value) + String.Format("{0:000.0}", Convert.ToDouble(FixDistTextBox.Text)); } EndLatitudeTextBox.Text = Conversions.Degrees2SCT(Lat, true); EndLat = Lat; EndLongitudeTextBox.Text = Conversions.Degrees2SCT(Lon, false); EndLon = Lon; //MagVarTextBox.Text = MagVar.ToString(); EndFixTextBox.Text = FixListDataGridView.SelectedRows[0].Cells[0].Value.ToString() + FixText; UpdateStats(); } }
private void ChordStats() { ChordLength = LatLongCalc.Distance(EndLat, EndLon, StartLat, StartLon); ChordArcAngle = LatLongCalc.Deg2Rad(Math.Abs(StartBrg = EndBrg)); ChordArcLength = ChordArcAngle * ArcRadius; ChordRadius = ChordArcLength / 2; ChordLengthTextBox.Text = ChordLength.ToString("F3"); ChordRadiusTextBox.Text = ChordRadius.ToString("F3"); ChordArcLengthTextBox.Text = ChordArcLength.ToString("F3"); }
private void FixEndCoordButton_Click(object sender, EventArgs e) { double[] coords = LatLongCalc.Destination(CenterLat, CenterLon, ArcRadius, Convert.ToDouble(EndRadialNUD.Value), 'N'); EndLat = coords[0]; EndLon = coords[1]; EndLatitudeTextBox.Text = Conversions.Degrees2SCT(EndLat, true); EndLongitudeTextBox.Text = Conversions.Degrees2SCT(EndLon, false); UpdateStats(); }
private void RadBrgStartButton_Click(object sender, EventArgs e) { double[] coords = new double[2]; if ((CenterLat != -1) && (CenterLon != -1)) { coords = LatLongCalc.Destination(CenterLat, CenterLon, ArcRadius, Convert.ToDouble(StartRadialNUD.Value), 'N'); StartLat = coords[0]; StartLon = coords[1]; StartLatitudeTextBox.Text = Conversions.Degrees2SCT(StartLat, true); StartLongitudeTextBox.Text = Conversions.Degrees2SCT(StartLon, false); } }
private void UpdateStats() { if ((CenterLat != -1) && (CenterLon != -1)) { if ((StartLat != -1) && (StartLon != -1)) { StartBrg = LatLongCalc.Bearing(CenterLat, CenterLon, StartLat, StartLon); if (StartBrg == 0) { StartBrg = 360; } StartRadialNUD.Value = Convert.ToInt32(StartBrg); ArcRadius = LatLongCalc.Distance(CenterLat, CenterLon, StartLat, StartLon); CalcDistanceTextBox.Text = ArcRadius.ToString("F3"); } else { ArcRadius = -1; StartBrg = -1; StartRadialNUD.Value = 1; CalcDistanceTextBox.Text = string.Empty; } if ((EndLat != -1) && (EndLon != -1)) { EndBrg = LatLongCalc.Bearing(CenterLat, CenterLon, EndLat, EndLon); if (EndBrg == 0) { EndBrg = 360; } EndRadialNUD.Value = Convert.ToInt32(EndBrg); EndDistTextBox.Text = LatLongCalc.Distance(CenterLat, CenterLon, EndLat, EndLon).ToString("F3"); if (ArcRadius != -1) { ChordStats(); } } else { EndBrg = -1; EndRadialNUD.Value = 1; EndDistTextBox.Text = string.Empty; } } else { ArcRadius = EndBrg = StartBrg - 1; } CheckArcButton(); }
public static float[] Adjust(float lat, float lon, float LeftRightSeconds, float UpDownSeconds, int Angle = 0, float Scale = 1) { // X and Y are Hershey units (one char is 30 x 30) // Latitude is Y and Longitude is X float[] result = new float[2]; PointF Origin = new PointF(lon, lat); SizeF Offset = new SizeF(LeftRightSeconds / 3600, UpDownSeconds / 3600); PointF Coord = PointF.Add(Origin, Offset); int angle = (int)InfoSection.MagneticVariation + Angle; Coord = LatLongCalc.RotatePoint(Coord, Origin, angle); result[0] = Coord.Y; result[1] = Coord.X; return(result); }
private string BuildArcString(double StartBrg, double EndBrg, double StartLat, double StartLon) { string Lat0 = string.Empty; string Lon0 = string.Empty; string Lat1; string Lon1; string output = string.Empty; double[] Coords; // Make sure we aren't crossing 360... if ((StartBrg + Math.Abs(EndBrg - StartBrg)) > 360) { for (double i = StartBrg; i < 360; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } for (double i = 1; i < EndBrg; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } } else { for (double i = StartBrg; i < EndBrg; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } } // Draw last segment Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, EndBrg, 'N'); PasteLat = Coords[0]; PasteLon = Coords[1]; Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); return(output); }
private void CenterFromChord() { // The center is perpendicular to the midpoint of the start/end chord // Since I'm always turning to the right, perpendicular is always +90 double Lat0 = (StartLat + EndLat) / 2.0; double Lon0 = (StartLon + EndLon) / 2.0; double Brg = (LatLongCalc.Bearing(StartLat, StartLon, EndLat, EndLon) + 90) % 360; double[] Coords = LatLongCalc.Destination(Lat0, Lon0, RadiusFromChordArc(), Brg, 'N'); CenterLat = Coords[0]; CenterLon = Coords[1]; CenterLatitudeTextBox.Text = Conversions.Degrees2SCT(CenterLat, true); CenterLongitudeTextBox.Text = Conversions.Degrees2SCT(CenterLon, false); CenterFixTextBox.Text = "<calculated from chord>"; StartBrg = (LatLongCalc.Bearing(CenterLat, CenterLon, StartLat, StartLon) + 90) % 360; StartRadialNUD.Value = (int)StartBrg; EndBrg = (LatLongCalc.Bearing(CenterLat, CenterLon, EndLat, EndLon) + 90) % 360; EndRadialNUD.Value = (int)EndBrg; }
private string BuildArcString() { string Lat0 = string.Empty; string Lon0 = string.Empty; string Lat1; string Lon1; string output = string.Empty; double[] Coords; if (CircleCheckBox.Checked) { StartBrg = 0; EndBrg = 360; } // Make sure we aren't crossing 360... if ((StartBrg + (EndBrg - StartBrg)) > 360) { for (double i = StartBrg; i < 360; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } for (double i = 1; i < EndBrg; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } } else { for (double i = StartBrg; i < EndBrg; i++) { Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, i, 'N'); Lat1 = Conversions.Degrees2SCT(Coords[0], true); Lon1 = Conversions.Degrees2SCT(Coords[1], false); output += OutputText(Lat0, Lon0, Lat1, Lon1); Lat0 = Lat1; Lon0 = Lon1; } } return(output); }
public static double NMperLongDegree() { // Assumes all Lat/Longs are in Decimal degrees double DegPerNMequator = 69.172; double radCenterLat; // Use the user's desired center if possible if (InfoSection.CenterLatitude_Dec == 0) { radCenterLat = LatLongCalc.Deg2Rad((FilterBy.NorthLimit + FilterBy.SouthLimit) / 2); } else { radCenterLat = LatLongCalc.Deg2Rad(InfoSection.CenterLatitude_Dec); } double result = Math.Cos(radCenterLat) * DegPerNMequator; return(result); }
public static PointF RotatePoint(PointF pointToRotate, PointF centerPoint, double angleInDegrees) { // Given a center point and point to rotate (aka a line), rotate the line X degrees double radians = LatLongCalc.Deg2Rad(angleInDegrees); double sin = Math.Sin(radians); double cos = Math.Cos(radians); // Translate point back to origin pointToRotate.X -= centerPoint.X; pointToRotate.Y -= centerPoint.Y; // Rotate point double xnew = pointToRotate.X * cos - pointToRotate.Y * sin; double ynew = pointToRotate.X * sin + pointToRotate.Y * cos; // Translate point back PointF newPoint = new PointF((float)xnew + centerPoint.X, (float)ynew + centerPoint.Y); return(newPoint); }
private static string DrawChar(char c, int[] hFont, PointF origin, int Angle, float Scale) { // Each vector needs to be (a) rotate to the angle of the line of text and (b) Scaled // One unit vector = 1 second or 90-100 feet. Use the Scale function to adjust. string result = string.Empty; float X; float Y; bool isFirst = true; string cr = Environment.NewLine; int angle = (int)InfoSection.MagneticVariation + Angle; float scale = Scale / 3600F; PointF end; PointF start = PointF.Empty; // Rotate through vectors in usual manner for (int i = 2; i < hFont.Length; i += 2) { Y = hFont[i + 1]; X = hFont[i]; // X-Lon, Y-Lat if ((X == -1) || (Y == -1)) // Next point is a break { end = PointF.Empty; } else // Get next vector (which will get moved to Start) { SizeF vector = new SizeF(X * scale, Y * scale); end = PointF.Add(origin, vector); end = LatLongCalc.RotatePoint(end, origin, angle); } if (!(start.IsEmpty) && !(end.IsEmpty)) { result += SCTstrings.CharOut(Conversions.DecDeg2SCT(start.Y, true), Conversions.DecDeg2SCT(start.X, false), Conversions.DecDeg2SCT(end.Y, true), Conversions.DecDeg2SCT(end.X, false)); if (isFirst) { result += ";" + c.ToString(); isFirst = false; } result += cr; } start = end; // No matter what happened, move End to Start } return(result); // Lat Long string to draw ONE character! (Sheesh) }
public static string DrawSymbol(object[] FixData) { // FixData contains: ID(opt), FacilityID, Frequency(opt), Latitude, Longitude, NameOrUse, FixType string Lat0; string Lon0; string Lat1; string Lon1; string cr = Environment.NewLine; string space = new string(' ', 27); int angle = (int)InfoSection.MagneticVariation; string Fix = FixData[1].ToString(); string FixType = FixData[6].ToString(); if (FixType == "FIX") { FixType = FixData[5].ToString(); } float lat = Convert.ToSingle(FixData[3]); float lon = Convert.ToSingle(FixData[4]); int[] Symbol = SymbolRef(FixType); // Declare values used in loop below PointF[] Coords = new PointF[Symbol[0]]; float myX; float myY; // Loop through the symbol points, creating the initial pattern int Counter = 0; for (int i = 2; i <= Symbol[0] * 2; i += 2) { myX = Symbol[i + 1]; myY = Symbol[i]; // Lat is Y, Lon is X if ((myY != -1) && (myX != -1)) { Coords[Counter] = new PointF(myX /= 3600F, myY /= 3600F); } else { Coords[Counter] = new PointF(-1F, -1F); } Counter++; } // Rotate the symbol to True North - with the first point as the origin (skip breaks) // WHY is Mag Var correct, but rotation is NOT? PointF PenUp = new PointF(-1, -1); for (int i = 0; i < Coords.Length; i++) { if (Coords[i] != PenUp) { Coords[i] = LatLongCalc.RotatePoint(Coords[i], Coords[0], angle); } } // Get the centroid PointF centroid = LatLongCalc.Centroid(Coords); // Find the offset of the centroid from the FIX SizeF CentOffset = new SizeF(lon - centroid.X, lat - centroid.Y); // Move the symbol so it appears over the FIX for (int i = 0; i < Coords.Length; i++) { if (Coords[i] != PenUp) { Coords[i] = PointF.Add(Coords[i], CentOffset); } } // Now write out the symbol strings in typical end-to-start rotation PointF start = PointF.Empty; PointF end; string Result = space + "; Symbol for " + FixType + " " + Fix + cr; foreach (PointF pointF in Coords) { if (pointF != PenUp) { end = pointF; } else { end = PointF.Empty; } if (!(start.IsEmpty) && !(end.IsEmpty)) { Lat0 = Conversions.DecDeg2SCT(start.Y, true); Lat1 = Conversions.DecDeg2SCT(end.Y, true); Lon0 = Conversions.DecDeg2SCT(start.X, false); Lon1 = Conversions.DecDeg2SCT(end.X, false); Result += SCTstrings.SSDout(Lat0, Lon0, Lat1, Lon1) + cr; } start = end; } return(Result); }
private string BuildRaceTrack() { string output = string.Empty; // Step 1 - build leg away from hold fix double StartLat = HoldLat; double StartLon = HoldLon; double StartBrg; double EndBrg; double EndLat; double EndLon; double[] Coords; string Lat0; string Lon0; string Lat1; string Lon1; double OutTrack = Track; if (InboundTrackRadioButton.Checked) { OutTrack = Track + 540 % 360; // Reverse track to outbnd } Coords = LatLongCalc.Destination(StartLat, StartLon, LegLnthDist, OutTrack, 'N'); EndLat = Coords[0]; EndLon = Coords[1]; Lat0 = Conversions.Degrees2SCT(PasteLat, true); Lon0 = Conversions.Degrees2SCT(PasteLon, false); Lat1 = Conversions.Degrees2SCT(EndLat, true); Lon1 = Conversions.Degrees2SCT(EndLon, false); output += OutputText(Lat0, Lon0, Lat1, Lon1); // Step 2 - Enter first turn StartLat = EndLat; StartLon = EndLon; // This is start of turn if (TurnRight) { StartBrg = (OutTrack + 270) % 360; EndBrg = (OutTrack + 90) % 360; } else { EndBrg = (OutTrack + 270) % 360; StartBrg = (OutTrack + 90) % 360; } Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, EndBrg, 'N'); double CenterLat = Coords[0]; double CenterLon = Coords[1]; // Center of arc output += BuildArcString(StartBrg, EndBrg, CenterLat, CenterLon); // Build Arc 1 // Step 3 - Return leg // Need to close the end of arc with next line Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius * 2, EndBrg, 'N'); StartLat = Coords[0]; StartLon = Coords[1]; Lat0 = Conversions.Degrees2SCT(PasteLat, true); Lon0 = Conversions.Degrees2SCT(PasteLon, false); Lat1 = Conversions.Degrees2SCT(StartLat, true); Lon1 = Conversions.Degrees2SCT(StartLon, false); output += OutputText(Lat0, Lon0, Lat1, Lon1); // Now draw the leg line double InTrack = (OutTrack + 180) % 360; Coords = LatLongCalc.Destination(StartLat, StartLon, LegLnthDist, InTrack, 'N'); EndLat = Coords[0]; EndLon = Coords[1]; Lat0 = Conversions.Degrees2SCT(StartLat, true); Lon0 = Conversions.Degrees2SCT(StartLon, false); Lat1 = Conversions.Degrees2SCT(EndLat, true); Lon1 = Conversions.Degrees2SCT(EndLon, false); output += OutputText(Lat0, Lon0, Lat1, Lon1); // Step 4 - Return arc if (TurnRight) { EndBrg = (OutTrack + 270) % 360; StartBrg = (OutTrack + 90) % 360; } else { StartBrg = (OutTrack + 270) % 360; EndBrg = (OutTrack + 90) % 360; } StartLat = EndLat; StartLon = EndLon; Coords = LatLongCalc.Destination(StartLat, StartLon, ArcRadius, EndBrg, 'N'); CenterLat = Coords[0]; CenterLon = Coords[1]; output += BuildArcString(StartBrg, EndBrg, CenterLat, CenterLon); if (DrawFixSymbol) { output += DrawFix_Symbol(); } if (DrawFixLabel) { output += DrawFix_Label(); } return(output); }