Skip to content

Instantly share code, notes, and snippets.

@JeffJacobson
Created March 29, 2012 20:39
Show Gist options
  • Save JeffJacobson/2243571 to your computer and use it in GitHub Desktop.
Save JeffJacobson/2243571 to your computer and use it in GitHub Desktop.
WA State Route related extension methods for .NET
/*
* Jeff Jacobson, CGIS, ITS3
* 2008-09
*/
using System.Text.RegularExpressions;
using System;
namespace Wsdot.Cgis.Extensions
{
/// <summary>
/// This <see langword="static"/> <see langword="class"/> provides extension methods for dealing with State Route ID strings.
/// </summary>
public static class RouteExtensions
{
private const string
////_SRID_PATTERN = @"(?in)(?<sr>\d{3})(?:(?<rrt>[A-Za-z0-9]{2})(?<rrq>[A-Za-z0-9]{0,6}))?",
// A regular expression matching a valid state route identifier.
_SRID_PATTERN =
@"(?inx)
(?<sr>\d{3})
(
(?<rrt>
(AR)|(CO)|(C[DI])|(F[DI])|(LX)|(ML)|(RL)|(SP)|(TB)|(TR)|(PR)|(FU)
# If a value is capture in the ramp group, we know it is a ramp.
|(?<ramp>[PQRS][\dU])
# A capture in the incOnly group indicates an RRT that only occurs in the increase layer.
# All others (excluding ramps) occur in both increasing and decreasing layers. (Based on info provided by Masao Matsuoka and Eric Jackson.)
|(?<incOnly>H[ID])
# A capture in this group means a ferry RRT.
|(?<ferry>F[ST])
)
(?<rrq>[A-Za-z0-9]{0,6})
)?";
private const string
_RAMP_RRT_PATTERN = @"(?i)[PQRS][\dU]",
////_DEC_RRT_PATTERN = @"(?in)(AR)|(CO)|(F[DI])|(FU)|(LX)|(RL)|(SP)",
////_INC_RRT_PATTERN = @"(?n)(AR)|(CO)|(F[DI])|(FU)|(H[DI])|(LX)|(RL)|(SP)";
_INC_ONLY_RRT_PATTERN = @"H[ID]";
private static readonly Regex
_srIdRegex = new Regex(_SRID_PATTERN),
_rampRrtRegex = new Regex(_RAMP_RRT_PATTERN);
/// <summary>
/// Attempts to split a state route string into its component SR, RRT, and RRQ parts.
/// </summary>
/// <param name="srid">A state route identifier string.</param>
/// <param name="sr">Output: The three digit route identifier.</param>
/// <param name="rrt">Output: The two character related route type (RRT) string, if applicable; otherwise, <see cref="string.Empty"/>.</param>
/// <param name="rrq">Output: The Related Roadway Qualifier string, if applicable; <see cref="string.Empty"/> otherwise.</param>
/// <returns>
/// Returns <see langword="true"/> if <paramref name="srid"/> is a properly formatted state route identifier.
/// Returns <see langword="false"/> otherwise.
/// </returns>
/// <remarks>
/// Note that this method does not check against all possible RRTs and RRQs; only the format of these strings is checked.
/// I.e., SR must be three digit characters, RRT (if provided) must consist of two digit or letter characters, RRQ (if RRT provided) must be between 0-6 digit or letter characters long.
/// </remarks>
public static bool TrySplitSRId(this string srid, out string sr, out string rrt, out string rrq)
{
sr = rrt = rrq = null;
bool output = false;
// We already know that the input is not valid if it is null or empty.
if (!string.IsNullOrEmpty(srid))
{
// Use the regex to see if the SRID is valid.
Match srMatch = _srIdRegex.Match(srid);
if (srMatch.Success)
{
GroupCollection groups = srMatch.Groups;
sr = groups["sr"].Value;
rrt = groups["rrt"].Value;
rrq = groups["rrq"].Value;
output = true;
}
}
return output;
}
public static bool IsValidSRId(this string srid)
{
if (string.IsNullOrEmpty(srid)) return false;
return _srIdRegex.IsMatch(srid);
}
public static bool isRampSRId(this string srId)
{
if (string.IsNullOrEmpty(srId)) return false;
Match m = _srIdRegex.Match(srId);
if (m.Success)
{
Group rampGroup = m.Groups["ramp"];
if (rampGroup.Success && rampGroup.Length > 0)
{
return true;
}
}
return false;
}
public static bool IsRampRrt(this string rrt)
{
if (string.IsNullOrEmpty(rrt)) return false;
return _rampRrtRegex.IsMatch(rrt);
}
public static char GetRouteType(this string srId, bool decrease)
{
const char RAMP = 'R', INC = 'I', DEC = 'D';
if (string.IsNullOrEmpty(srId)) throw new ArgumentException("Invalid SRID. SRID cannot be null or empty.", "srId");
Match m = _srIdRegex.Match(srId);
if (string.IsNullOrEmpty(srId)) throw new ArgumentException("Invalid SRID.", "srId");
GroupCollection groups = m.Groups;
// If the RRT indicates a ramp...
Group rampGroup = groups["ramp"];
if (rampGroup.Success && rampGroup.Length > 0)
{
return RAMP;
}
// If the RRT is only in the INC layer, or the user specified increase, return INC. Otherwise return DEC.
Group incOnlyGroup = groups["incOnly"];
if ((incOnlyGroup.Success && incOnlyGroup.Length > 0) || !decrease)
{
return INC;
}
else
{
return DEC;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment