//******************************************************************************************************
// Length.cs - Gbtc
//
// Copyright © 2012, Grid Protection Alliance. All Rights Reserved.
//
// Licensed to the Grid Protection Alliance (GPA) under one or more contributor license agreements. See
// the NOTICE file distributed with this work for additional information regarding copyright ownership.
// The GPA licenses this file to you under the MIT License (MIT), the "License"; you may
// not use this file except in compliance with the License. You may obtain a copy of the License at:
//
// http://www.opensource.org/licenses/MIT
//
// Unless agreed to in writing, the subject software distributed under the License is distributed on an
// "AS-IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. Refer to the
// License for the specific language governing permissions and limitations.
//
// Code Modification History:
// ----------------------------------------------------------------------------------------------------
// 01/25/2008 - J. Ritchie Carroll
// Initial version of source generated.
// 09/11/2008 - J. Ritchie Carroll
// Converted to C#.
// 08/10/2009 - Josh L. Patterson
// Edited Comments.
// 09/14/2009 - Stephen C. Wills
// Added new header and license agreement.
// 12/14/2012 - Starlynn Danyelle Gilliam
// Modified Header.
// 10/03/2017 - J. Ritchie Carroll
// Added units enumeration with associated Convert method.
//
//******************************************************************************************************
#region [ Contributor License Agreements ]
/**************************************************************************\
Copyright © 2009 - J. Ritchie Carroll
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 HOLDER "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 OWNER 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.
\**************************************************************************/
#endregion
using System;
using System.ComponentModel;
using System.Globalization;
using System.Runtime.CompilerServices;
namespace GSF.Units
{
#region [ Enumerations ]
///
/// Represents the units available for a value.
///
public enum LengthUnit
{
///
/// Meter length units.
///
Meters,
///
/// Foot length units.
///
Feet,
///
/// Inch length units.
///
Inches,
///
/// Mile length units.
///
Miles,
///
/// Light-second length units.
///
LightSeconds,
///
/// U.S. survey foot length units.
///
USSurveyFeet,
///
/// U.S. survey mile length units.
///
USSurveyMiles,
///
/// Nautical mile length units.
///
NauticalMiles,
///
/// Yard length units.
///
Yards
}
#endregion
///
/// Represents a length measurement, in meters, as a double-precision floating-point number.
///
///
/// This class behaves just like a representing a length in meters; it is implicitly
/// castable to and from a and therefore can be generally used "as" a double, but it
/// has the advantage of handling conversions to and from other length representations, specifically
/// inches, feet, yards, miles, U.S. survey feet, U.S. survey miles, light-seconds, and nautical miles.
/// Metric conversions are handled simply by applying the needed conversion factor, for example:
///
/// Convert length in meters to kilometers:
///
/// public double GetKilometers(Length meters)
/// {
/// return meters / SI.Kilo;
/// }
///
/// This example converts feet to inches:
///
/// public double GetFeet(double inches)
/// {
/// return Length.FromInches(inches).ToFeet();
/// }
///
///
///
[Serializable]
public struct Length : IComparable, IFormattable, IConvertible, IComparable, IComparable, IEquatable, IEquatable
{
#region [ Members ]
// Constants
private const double FeetFactor = 0.3048D;
private const double InchesFactor = 0.0254D;
private const double MilesFactor = 1609.344D;
private const double LightSecondsFactor = 2.99792458E8;
private const double USSurveyFeetFactor = 0.304800610D;
private const double USSurveyMilesFactor = 1609.347219D;
private const double NauticalMilesFactor = 1852.0D;
private const double YardsFactor = 0.9144D;
// Fields
private readonly double m_value; // Length value stored in meters
#endregion
#region [ Constructors ]
///
/// Creates a new .
///
/// New length value in meters.
public Length(double value)
{
m_value = value;
}
#endregion
#region [ Methods ]
///
/// Gets the value in feet.
///
/// Value of in feet.
public double ToFeet()
{
return m_value / FeetFactor;
}
///
/// Gets the value in yards.
///
/// Value of in yards.
public double ToYards()
{
return m_value / YardsFactor;
}
///
/// Gets the value in inches.
///
/// Value of in inches.
public double ToInches()
{
return m_value / InchesFactor;
}
///
/// Gets the value in miles.
///
/// Value of in miles.
public double ToMiles()
{
return m_value / MilesFactor;
}
///
/// Gets the value in light-seconds.
///
/// Value of in light-seconds.
public double ToLightSeconds()
{
return m_value / LightSecondsFactor;
}
///
/// Gets the value in US survey feet.
///
/// Value of in US survey feet.
public double ToUSSurveyFeet()
{
return m_value / USSurveyFeetFactor;
}
///
/// Gets the value in US survey miles.
///
/// Value of in US survey miles.
public double ToUSSurveyMiles()
{
return m_value / USSurveyMilesFactor;
}
///
/// Gets the value in nautical miles.
///
/// Value of in nautical miles.
public double ToNauticalMiles()
{
return m_value / NauticalMilesFactor;
}
///
/// Converts the to the specified .
///
/// Target units.
/// converted to .
public double ConvertTo(LengthUnit targetUnit)
{
switch (targetUnit)
{
case LengthUnit.Meters:
return m_value;
case LengthUnit.Feet:
return ToFeet();
case LengthUnit.Inches:
return ToInches();
case LengthUnit.Miles:
return ToMiles();
case LengthUnit.LightSeconds:
return ToLightSeconds();
case LengthUnit.USSurveyFeet:
return ToUSSurveyFeet();
case LengthUnit.USSurveyMiles:
return ToUSSurveyMiles();
case LengthUnit.NauticalMiles:
return ToNauticalMiles();
case LengthUnit.Yards:
return ToYards();
default:
throw new ArgumentOutOfRangeException(nameof(targetUnit), targetUnit, null);
}
}
#region [ Numeric Interface Implementations ]
///
/// Compares this instance to a specified object and returns an indication of their relative values.
///
/// An object to compare, or null.
///
/// A signed number indicating the relative values of this instance and value. Returns less than zero
/// if this instance is less than value, zero if this instance is equal to value, or greater than zero
/// if this instance is greater than value.
///
/// value is not a or .
public int CompareTo(object value)
{
if (value == null)
return 1;
double num;
if (value is double)
num = (double)value;
else if (value is Length)
num = (Length)value;
else
throw new ArgumentException("Argument must be a Double or a Length");
return m_value < num ? -1 : (m_value > num ? 1 : 0);
}
///
/// Compares this instance to a specified and returns an indication of their
/// relative values.
///
/// A to compare.
///
/// A signed number indicating the relative values of this instance and value. Returns less than zero
/// if this instance is less than value, zero if this instance is equal to value, or greater than zero
/// if this instance is greater than value.
///
public int CompareTo(Length value)
{
return CompareTo((double)value);
}
///
/// Compares this instance to a specified and returns an indication of their
/// relative values.
///
/// A to compare.
///
/// A signed number indicating the relative values of this instance and value. Returns less than zero
/// if this instance is less than value, zero if this instance is equal to value, or greater than zero
/// if this instance is greater than value.
///
public int CompareTo(double value)
{
return m_value < value ? -1 : (m_value > value ? 1 : 0);
}
///
/// Returns a value indicating whether this instance is equal to a specified object.
///
/// An object to compare, or null.
///
/// True if obj is an instance of or and equals the value of this instance;
/// otherwise, False.
///
public override bool Equals(object obj)
{
if (obj is double)
return Equals((double)obj);
if (obj is Length)
return Equals((Length)obj);
return false;
}
///
/// Returns a value indicating whether this instance is equal to a specified value.
///
/// A value to compare to this instance.
///
/// True if obj has the same value as this instance; otherwise, False.
///
public bool Equals(Length obj)
{
return Equals((double)obj);
}
///
/// Returns a value indicating whether this instance is equal to a specified value.
///
/// A value to compare to this instance.
///
/// True if obj has the same value as this instance; otherwise, False.
///
public bool Equals(double obj)
{
return m_value == obj;
}
///
/// Returns the hash code for this instance.
///
///
/// A 32-bit signed integer hash code.
///
public override int GetHashCode()
{
return m_value.GetHashCode();
}
///
/// Converts the numeric value of this instance to its equivalent string representation.
///
///
/// The string representation of the value of this instance, consisting of a minus sign if
/// the value is negative, and a sequence of digits ranging from 0 to 9 with no leading zeros.
///
public override string ToString()
{
return m_value.ToString();
}
///
/// Converts the numeric value of this instance to its equivalent string representation, using
/// the specified format.
///
/// A format string.
///
/// The string representation of the value of this instance as specified by format.
///
public string ToString(string format)
{
return m_value.ToString(format);
}
///
/// Converts the numeric value of this instance to its equivalent string representation using the
/// specified culture-specific format information.
///
///
/// A that supplies culture-specific formatting information.
///
///
/// The string representation of the value of this instance as specified by provider.
///
public string ToString(IFormatProvider provider)
{
return m_value.ToString(provider);
}
///
/// Converts the numeric value of this instance to its equivalent string representation using the
/// specified format and culture-specific format information.
///
/// A format specification.
///
/// A that supplies culture-specific formatting information.
///
///
/// The string representation of the value of this instance as specified by format and provider.
///
public string ToString(string format, IFormatProvider provider)
{
return m_value.ToString(format, provider);
}
///
/// Converts the string representation of a number to its equivalent.
///
/// A string containing a number to convert.
///
/// A equivalent to the number contained in s.
///
/// s is null.
///
/// s represents a number less than or greater than .
///
/// s is not in the correct format.
public static Length Parse(string s)
{
return double.Parse(s);
}
///
/// Converts the string representation of a number in a specified style to its equivalent.
///
/// A string containing a number to convert.
///
/// A bitwise combination of System.Globalization.NumberStyles values that indicates the permitted format of s.
///
///
/// A equivalent to the number contained in s.
///
///
/// style is not a System.Globalization.NumberStyles value. -or- style is not a combination of
/// System.Globalization.NumberStyles.AllowHexSpecifier and System.Globalization.NumberStyles.HexNumber values.
///
/// s is null.
///
/// s represents a number less than or greater than .
///
/// s is not in a format compliant with style.
public static Length Parse(string s, NumberStyles style)
{
return double.Parse(s, style);
}
///
/// Converts the string representation of a number in a specified culture-specific format to its equivalent.
///
/// A string containing a number to convert.
///
/// A that supplies culture-specific formatting information about s.
///
///
/// A equivalent to the number contained in s.
///
/// s is null.
///
/// s represents a number less than or greater than .
///
/// s is not in the correct format.
public static Length Parse(string s, IFormatProvider provider)
{
return double.Parse(s, provider);
}
///
/// Converts the string representation of a number in a specified style and culture-specific format to its equivalent.
///
/// A string containing a number to convert.
///
/// A bitwise combination of System.Globalization.NumberStyles values that indicates the permitted format of s.
///
///
/// A that supplies culture-specific formatting information about s.
///
///
/// A equivalent to the number contained in s.
///
///
/// style is not a System.Globalization.NumberStyles value. -or- style is not a combination of
/// System.Globalization.NumberStyles.AllowHexSpecifier and System.Globalization.NumberStyles.HexNumber values.
///
/// s is null.
///
/// s represents a number less than or greater than .
///
/// s is not in a format compliant with style.
public static Length Parse(string s, NumberStyles style, IFormatProvider provider)
{
return double.Parse(s, style, provider);
}
///
/// Converts the string representation of a number to its equivalent. A return value
/// indicates whether the conversion succeeded or failed.
///
/// A string containing a number to convert.
///
/// When this method returns, contains the value equivalent to the number contained in s,
/// if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is null,
/// is not of the correct format, or represents a number less than or greater than .
/// This parameter is passed uninitialized.
///
/// true if s was converted successfully; otherwise, false.
public static bool TryParse(string s, out Length result)
{
double parseResult;
bool parseResponse;
parseResponse = double.TryParse(s, out parseResult);
result = parseResult;
return parseResponse;
}
///
/// Converts the string representation of a number in a specified style and culture-specific format to its
/// equivalent. A return value indicates whether the conversion succeeded or failed.
///
/// A string containing a number to convert.
///
/// A bitwise combination of System.Globalization.NumberStyles values that indicates the permitted format of s.
///
///
/// When this method returns, contains the value equivalent to the number contained in s,
/// if the conversion succeeded, or zero if the conversion failed. The conversion fails if the s parameter is null,
/// is not in a format compliant with style, or represents a number less than or
/// greater than . This parameter is passed uninitialized.
///
///
/// A object that supplies culture-specific formatting information about s.
///
/// true if s was converted successfully; otherwise, false.
///
/// style is not a System.Globalization.NumberStyles value. -or- style is not a combination of
/// System.Globalization.NumberStyles.AllowHexSpecifier and System.Globalization.NumberStyles.HexNumber values.
///
public static bool TryParse(string s, NumberStyles style, IFormatProvider provider, out Length result)
{
double parseResult;
bool parseResponse;
parseResponse = double.TryParse(s, style, provider, out parseResult);
result = parseResult;
return parseResponse;
}
///
/// Returns the for value type .
///
/// The enumerated constant, .
public TypeCode GetTypeCode()
{
return TypeCode.Double;
}
#region [ Explicit IConvertible Implementation ]
// These are explicitly implemented on the native System.Double implementations, so we do the same...
bool IConvertible.ToBoolean(IFormatProvider provider)
{
return Convert.ToBoolean(m_value, provider);
}
char IConvertible.ToChar(IFormatProvider provider)
{
return Convert.ToChar(m_value, provider);
}
sbyte IConvertible.ToSByte(IFormatProvider provider)
{
return Convert.ToSByte(m_value, provider);
}
byte IConvertible.ToByte(IFormatProvider provider)
{
return Convert.ToByte(m_value, provider);
}
short IConvertible.ToInt16(IFormatProvider provider)
{
return Convert.ToInt16(m_value, provider);
}
ushort IConvertible.ToUInt16(IFormatProvider provider)
{
return Convert.ToUInt16(m_value, provider);
}
int IConvertible.ToInt32(IFormatProvider provider)
{
return Convert.ToInt32(m_value, provider);
}
uint IConvertible.ToUInt32(IFormatProvider provider)
{
return Convert.ToUInt32(m_value, provider);
}
long IConvertible.ToInt64(IFormatProvider provider)
{
return Convert.ToInt64(m_value, provider);
}
ulong IConvertible.ToUInt64(IFormatProvider provider)
{
return Convert.ToUInt64(m_value, provider);
}
float IConvertible.ToSingle(IFormatProvider provider)
{
return Convert.ToSingle(m_value, provider);
}
double IConvertible.ToDouble(IFormatProvider provider)
{
return m_value;
}
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
return Convert.ToDecimal(m_value, provider);
}
DateTime IConvertible.ToDateTime(IFormatProvider provider)
{
return Convert.ToDateTime(m_value, provider);
}
object IConvertible.ToType(Type type, IFormatProvider provider)
{
return Convert.ChangeType(m_value, type, provider) ?? Activator.CreateInstance(type);
}
#endregion
#endregion
#endregion
#region [ Operators ]
#region [ Comparison Operators ]
///
/// Compares the two values for equality.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator ==(Length value1, Length value2)
{
return value1.Equals(value2);
}
///
/// Compares the two values for inequality.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator !=(Length value1, Length value2)
{
return !value1.Equals(value2);
}
///
/// Returns true if left value is less than right value.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator <(Length value1, Length value2)
{
return value1.CompareTo(value2) < 0;
}
///
/// Returns true if left value is less or equal to than right value.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator <=(Length value1, Length value2)
{
return value1.CompareTo(value2) <= 0;
}
///
/// Returns true if left value is greater than right value.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator >(Length value1, Length value2)
{
return value1.CompareTo(value2) > 0;
}
///
/// Returns true if left value is greater than or equal to right value.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result of the operation.
public static bool operator >=(Length value1, Length value2)
{
return value1.CompareTo(value2) >= 0;
}
#endregion
#region [ Type Conversion Operators ]
///
/// Implicitly converts value, represented in meters, to a .
///
/// A value.
/// A object.
public static implicit operator Length(double value)
{
return new Length(value);
}
///
/// Implicitly converts , represented in meters, to a .
///
/// A object.
/// A value.
public static implicit operator double(Length value)
{
return value.m_value;
}
#endregion
#region [ Arithmetic Operators ]
///
/// Returns computed remainder after dividing first value by the second.
///
/// A object left hand operand.
/// A object right hand operand.
/// A object as the result.
public static Length operator %(Length value1, Length value2)
{
return value1.m_value % value2.m_value;
}
///
/// Returns computed sum of values.
///
/// A object left hand operand.
/// A object right hand operand.
/// A object as the result.
public static Length operator +(Length value1, Length value2)
{
return value1.m_value + value2.m_value;
}
///
/// Returns computed difference of values.
///
/// A object left hand operand.
/// A object right hand operand.
/// A object as the result.
public static Length operator -(Length value1, Length value2)
{
return value1.m_value - value2.m_value;
}
///
/// Returns computed product of values.
///
/// A object left hand operand.
/// A object right hand operand.
/// A object as the result.
public static Length operator *(Length value1, Length value2)
{
return value1.m_value * value2.m_value;
}
///
/// Returns computed division of values.
///
/// A object left hand operand.
/// A object right hand operand.
/// A object as the result.
public static Length operator /(Length value1, Length value2)
{
return value1.m_value / value2.m_value;
}
// C# doesn't expose an exponent operator but some other .NET languages do,
// so we expose the operator via its native special IL function name
///
/// Returns result of first value raised to power of second value.
///
/// A object left hand operand.
/// A object right hand operand.
/// A value as the result.
[EditorBrowsable(EditorBrowsableState.Advanced), SpecialName]
public static double op_Exponent(Length value1, Length value2)
{
return Math.Pow(value1.m_value, value2.m_value);
}
#endregion
#endregion
#region [ Static ]
// Static Fields
/// Represents the largest possible value of an . This field is constant.
public static readonly Length MaxValue = double.MaxValue;
/// Represents the smallest possible value of an . This field is constant.
public static readonly Length MinValue = double.MinValue;
// Static Methods
///
/// Creates a new value from the specified in feet.
///
/// New value in feet.
/// New object from the specified in feet.
public static Length FromFeet(double value)
{
return new Length(value * FeetFactor);
}
///
/// Creates a new value from the specified in yards.
///
/// New value in yards.
/// New object from the specified in yards.
public static Length FromYards(double value)
{
return new Length(value * YardsFactor);
}
///
/// Creates a new value from the specified in inches.
///
/// New value in inches.
/// New object from the specified in inches.
public static Length FromInches(double value)
{
return new Length(value * InchesFactor);
}
///
/// Creates a new value from the specified in miles.
///
/// New value in miles.
/// New object from the specified in miles.
public static Length FromMiles(double value)
{
return new Length(value * MilesFactor);
}
///
/// Creates a new value from the specified in light-seconds.
///
/// New value in light-seconds.
/// New object from the specified in light-seconds.
public static Length FromLightSeconds(double value)
{
return new Length(value * LightSecondsFactor);
}
///
/// Creates a new value from the specified in US survey feet.
///
/// New value in US survey feet.
/// New object from the specified in US survey feet.
public static Length FromUSSurveyFeet(double value)
{
return new Length(value * USSurveyFeetFactor);
}
///
/// Creates a new value from the specified in US survey miles.
///
/// New value in US survey miles.
/// New object from the specified in US survey miles.
public static Length FromUSSurveyMiles(double value)
{
return new Length(value * USSurveyMilesFactor);
}
///
/// Creates a new value from the specified in nautical miles.
///
/// New value in nautical miles.
/// New object from the specified in nautical miles.
public static Length FromNauticalMiles(double value)
{
return new Length(value * NauticalMilesFactor);
}
///
/// Converts the in the specified to a new in meters.
///
/// Source value.
/// Source value units.
/// New from the specified in .
public static Length ConvertFrom(double value, LengthUnit sourceUnit)
{
switch (sourceUnit)
{
case LengthUnit.Meters:
return value;
case LengthUnit.Feet:
return FromFeet(value);
case LengthUnit.Inches:
return FromInches(value);
case LengthUnit.Miles:
return FromMiles(value);
case LengthUnit.LightSeconds:
return FromLightSeconds(value);
case LengthUnit.USSurveyFeet:
return FromUSSurveyFeet(value);
case LengthUnit.USSurveyMiles:
return FromUSSurveyMiles(value);
case LengthUnit.NauticalMiles:
return FromNauticalMiles(value);
case LengthUnit.Yards:
return FromYards(value);
default:
throw new ArgumentOutOfRangeException(nameof(sourceUnit), sourceUnit, null);
}
}
#endregion
}
}