kopia lustrzana https://github.com/dl2alf/AirScout
673 wiersze
24 KiB
C#
673 wiersze
24 KiB
C#
/*
|
|
* Author: G. Monz (DK7IO), 2011-11-30
|
|
* This file is distributed without any warranty.
|
|
* */
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Windows;
|
|
|
|
namespace ScoutBase.Core
|
|
{
|
|
/// <summary>
|
|
/// Converts geographical coordinates to a 'Maidenhead Locator' and vice versa.
|
|
/// </summary>
|
|
public static class MaidenheadLocator
|
|
{
|
|
#region Constants
|
|
#region Number of zones
|
|
/// <summary>
|
|
/// Number of zones for 'Field' (Precision step 1).
|
|
/// </summary>
|
|
public const int ZonesOddStep1 = 18;
|
|
|
|
/// <summary>
|
|
/// Number of zones for 'Subsquare', 'Subsubsubsquare', etc. (Precision steps 3, 5, etc.).
|
|
/// </summary>
|
|
public const int ZonesOddStepsExcept1 = 24;
|
|
|
|
/// <summary>
|
|
/// Number of zones for 'Square', 'Subsubsquare', etc. (Precision steps 2, 4, etc.).
|
|
/// </summary>
|
|
public const int ZonesEvenSteps = 10;
|
|
#endregion
|
|
|
|
#region First characters for locator text
|
|
/// <summary>
|
|
/// The first character for 'Field' (Precision step 1).
|
|
/// </summary>
|
|
public const char FirstOddStep1Character = 'A';
|
|
|
|
/// <summary>
|
|
/// The first character for 'Subsquare', 'Subsubsubsquare', etc. (Precision steps 3, 5, etc.).
|
|
/// </summary>
|
|
public const char FirstOddStepsExcept1Character = 'a';
|
|
|
|
/// <summary>
|
|
/// The first character for 'Square', 'Subsubsquare', etc. (Precision steps 2, 4, etc.).
|
|
/// </summary>
|
|
public const char FirstEvenStepsCharacter = '0';
|
|
#endregion
|
|
|
|
#region Implementation constraints
|
|
/// <summary>
|
|
/// The lowest allowed precision.
|
|
/// </summary>
|
|
public const int MinPrecision = 1;
|
|
|
|
/// <summary>
|
|
/// The highest allowed precision.
|
|
/// </summary>
|
|
public const int MaxPrecision = 9;
|
|
#endregion
|
|
#endregion
|
|
|
|
/// <summary>
|
|
/// The subgrids filter within a grid.
|
|
/// </summary>
|
|
public enum SubGridsFilter
|
|
{
|
|
/// <summary>
|
|
/// All subgrids.
|
|
/// </summary>
|
|
All,
|
|
|
|
/// <summary>
|
|
/// Top subgrids only.
|
|
/// </summary>
|
|
Top,
|
|
|
|
/// <summary>
|
|
/// Bottom subgrids only.
|
|
/// </summary>
|
|
Bottom,
|
|
|
|
/// <summary>
|
|
/// Left subgrids only.
|
|
/// </summary>
|
|
Left,
|
|
|
|
/// <summary>
|
|
/// Right subgrids only.
|
|
/// </summary>
|
|
Right,
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if a string is a valid Maidenhead Locator.
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The Maidenhead Locator.</param>
|
|
/// <returns>True if the given string is a valid Maidenhead Locator.</returns>
|
|
public static bool Check(string maidenheadLocator)
|
|
{
|
|
// chekc for empty string
|
|
if (String.IsNullOrEmpty(maidenheadLocator))
|
|
return false;
|
|
// make string upper
|
|
maidenheadLocator = maidenheadLocator.ToUpper();
|
|
// string must have even length
|
|
if (maidenheadLocator.Length % 2 != 0)
|
|
return false;
|
|
// string must have MinPrecision
|
|
if (maidenheadLocator.Length / 2 < MinPrecision)
|
|
return false;
|
|
// string must not have more than MaxPrecision
|
|
if (maidenheadLocator.Length / 2 > MaxPrecision)
|
|
return false;
|
|
for (int i = 0; i < maidenheadLocator.Length; i++)
|
|
{
|
|
if ((i % 4) <= 1)
|
|
{
|
|
if ((maidenheadLocator[i] < 'A') || (maidenheadLocator[i] > 'X'))
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
if (!char.IsDigit(maidenheadLocator[i]))
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Checks if a given location (by lat/lon) is precise, e.g. is not located at midpoint of a given Maidenhead Locator
|
|
/// </summary>
|
|
/// <param name="latitude">The geographic latitude.</param>
|
|
/// <param name="longitude">The geographic longitude.</param>
|
|
/// <param name="precision">
|
|
/// The precision for conversion, must be >=1 and <=9.
|
|
/// <para></para>
|
|
/// <list type="bullet">
|
|
/// <listheader>
|
|
/// <description>Examples for precision use:</description>
|
|
/// </listheader>
|
|
/// <item><term>precision1</term><description>HF: 'Field' only is needed -> precision=1 -> JN</description></item>
|
|
/// <item><term>precision2</term><description>6m: 'Field' and 'Square' is needed -> precision=2 -> JN39</description></item>
|
|
/// <item><term>precision3</term><description>VHF/UHF: 'Field' until 'Subsquare' is needed -> precision=3 -> JN39ml</description></item>
|
|
/// <item><term>precision4</term><description>SHF/EHF: 'Field' until 'Subsubsquare' is needed -> precision=4 -> JN39ml36</description></item>
|
|
/// </list>
|
|
/// <returns>True if the given location is precise .</returns>
|
|
public static bool IsPrecise(double latitude, double longitude, int precision)
|
|
{
|
|
double mlat, mlon;
|
|
string loc = LocFromLatLon(latitude, longitude, false, precision);
|
|
if (String.IsNullOrEmpty(loc))
|
|
return false;
|
|
LatLonFromLoc(loc, PositionInRectangle.MiddleMiddle, out mlat, out mlon);
|
|
return (Math.Abs(mlat - latitude) > 0.00001) || (Math.Abs(mlon - longitude) > 0.00001);
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a given Maidenhead Locator with format options
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The Maidenhead Locator.</param>
|
|
/// <param name="smallLettersForSubsquares">If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.</param>
|
|
/// <returns>The new formatted Maidenhead Locator.</returns>
|
|
/// <exception cref="ArgumentException">If the string is not a Maidenhead locator.</exception>
|
|
public static string Convert(string maidenheadLocator, bool smallLettersForSubsquares)
|
|
{
|
|
// return null on null
|
|
if (maidenheadLocator == null)
|
|
return null;
|
|
// return empty string on empty
|
|
if (maidenheadLocator == "")
|
|
return "";
|
|
// check
|
|
if (!Check(maidenheadLocator))
|
|
throw new ArgumentException("This is not a valid Maidenhead Locator: " + maidenheadLocator);
|
|
string loc = "";
|
|
for (int i = 0; i < maidenheadLocator.Length; i++)
|
|
{
|
|
if (i <= 1)
|
|
loc = loc + Char.ToUpper(maidenheadLocator[i]);
|
|
else if (smallLettersForSubsquares)
|
|
{
|
|
loc = loc + Char.ToLower(maidenheadLocator[i]);
|
|
}
|
|
else
|
|
{
|
|
loc = loc + Char.ToUpper(maidenheadLocator[i]);
|
|
}
|
|
}
|
|
return loc;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts geographical coordinates (latitude and longitude, in degrees)
|
|
/// to a 'Maidenhead Locator' until a specific precision.
|
|
/// The maximum precision is 9 due to numerical limits of floating point operations.
|
|
/// </summary>
|
|
/// <param name="latitude">
|
|
/// The latitude to convert ([-90...+90]).
|
|
/// +90 is handled like +89.999...
|
|
/// </param>
|
|
/// <param name="longitude">
|
|
/// The longitude to convert ([-180...+180]).
|
|
/// +180 is handled like +179.999...
|
|
/// </param>
|
|
/// <param name="smallLettersForSubsquares">If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.</param>
|
|
/// <param name="precision">
|
|
/// The precision for conversion, must be >=1 and <=9.
|
|
/// <para></para>
|
|
/// <list type="bullet">
|
|
/// <listheader>
|
|
/// <description>Examples for precision use:</description>
|
|
/// </listheader>
|
|
/// <item><term>precision1</term><description>HF: 'Field' only is needed -> precision=1 -> JN</description></item>
|
|
/// <item><term>precision2</term><description>6m: 'Field' and 'Square' is needed -> precision=2 -> JN39</description></item>
|
|
/// <item><term>precision3</term><description>VHF/UHF: 'Field' until 'Subsquare' is needed -> precision=3 -> JN39ml</description></item>
|
|
/// <item><term>precision4</term><description>SHF/EHF: 'Field' until 'Subsubsquare' is needed -> precision=4 -> JN39ml36</description></item>
|
|
/// </list>
|
|
/// </param>
|
|
/// <returns>The 'Maidenhead Locator'.</returns>
|
|
/// <exception cref="ArgumentException">If the latitude or longitude exceeds its allowed interval.</exception>
|
|
public static string LocFromLatLon(double latitude, double longitude, bool smallLettersForSubsquares, int precision, bool autolength = false)
|
|
{
|
|
string loc;
|
|
// autolength = false -- > return loc with fixed length
|
|
if (!autolength)
|
|
return LocFromLatLon(latitude, longitude, smallLettersForSubsquares, precision);
|
|
// autolength = true
|
|
int p = 3;
|
|
do
|
|
{
|
|
loc = LocFromLatLon(latitude, longitude, smallLettersForSubsquares, p);
|
|
if (IsPrecise(latitude, longitude, p))
|
|
p++;
|
|
else
|
|
break;
|
|
}
|
|
while (p <= precision);
|
|
return loc;
|
|
}
|
|
/// <summary>
|
|
/// Converts geographical coordinates (latitude and longitude, in degrees)
|
|
/// to a 'Maidenhead Locator' until a specific precision.
|
|
/// The maximum precision is 9 due to numerical limits of floating point operations.
|
|
/// </summary>
|
|
/// <param name="latitude">
|
|
/// The latitude to convert ([-90...+90]).
|
|
/// +90 is handled like +89.999...
|
|
/// </param>
|
|
/// <param name="longitude">
|
|
/// The longitude to convert ([-180...+180]).
|
|
/// +180 is handled like +179.999...
|
|
/// </param>
|
|
/// <param name="smallLettersForSubsquares">If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.</param>
|
|
/// <param name="precision">
|
|
/// The precision for conversion, must be >=1 and <=9.
|
|
/// <para></para>
|
|
/// <list type="bullet">
|
|
/// <listheader>
|
|
/// <description>Examples for precision use:</description>
|
|
/// </listheader>
|
|
/// <item><term>precision1</term><description>HF: 'Field' only is needed -> precision=1 -> JN</description></item>
|
|
/// <item><term>precision2</term><description>6m: 'Field' and 'Square' is needed -> precision=2 -> JN39</description></item>
|
|
/// <item><term>precision3</term><description>VHF/UHF: 'Field' until 'Subsquare' is needed -> precision=3 -> JN39ml</description></item>
|
|
/// <item><term>precision4</term><description>SHF/EHF: 'Field' until 'Subsubsquare' is needed -> precision=4 -> JN39ml36</description></item>
|
|
/// </list>
|
|
/// </param>
|
|
/// <returns>The 'Maidenhead Locator'.</returns>
|
|
/// <exception cref="ArgumentException">If the latitude or longitude exceeds its allowed interval.</exception>
|
|
private static string LocFromLatLon(double latitude, double longitude, bool smallLettersForSubsquares, int precision)
|
|
{
|
|
//Check arguments
|
|
{
|
|
if (!GeographicalPoint.Check(latitude, longitude))
|
|
return null;
|
|
}
|
|
|
|
//Corrections
|
|
{
|
|
//MinPrecision <= precision <= MaxPrecision
|
|
precision = Math.Min(MaxPrecision, Math.Max(MinPrecision, precision));
|
|
}
|
|
|
|
//Work
|
|
string result;
|
|
{
|
|
List<char> locatorCharacters = new List<char>();
|
|
|
|
double latitudeWork = latitude + (-GeographicalPoint.LowerLatitudeLimit);
|
|
double longitudeWork = longitude + (-GeographicalPoint.LowerLongitudeLimit);
|
|
|
|
//Zone size for step "0"
|
|
double height;
|
|
double width;
|
|
InitializeZoneSize(out height, out width);
|
|
|
|
for (int step = MinPrecision; step <= precision; step++)
|
|
{
|
|
int zones;
|
|
char firstCharacter;
|
|
RetrieveStepValues(step, smallLettersForSubsquares, out zones, out firstCharacter);
|
|
|
|
//Zone size of current step
|
|
height /= zones;
|
|
width /= zones;
|
|
|
|
//Retrieve zones and locator characters
|
|
int latitudeZone;
|
|
int longitudeZone;
|
|
{
|
|
longitudeZone = GetZone(longitudeWork, width);
|
|
{
|
|
char locatorCharacter = (char)(firstCharacter + longitudeZone);
|
|
locatorCharacters.Add(locatorCharacter);
|
|
}
|
|
|
|
latitudeZone = GetZone(latitudeWork, height);
|
|
{
|
|
char locatorCharacter = (char)(firstCharacter + latitudeZone);
|
|
locatorCharacters.Add(locatorCharacter);
|
|
}
|
|
}
|
|
|
|
if (step <= MaxPrecision - 1)
|
|
{
|
|
//Prepare the next step
|
|
{
|
|
latitudeWork -= latitudeZone * height;
|
|
longitudeWork -= longitudeZone * width;
|
|
|
|
//Numerical corrections
|
|
{
|
|
if (latitudeWork < 0)
|
|
{
|
|
latitudeWork = 0;
|
|
}
|
|
|
|
if (longitudeWork < 0)
|
|
{
|
|
longitudeWork = 0;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
//Build the result (Locator text)
|
|
result = new string(locatorCharacters.ToArray());
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a 'Maidenhead Locator' to geographical coordinates (latitude and longitude, in degrees).
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <param name="positionInRectangle">The position of the geographical coordinates in the locator.</param>
|
|
/// <returns>The geographical latitude.</returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// If the length of the locator text is null or not an even number.
|
|
/// If the locator text contains invalid characters.
|
|
/// </exception>
|
|
|
|
public static double LatFromLoc(string maidenheadLocator, PositionInRectangle positionInRectangle = PositionInRectangle.MiddleMiddle)
|
|
{
|
|
double lat, lon;
|
|
LatLonFromLoc(maidenheadLocator, positionInRectangle, out lat, out lon);
|
|
return lat;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a 'Maidenhead Locator' to geographical coordinates (latitude and longitude, in degrees).
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <param name="positionInRectangle">The position of the geographical coordinates in the locator.</param>
|
|
/// <returns>The geographical longitude.</returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// If the length of the locator text is null or not an even number.
|
|
/// If the locator text contains invalid characters.
|
|
/// </exception>
|
|
|
|
public static double LonFromLoc(string maidenheadLocator, PositionInRectangle positionInRectangle = PositionInRectangle.MiddleMiddle)
|
|
{
|
|
double lat, lon;
|
|
LatLonFromLoc(maidenheadLocator, positionInRectangle, out lat, out lon);
|
|
return lon;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Converts a 'Maidenhead Locator' to geographical point (latitude and longitude, in degrees).
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <param name="positionInRectangle">The position of the geographical coordinates in the locator.</param>
|
|
/// <returns>The geographical point as LatLon.GPoint.</returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// If the length of the locator text is null or not an even number.
|
|
/// If the locator text contains invalid characters.
|
|
/// </exception>
|
|
/// <summary>
|
|
public static LatLon.GPoint GPointFromLoc(string maidenheadLocator, PositionInRectangle positionInRectangle = PositionInRectangle.MiddleMiddle)
|
|
{
|
|
double lat, lon;
|
|
LatLonFromLoc(maidenheadLocator, positionInRectangle, out lat, out lon);
|
|
return new LatLon.GPoint(lat, lon);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Gives the bounds of a 'Maidenhead Locator' (latitudes and longitudes, in degrees).
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <returns>The geographical bounds as LatLon.GRect.</returns>
|
|
/// <exception cref="ArgumentException">
|
|
/// If the length of the locator text is null or not an even number.
|
|
/// If the locator text contains invalid characters.
|
|
/// </exception>
|
|
/// <summary>
|
|
public static LatLon.GRect BoundsFromLoc(string maidenheadLocator)
|
|
{
|
|
LatLon.GPoint gmin = GPointFromLoc(maidenheadLocator, PositionInRectangle.BottomLeft);
|
|
LatLon.GPoint gmax = GPointFromLoc(maidenheadLocator, PositionInRectangle.TopRight);
|
|
return new LatLon.GRect(gmin.Lat, gmin.Lon, gmax.Lat, gmax.Lon);
|
|
}
|
|
|
|
|
|
/// <summary>
|
|
/// Converts a 'Maidenhead Locator' to geographical coordinates (latitude and longitude, in degrees).
|
|
/// </summary>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <param name="positionInRectangle">The position of the geographical coordinates in the locator.</param>
|
|
/// <param name="latitude">The geographical latitude.</param>
|
|
/// <param name="longitude">The geographical longitude.</param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If the length of the locator text is null or not an even number.
|
|
/// If the locator text contains invalid characters.
|
|
/// </exception>
|
|
public static void LatLonFromLoc(string maidenheadLocator, PositionInRectangle positionInRectangle, out double latitude, out double longitude)
|
|
{
|
|
//Check arguments
|
|
{
|
|
if (
|
|
string.IsNullOrEmpty(maidenheadLocator) ||
|
|
maidenheadLocator.Length % 2 != 0
|
|
)
|
|
{
|
|
throw new ArgumentException("Length of locator text is null or not an even number.", "maidenheadLocator");
|
|
}
|
|
}
|
|
|
|
//Corrections
|
|
{
|
|
//Upper cases
|
|
maidenheadLocator = maidenheadLocator.ToUpper();
|
|
}
|
|
//Work
|
|
{
|
|
int precision = maidenheadLocator.Length / 2;
|
|
|
|
latitude = GeographicalPoint.LowerLatitudeLimit;
|
|
longitude = GeographicalPoint.LowerLongitudeLimit;
|
|
|
|
//Zone size for step "0"
|
|
double height;
|
|
double width;
|
|
InitializeZoneSize(out height, out width);
|
|
|
|
for (int step = 1; step <= precision; step++)
|
|
{
|
|
int zones;
|
|
char firstCharacter;
|
|
RetrieveStepValues(step, false, out zones, out firstCharacter);
|
|
|
|
//Zone size of current step
|
|
height /= zones;
|
|
width /= zones;
|
|
|
|
//Retrieve precision specific geographical coordinates
|
|
double longitudeStep = 0;
|
|
double latitudeStep = 0;
|
|
{
|
|
bool error = false;
|
|
int position = -1;
|
|
|
|
if (!error)
|
|
{
|
|
//Longitude
|
|
|
|
position = step * 2 - 2;
|
|
char locatorCharacter = maidenheadLocator[position];
|
|
int zone = (int)(locatorCharacter - firstCharacter);
|
|
|
|
if (zone >= 0 && zone < zones)
|
|
{
|
|
longitudeStep = zone * width;
|
|
}
|
|
else
|
|
{
|
|
error = true;
|
|
}
|
|
}
|
|
|
|
if (!error)
|
|
{
|
|
//Latitude
|
|
|
|
position = step * 2 - 1;
|
|
char locatorCharacter = maidenheadLocator[position];
|
|
int zone = (int)(locatorCharacter - firstCharacter);
|
|
|
|
if (zone >= 0 && zone < zones)
|
|
{
|
|
latitudeStep = zone * height;
|
|
}
|
|
else
|
|
{
|
|
error = true;
|
|
}
|
|
}
|
|
|
|
if (error)
|
|
{
|
|
throw new ArgumentException("Locator text contains an invalid character at position " + (position + 1) + " (Current precision step is " + step + ").", "maidenheadLocator");
|
|
}
|
|
}
|
|
longitude += longitudeStep;
|
|
latitude += latitudeStep;
|
|
}
|
|
|
|
//Corrections according argument positionInRectangle
|
|
GeographicalPoint.ShiftPositionInRectangle(ref latitude, ref longitude, positionInRectangle, height, width);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Retrieves a list of subgrids for a given 'Maidenhead Locator'.
|
|
/// There is no check for invalid input characters.
|
|
/// </summary>
|
|
/// <param name="subGridsFilter">A <see cref="SubGridsFilter" /> member (subgrids filter).</param>
|
|
/// <param name="maidenheadLocator">The 'Maidenhead Locator'.</param>
|
|
/// <param name="smallLettersForSubsquares">If true: generate small (if false: big) letters for 'Subsquares', 'Subsubsquare', etc.</param>
|
|
/// <param name="reverse">If true: reverse the order.</param>
|
|
/// <returns>The list of subgrids.</returns>
|
|
/// <exception cref="ArgumentException">If the length of the locator text is not an even number.</exception>
|
|
public static List<string> GetSubGrids(string maidenheadLocator, SubGridsFilter subGridsFilter, bool smallLettersForSubsquares, bool reverse)
|
|
{
|
|
if (maidenheadLocator == null)
|
|
{
|
|
maidenheadLocator = string.Empty;
|
|
}
|
|
|
|
int length = maidenheadLocator.Length;
|
|
|
|
//Check arguments
|
|
{
|
|
if (length % 2 != 0)
|
|
{
|
|
throw new ArgumentException("Length of locator text is not an even number.", "maidenheadLocator");
|
|
}
|
|
}
|
|
|
|
List<string> result = new List<string>();
|
|
|
|
int subPrecision = length / 2 + 1;
|
|
|
|
int zones;
|
|
char firstCharacter;
|
|
RetrieveStepValues(subPrecision, smallLettersForSubsquares, out zones, out firstCharacter);
|
|
|
|
int wStart = 1;
|
|
int wEnd = zones;
|
|
int hStart = 1;
|
|
int hEnd = zones;
|
|
|
|
switch (subGridsFilter)
|
|
{
|
|
case SubGridsFilter.Top:
|
|
{
|
|
wStart = 1;
|
|
wEnd = hStart = hEnd = zones;
|
|
}
|
|
break;
|
|
case SubGridsFilter.Bottom:
|
|
{
|
|
wStart = hStart = hEnd = 1;
|
|
wEnd = zones;
|
|
}
|
|
break;
|
|
case SubGridsFilter.Left:
|
|
{
|
|
wStart = wEnd = hStart = 1;
|
|
hEnd = zones;
|
|
}
|
|
break;
|
|
case SubGridsFilter.Right:
|
|
{
|
|
wStart = wEnd = hEnd = zones;
|
|
hStart = 1;
|
|
}
|
|
break;
|
|
}
|
|
|
|
for (int wZone = wStart; wZone <= wEnd; wZone++)
|
|
{
|
|
for (int hZone = hStart; hZone <= hEnd; hZone++)
|
|
{
|
|
string subGrid =
|
|
maidenheadLocator +
|
|
(char)(firstCharacter + wZone - 1) +
|
|
(char)(firstCharacter + hZone - 1)
|
|
;
|
|
result.Add(subGrid);
|
|
}
|
|
}
|
|
|
|
if (reverse)
|
|
{
|
|
result.Reverse();
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void InitializeZoneSize(out double height, out double width)
|
|
{
|
|
height = GeographicalPoint.UpperLatitudeLimit - GeographicalPoint.LowerLatitudeLimit;
|
|
width = GeographicalPoint.UpperLongitudeLimit - GeographicalPoint.LowerLongitudeLimit;
|
|
}
|
|
|
|
static void RetrieveStepValues(int step, bool smallLettersForSubsquares, out int zones, out char firstCharacter)
|
|
{
|
|
if (step % 2 == 0)
|
|
{
|
|
//Step is even
|
|
|
|
zones = ZonesEvenSteps;
|
|
firstCharacter = FirstEvenStepsCharacter;
|
|
}
|
|
else
|
|
{
|
|
//Step is odd
|
|
|
|
zones = (step == 1 ? ZonesOddStep1 : ZonesOddStepsExcept1);
|
|
firstCharacter = ((step >= 3 && smallLettersForSubsquares) ? FirstOddStepsExcept1Character : FirstOddStep1Character);
|
|
}
|
|
}
|
|
|
|
static int GetZone(double value, double interval)
|
|
{
|
|
double factor = value / interval;
|
|
int result = (int)factor;
|
|
|
|
//Numerical corrections
|
|
{
|
|
double roundedValue = Utilities.Round(value, interval);
|
|
double diff = roundedValue - value;
|
|
|
|
if (diff < 0.0000000000001)
|
|
{
|
|
if (roundedValue > value)
|
|
{
|
|
result++;
|
|
}
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
}
|
|
} |