/// <summary> /// Returns the unit of strongly typed metric unit to unit with sub units as base units /// and add the prefix to the expanded base units. /// </summary> /// <param name="unit"></param> /// <returns></returns> public static Unit ExpandMetricUnit(MetricUnit unit) { List <Unit> DefaultUnits = new List <Unit>(); if (unit.IsBaseUnit) { //if baseunit then why we would convert it // put it immediately return(unit); } else { QuantityDimension qdim = QuantityDimension.DimensionFrom(unit.QuantityType); if (unit is MetricUnit) { //pure unit without sub units like Pa, N, and L Unit u = DiscoverUnit(qdim); List <Unit> baseUnits = u.SubUnits; //add prefix to the first unit in the array ((MetricUnit)baseUnits[0]).UnitPrefix += ((MetricUnit)unit).UnitPrefix; DefaultUnits.AddRange(baseUnits); } return(new Unit(unit._QuantityType, DefaultUnits.ToArray())); } }
/// <summary> /// Adding quantities with different storage types /// </summary> /// <typeparam name="Q">Second Quantity Type</typeparam> /// <param name="firstQuantity"></param> /// <param name="secondQuantity"></param> /// <returns></returns> public static AnyQuantity <T> Add <Q>(AnyQuantity <T> firstQuantity, AnyQuantity <Q> secondQuantity) { if (firstQuantity.Equals(secondQuantity)) { AnyQuantity <T> AQ = null; try { AQ = QuantityDimension.QuantityFrom <T>(firstQuantity.Dimension); //exception happen when adding two derived quantities together } catch (QuantityNotFoundException) { //keep the first quantity configuration. AQ = (AnyQuantity <T>)firstQuantity.Clone(); } T firstVal = (firstQuantity.Value); Q secondVal = (secondQuantity.Value); //correct the values according to left unit or first unit. //the resulted quantity has the values of the first unit. if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //factor from second unit to first unit UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit); secondVal = MultiplyScalarByGeneric <Q>(stof.ConversionFactor, secondVal); } var expr = Expression.Add(Expression.Constant(firstVal), Expression.Constant(secondVal)); // Construct Lambda function which return one object. Expression <Func <T> > cq = Expression.Lambda <Func <T> >(expr); // compile the function Func <T> aqf = cq.Compile(); // execute the function T result = aqf(); if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //assign the unit of first quantity to the result. AQ.Unit = firstQuantity.Unit; } AQ.Value = result; return(AQ); } else { throw new QuantitiesNotDimensionallyEqualException(); } }
public DerivedQuantity(QuantityDimension dimension) { //create quantity for each sub quantity List <AnyQuantity <T> > quantities = new List <AnyQuantity <T> >(); if (dimension.Mass.Exponent != 0) { quantities.Add(new Mass <T>(dimension.Mass.Exponent)); } { if (dimension.Length.RegularExponent != 0) { quantities.Add(new Length <T>(dimension.Length.RegularExponent)); } if (dimension.Length.PolarExponent != 0) { quantities.Add(new PolarLength <T>(dimension.Length.PolarExponent)); } } if (dimension.Time.Exponent != 0) { quantities.Add(new Time <T>(dimension.Time.Exponent)); } if (dimension.Temperature.Exponent != 0) { quantities.Add(new Temperature <T>(dimension.Temperature.Exponent)); } if (dimension.LuminousIntensity.Exponent != 0) { quantities.Add(new LuminousIntensity <T>(dimension.LuminousIntensity.Exponent)); } if (dimension.AmountOfSubstance.Exponent != 0) { quantities.Add(new AmountOfSubstance <T>(dimension.AmountOfSubstance.Exponent)); } if (dimension.ElectricCurrent.Exponent != 0) { quantities.Add(new ElectricalCurrent <T>(dimension.ElectricCurrent.Exponent)); } if (dimension.Currency.Exponent != 0) { quantities.Add(new Currency <T>(dimension.Currency.Exponent)); } if (dimension.Digital.Exponent != 0) { quantities.Add(new Digital <T>(dimension.Digital.Exponent)); } InternalQuantities = quantities.ToArray(); }
// //You can use the following additional attributes as you write your tests: // //Use ClassInitialize to run code before running the first test in the class //[ClassInitialize()] //public static void MyClassInitialize(TestContext testContext) //{ //} // //Use ClassCleanup to run code after all tests in a class have run //[ClassCleanup()] //public static void MyClassCleanup() //{ //} // //Use TestInitialize to run code before running each test //[TestInitialize()] //public void MyTestInitialize() //{ //} // //Use TestCleanup to run code after each test has run //[TestCleanup()] //public void MyTestCleanup() //{ //} // #endregion /// <summary> ///A test for Mass`1 Constructor ///</summary> public void MassConstructorTestHelper <T>() { Mass <T> target = new Mass <T>(); QuantityDimension MassDimension = new QuantityDimension(1, 0, 0); Assert.AreEqual(MassDimension, target.Dimension); }
public static AnyQuantity <T> Divide(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity) { //to preserve the units we make a derivedquantity with passed quantities // then we take the derived unit in temporary store // then we try to get strongly typed Quantity // then assign the unit to the generated quantity. // this way we won't have to know the unit system of the quantity. AnyQuantity <T> sec_qty = (AnyQuantity <T>)secondQuantity.Invert(); //this is a divide process we must make 1/exponenet :) AnyQuantity <T> qresult = (AnyQuantity <T>)ConstructDerivedQuantity(firstQuantity, sec_qty); try { qresult = QuantityDimension.QuantityFrom <T>(qresult.Dimension); } catch (QuantityNotFoundException) { } if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short)) { qresult.Value = (T)(object)(((double)(object)firstQuantity.Value) * ((double)(object)sec_qty.Value)); if (firstQuantity.Unit != null && secondQuantity.Unit != null) { Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, sec_qty.Unit); qresult.Unit = un; if (un.IsOverflowed) { qresult.Value = (T)(object)(un.GetUnitOverflow() * ((double)(object)qresult.Value)); } } } else { qresult.Value = DivideGenericByGeneric(firstQuantity.Value, secondQuantity.Value); //check if any of the two quantities have a valid unit // to be able to derive the current quantity if (firstQuantity.Unit != null && secondQuantity.Unit != null) { Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, sec_qty.Unit); qresult.Unit = un; if (un.IsOverflowed) { qresult.Value = MultiplyScalarByGeneric(un.GetUnitOverflow(), qresult.Value); } } } return(qresult); }
// //You can use the following additional attributes as you write your tests: // //Use ClassInitialize to run code before running the first test in the class //[ClassInitialize()] //public static void MyClassInitialize(TestContext testContext) //{ //} // //Use ClassCleanup to run code after all tests in a class have run //[ClassCleanup()] //public static void MyClassCleanup() //{ //} // //Use TestInitialize to run code before running each test //[TestInitialize()] //public void MyTestInitialize() //{ //} // //Use TestCleanup to run code after each test has run //[TestCleanup()] //public void MyTestCleanup() //{ //} // #endregion /// <summary> ///A test for Dimension ///</summary> public void DimensionTestHelper <T>() { Length <T> target = new Length <T>(); // TODO: Initialize to an appropriate value QuantityDimension LengthDimension = new QuantityDimension(0, 1, 0); Assert.AreEqual(LengthDimension, target.Dimension); }
/// <summary> /// This constructor creates a unit from several units. /// </summary> /// <param name="units"></param> internal Unit(Type quantityType, params Unit[] units) { SubUnits = new List <Unit>(); foreach (Unit un in units) { SubUnits.Add(un); } SubUnits = GroupUnits(SubUnits); //group similar units this._Symbol = GenerateUnitSymbolFromSubBaseUnits(); // if the passed type is AnyQuantity<object> for example // then I want to get the type without type parameters AnyQuantity<> if (quantityType != null) { if (!quantityType.IsGenericTypeDefinition) { quantityType = quantityType.GetGenericTypeDefinition(); } } if (quantityType != typeof(DerivedQuantity <>) && quantityType != null) { if (quantityType != typeof(DimensionlessQuantity <>)) { this._IsDefaultUnit = true; } this._QuantityType = quantityType; //get the unit dimension from the passed type. _UnitDimension = QuantityDimension.DimensionFrom(quantityType); } else { //passed type is derivedQuantity which indicates that the units representing unknow derived quantity to the system //so that quantityType should be kept as derived quantity type. this._QuantityType = quantityType; //get the unit dimension from the passed units. this._UnitDimension = QuantityDimension.Dimensionless; foreach (Unit uu in SubUnits) { this._UnitDimension += uu.UnitDimension; } } this._IsBaseUnit = false; }
public Unit RaiseUnitPower(float power) { //make short-cut when power equal zero return dimensionless unit immediatly // because if I left the execution to the end // the dimensionless unit is created and wrapping the original unit under sub unit // and this made errors in conversion between dimensionless units :). if (power == 0) { return(Unit.DiscoverUnit(QuantityDimension.Dimensionless)); } Unit u = (Unit)this.MemberwiseClone(); if (SubUnits != null) { u.SubUnits = new List <Unit>(SubUnits.Count); for (int i = 0; i < SubUnits.Count; i++) { u.SubUnits.Add(SubUnits[i].RaiseUnitPower(power)); } } else { u.unitExponent *= power; //the exponent is changing in strongly typed units } u._UnitDimension = this._UnitDimension * power; //must change the unit dimension of the unit // however because the unit is having sub units we don't have to modify the exponent of it // note: unit that depend on sub units is completly unaware of its exponent // or I should say it is always equal = 1 u._QuantityType = QuantityDimension.GetQuantityTypeFrom(u._UnitDimension); if (u.SubUnits == null && u.unitExponent == 1) { //no sub units and exponent ==1 then no need to processing return(u); } else if (u.SubUnits == null) { //exponent != 1 like ^5 ^0.3 we need processing return(new Unit(u._QuantityType, u)); } else { //consist of sub units definitly we need processing. return(new Unit(u._QuantityType, u.SubUnits.ToArray())); } }
// //You can use the following additional attributes as you write your tests: // //Use ClassInitialize to run code before running the first test in the class //[ClassInitialize()] //public static void MyClassInitialize(TestContext testContext) //{ //} // //Use ClassCleanup to run code after all tests in a class have run //[ClassCleanup()] //public static void MyClassCleanup() //{ //} // //Use TestInitialize to run code before running each test //[TestInitialize()] //public void MyTestInitialize() //{ //} // //Use TestCleanup to run code after each test has run //[TestCleanup()] //public void MyTestCleanup() //{ //} // #endregion /// <summary> ///A test for Angle`1 Constructor ///</summary> public void AngleConstructorTestHelper <T>() { Angle <T> target = new Angle <T>(); //test the dimension of the Angle QuantityDimension AngleDimension = new QuantityDimension(); AngleDimension.Length = new QuantitySystem.DimensionDescriptors.LengthDescriptor(1, -1); Assert.AreEqual(AngleDimension, target.Dimension); }
public void QuantityDimensionConstructorTest1() { QuantityDimension target = new QuantityDimension(); Assert.AreEqual(0, target.Mass.Exponent); Assert.AreEqual(0, target.Length.Exponent); Assert.AreEqual(0, target.Time.Exponent); Assert.AreEqual(0, target.Temperature.Exponent); Assert.AreEqual(0, target.LuminousIntensity.Exponent); Assert.AreEqual(0, target.ElectricCurrent.Exponent); Assert.AreEqual(0, target.AmountOfSubstance.Exponent); }
/// <summary> /// Resturns the name of the quantity associated with this dimension /// </summary> /// <param name="dimension"></param> /// <returns></returns> public static QsValue FromDimension(QsParameter dimension) { string ss = dimension.ParameterRawText; if (dimension.QsNativeValue is QsText) { ss = ((QsText)dimension.QsNativeValue).Text; } var q = QuantityDimension.Parse(ss); string qt = QuantityDimension.GetQuantityTypeFrom(q).Name; return(new QsText(qt.Substring(0, qt.Length - 2))); }
public static AnyQuantity <T> Multiply(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity) { AnyQuantity <T> qresult = (AnyQuantity <T>)ConstructDerivedQuantity <T>(firstQuantity, secondQuantity); try { //correct quantities and units qresult = QuantityDimension.QuantityFrom <T>(qresult.Dimension); } catch (QuantityNotFoundException) { } if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short)) { qresult.Value = (T)(object)(((double)(object)firstQuantity.Value) * ((double)(object)secondQuantity.Value)); if (firstQuantity.Unit != null && secondQuantity.Unit != null) { Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, secondQuantity.Unit); qresult.Unit = un; if (un.IsOverflowed) { qresult.Value = (T)(object)(un.GetUnitOverflow() * ((double)(object)qresult.Value)); } } } else { qresult.Value = MultiplyGenericByGeneric(firstQuantity.Value, secondQuantity.Value); //check if any of the two quantities have a valid unit // to be able to derive the current quantity if (firstQuantity.Unit != null && secondQuantity.Unit != null) { Unit un = new Unit(qresult.GetType(), firstQuantity.Unit, secondQuantity.Unit); qresult.Unit = un; if (un.IsOverflowed) { qresult.Value = MultiplyScalarByGeneric(un.GetUnitOverflow(), qresult.Value); } } } return(qresult); }
/// <summary> /// Parse the input name and return the quantity object from it. /// </summary> /// <typeparam name="T">container type of the value</typeparam> /// <param name="quantityName"></param> /// <returns></returns> public static AnyQuantity <T> Parse(string quantityName) { Type QuantityType = QuantityDimension.QuantityTypeFrom(quantityName); if (QuantityType == null) { throw new QuantityNotFoundException(); } else { //QuantityType = QuantityType.MakeGenericType(typeof(T)); //AnyQuantity<T> qty = (AnyQuantity<T>)Activator.CreateInstance(QuantityType); AnyQuantity <T> qty = QuantityDimension.QuantityFrom <T>(QuantityDimension.DimensionFrom(QuantityType)); return(qty); } }
public void QuantityDimensionConstructorTest() { int mass = 1; // TODO: Initialize to an appropriate value int length = 2; // TODO: Initialize to an appropriate value int time = 3; // TODO: Initialize to an appropriate value QuantityDimension target = new QuantityDimension(mass, length, time); Assert.AreEqual(1, target.Mass.Exponent); Assert.AreEqual(2, target.Length.Exponent); Assert.AreEqual(3, target.Time.Exponent); Assert.AreEqual(0, target.Temperature.Exponent); Assert.AreEqual(0, target.LuminousIntensity.Exponent); Assert.AreEqual(0, target.ElectricCurrent.Exponent); Assert.AreEqual(0, target.AmountOfSubstance.Exponent); }
/// <summary> /// Returns a value from the dimension of this quantity. /// </summary> /// <param name="dimension"></param> /// <param name="value"></param> /// <returns></returns> public static QsValue FromDimension(QsParameter dimension, QsParameter value) { string ss = dimension.ParameterRawText; if (dimension.QsNativeValue is QsText) { ss = ((QsText)dimension.QsNativeValue).Text; } var q = QuantityDimension.Parse(ss); var unit = QuantitySystem.Units.Unit.DiscoverUnit(q); var qval = unit.GetThisUnitQuantity <double>(double.Parse(value.ParameterRawText, CultureInfo.InvariantCulture)); var qs = new QsScalar(ScalarTypes.NumericalQuantity) { NumericalQuantity = qval }; return(qs); }
public void PathToUnitTest() { double expected = 63360; Mile mil = new Mile(); Inch i = new Inch(); UnitPathStack actual = mil.PathToUnit(i); Assert.AreEqual(expected, actual.ConversionFactor); Gram g = new Gram(); g.UnitPrefix = MetricPrefix.None; Gram Mg = new Gram(); Mg.UnitPrefix = MetricPrefix.Mega; actual = g.PathToUnit(Mg); Assert.AreEqual(1e-6, actual.ConversionFactor); Metre mr = new Metre(); actual = i.PathToUnit(mr); Assert.AreEqual(0.0254, actual.ConversionFactor); //now the idea is to make any combination of units to go to any combination of units QuantityDimension qd = QuantityDimension.ParseMLT("M1L0T-1"); Unit u = Unit.DiscoverUnit(qd); Assert.AreEqual("<kg/s>", u.Symbol); Assert.AreEqual(qd, u.UnitDimension); }
public static MetricUnit UnitOf <TQuantity>() where TQuantity : BaseQuantity, new() { //try direct mapping MetricUnit unit = Activator.CreateInstance(Unit.GetDefaultSIUnitTypeOf(typeof(TQuantity))) as MetricUnit; if (unit != null) { return(unit); } else { //if failed you should generate it //try first the child quantities in the quantity instance if its base is dervied quantity // and DerivedQuantity itself. QuantityDimension dimension = QuantityDimension.DimensionFrom(typeof(TQuantity)); //return a derived unit. //return new DerivedSIUnit(dimension); throw new NotImplementedException(); } }
/// <summary> /// Returns the unit corresponding to the passed string. /// Suppors units with exponent. /// </summary> /// <param name="unit"></param> /// <returns></returns> internal static Unit ParseUnit(string un) { if (un == "1") { //this is dimensionless value return(new Unit(typeof(Quantities.DimensionlessQuantities.DimensionlessQuantity <>))); } //find '^' string[] upower = un.Split('^'); string unit = upower[0]; int power = 1; if (upower.Length > 1) { power = int.Parse(upower[1], CultureInfo.InvariantCulture); } Unit FinalUnit = null; //Phase 1: try direct mapping. try { FinalUnit = FindUnit(unit); } catch (UnitNotFoundException) { //try to find if it as a Metric unit with prefix //loop through all prefixes. for (int i = 10; i >= -10; i -= 1) { if (i == 0) { i--; //skip the None prefix } if (unit.StartsWith(MetricPrefix.GetPrefix(i).Symbol, StringComparison.Ordinal)) { //found MetricPrefix mp = MetricPrefix.GetPrefix(i); string upart = unit.Substring(mp.Symbol.Length); //then it should be MetricUnit otherwise die :) MetricUnit u = FindUnit(upart) as MetricUnit; if (u == null) { goto nounit; } u.UnitPrefix = mp; FinalUnit = u; break; } } } if (FinalUnit == null) { goto nounit; } if (power > 1) { //discover the new type QuantityDimension ud = FinalUnit.UnitDimension * power; Unit[] chobits = new Unit[power]; //what is chobits any way :O for (int iy = 0; iy < power; iy++) { chobits[iy] = (Unit)FinalUnit.MemberwiseClone(); } Type uQType = null; uQType = QuantityDimension.GetQuantityTypeFrom(ud); FinalUnit = new Unit(uQType, chobits); } return(FinalUnit); nounit: throw new UnitNotFoundException(un); }
public static AnyQuantity <T> Subtract(AnyQuantity <T> firstQuantity, AnyQuantity <T> secondQuantity) { if (firstQuantity.Equals(secondQuantity)) { AnyQuantity <T> AQ = null; try { AQ = QuantityDimension.QuantityFrom <T>(firstQuantity.Dimension); //exception happen when adding two derived quantities together } catch (QuantityNotFoundException) { //keep the first quantity configuration. AQ = (AnyQuantity <T>)firstQuantity.Clone(); } if (typeof(T) == typeof(decimal) || typeof(T) == typeof(double) || typeof(T) == typeof(float) || typeof(T) == typeof(int) || typeof(T) == typeof(short)) { //use direct calculations double firstVal = (double)(object)firstQuantity.Value; double secondVal = (double)(object)secondQuantity.Value; //correct the values according to left unit or first unit. //the resulted quantity has the values of the first unit. if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //factor from second unit to first unit UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit); secondVal = stof.ConversionFactor * secondVal; } ////sum the values double result = firstVal - secondVal; if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //assign the unit of first quantity to the result. AQ.Unit = (Unit)firstQuantity.Unit.Clone(); } AQ.Value = (T)(object)result; return(AQ); } else { T firstVal = (firstQuantity.Value); T secondVal = (secondQuantity.Value); //correct the values according to left unit or first unit. //the resulted quantity has the values of the first unit. if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //factor from second unit to first unit UnitPathStack stof = secondQuantity.Unit.PathToUnit(firstQuantity.Unit); secondVal = MultiplyScalarByGeneric(stof.ConversionFactor, secondVal); } var expr = Expression.Subtract(Expression.Constant(firstVal), Expression.Constant(secondVal)); // Construct Lambda function which return one object. Expression <Func <T> > cq = Expression.Lambda <Func <T> >(expr); // compile the function Func <T> aqf = cq.Compile(); // execute the function T result = aqf(); if (firstQuantity.Unit != null && secondQuantity.Unit != null) { //assign the unit of first quantity to the result. AQ.Unit = firstQuantity.Unit; } AQ.Value = result; return(AQ); } } else { throw new QuantitiesNotDimensionallyEqualException(); } }
/// <summary> /// Construct a unit based on the quantity type in SI Base units. /// Any Dimensionless quantity will return in its unit. /// </summary> /// <param name="quantityType"></param> public Unit(Type quantityType) { SubUnits = new List <Unit>(); //try direct mapping first to get the unit Type InnerUnitType = Unit.GetDefaultSIUnitTypeOf(quantityType); if (InnerUnitType == null) { QuantityDimension dimension = QuantityDimension.DimensionFrom(quantityType); if (dimension.Mass.Exponent != 0) { Unit u = new Metric.SI.Gram(); u.UnitExponent = dimension.Mass.Exponent; u.UnitDimension = u.UnitDimension * dimension.Mass.Exponent; SubUnits.Add(u); } if (dimension.Length.Exponent != 0) { Unit u = new Metric.SI.Metre(); u.UnitExponent = dimension.Length.Exponent; u.UnitDimension = u.UnitDimension * dimension.Length.Exponent; SubUnits.Add(u); } if (dimension.Time.Exponent != 0) { Unit u = new Shared.Second(); u.UnitExponent = dimension.Time.Exponent; u.UnitDimension = u.UnitDimension * dimension.Time.Exponent; SubUnits.Add(u); } if (dimension.Temperature.Exponent != 0) { Unit u = new Metric.SI.Kelvin(); u.UnitExponent = dimension.Temperature.Exponent; u.UnitDimension = u.UnitDimension * dimension.Temperature.Exponent; SubUnits.Add(u); } if (dimension.LuminousIntensity.Exponent != 0) { Unit u = new Metric.SI.Candela(); u.UnitExponent = dimension.LuminousIntensity.Exponent; u.UnitDimension = u.UnitDimension * dimension.LuminousIntensity.Exponent; SubUnits.Add(u); } if (dimension.AmountOfSubstance.Exponent != 0) { Unit u = new Metric.SI.Mole(); u.UnitExponent = dimension.AmountOfSubstance.Exponent; u.UnitDimension = u.UnitDimension * dimension.AmountOfSubstance.Exponent; SubUnits.Add(u); } if (dimension.ElectricCurrent.Exponent != 0) { Unit u = new Metric.SI.Ampere(); u.UnitExponent = dimension.ElectricCurrent.Exponent; u.UnitDimension = u.UnitDimension * dimension.ElectricCurrent.Exponent; SubUnits.Add(u); } if (dimension.Currency.Exponent != 0) { Unit u = new Currency.Coin(); u.UnitExponent = dimension.Currency.Exponent; u.UnitDimension = u.UnitDimension * dimension.Currency.Exponent; SubUnits.Add(u); } if (dimension.Digital.Exponent != 0) { Unit u = new Digital.Bit(); u.UnitExponent = dimension.Digital.Exponent; u.UnitDimension = u.UnitDimension * dimension.Digital.Exponent; SubUnits.Add(u); } } else { //subclass of AnyQuantity //use direct mapping with the exponent of the quantity Unit un = (Unit)Activator.CreateInstance(InnerUnitType); SubUnits.Add(un); } this._Symbol = GenerateUnitSymbolFromSubBaseUnits(); this._IsDefaultUnit = true; //the quantity may be derived quantity which shouldn't be referenced :check here. this._QuantityType = quantityType; _UnitDimension = QuantityDimension.DimensionFrom(this._QuantityType); this._IsBaseUnit = false; }
} //the list shouldn't been modified by sub classes /// <summary> /// Create the unit directly from the specfied dimension in its SI base units. /// </summary> /// <param name="dimension"></param> public static Unit DiscoverUnit(QuantityDimension dimension) { return(DiscoverUnit(dimension, "Metric.SI")); }
/// <summary> /// Create the unit directly from the specfied dimension based on the unit system given. /// </summary> /// <param name="dimension"></param> public static Unit DiscoverUnit(QuantityDimension dimension, string unitSystem) { List <Unit> SubUnits = new List <Unit>(); if (dimension.Currency.Exponent != 0) { Unit u = new Currency.Coin(); u.UnitExponent = dimension.Currency.Exponent; u.UnitDimension = new QuantityDimension { Currency = new DimensionDescriptors.CurrencyDescriptor(dimension.Currency.Exponent) }; SubUnits.Add(u); } if (dimension.Mass.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Mass <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.Mass.Exponent; u.UnitDimension = new QuantityDimension(dimension.Mass.Exponent, 0, 0); SubUnits.Add(u); } if (dimension.Length.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Length <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.Length.Exponent; u.UnitDimension = new QuantityDimension() { Length = dimension.Length }; SubUnits.Add(u); } if (dimension.Time.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Time <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.Time.Exponent; u.UnitDimension = new QuantityDimension() { Time = dimension.Time }; SubUnits.Add(u); } if (dimension.Temperature.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(Temperature <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.Temperature.Exponent; u.UnitDimension = new QuantityDimension() { Temperature = dimension.Temperature }; SubUnits.Add(u); } if (dimension.LuminousIntensity.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(LuminousIntensity <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.LuminousIntensity.Exponent; u.UnitDimension = new QuantityDimension() { LuminousIntensity = dimension.LuminousIntensity }; SubUnits.Add(u); } if (dimension.AmountOfSubstance.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(AmountOfSubstance <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.AmountOfSubstance.Exponent; u.UnitDimension = new QuantityDimension(0, 0, 0, 0, 0, dimension.AmountOfSubstance.Exponent, 0); SubUnits.Add(u); } if (dimension.ElectricCurrent.Exponent != 0) { Type UnitType = Unit.GetDefaultUnitTypeOf(typeof(ElectricalCurrent <>), unitSystem); Unit u = (Unit)Activator.CreateInstance(UnitType); u.UnitExponent = dimension.ElectricCurrent.Exponent; u.UnitDimension = new QuantityDimension() { ElectricCurrent = dimension.ElectricCurrent }; SubUnits.Add(u); } if (dimension.Currency.Exponent != 0) { Unit u = new Currency.Coin(); u.UnitExponent = dimension.Currency.Exponent; u.UnitDimension = u.UnitDimension * dimension.Currency.Exponent; SubUnits.Add(u); } if (dimension.Digital.Exponent != 0) { Unit u = new Digital.Bit(); u.UnitExponent = dimension.Digital.Exponent; u.UnitDimension = u.UnitDimension * dimension.Digital.Exponent; SubUnits.Add(u); } Unit un = null; try { Type qType = QuantityDimension.QuantityTypeFrom(dimension); un = new Unit(qType, SubUnits.ToArray()); } catch (QuantityNotFoundException) { un = new Unit(null, SubUnits.ToArray()); } return(un); }
/// <summary> /// Parse units with exponent and one division '/' with many '.' /// i.e. m/s m/s^2 kg.m/s^2 /// </summary> /// <param name="units"></param> /// <returns></returns> public static Unit Parse(string units) { // if found treat store its value. // m/s^2 m.K/m.s // kg^2/in^2.s // sea //search for '/' string[] uny = units.Split('/'); string[] numa = uny[0].Split('.'); List <Unit> dunits = new List <Unit>(); foreach (string num in numa) { dunits.Add(ParseUnit(num)); } if (uny.Length > 1) { string[] dena = uny[1].Split('.'); foreach (string den in dena) { var uu = ParseUnit(den); if (uu.SubUnits != null) { //then it is unit with sub units in it if (uu.SubUnits.Count == 1) { uu = uu.SubUnits[0]; } } dunits.Add(uu.Invert()); } } if (dunits.Count == 1) { return(dunits[0]); } //get the dimension of all units QuantityDimension ud = QuantityDimension.Dimensionless; foreach (Unit un in dunits) { ud += un.UnitDimension; } Type uQType = null; uQType = QuantityDimension.GetQuantityTypeFrom(ud); Unit FinalUnit = new Unit(uQType, dunits.ToArray()); return(FinalUnit); }
/// <summary> /// Fill the instance of the unit with the attributes /// found on it. /// </summary> protected Unit() { //only called on the strongly typed units _IsStronglyTyped = true; UnitValues uv; if (CachedUnitsValues.TryGetValue(this.GetType(), out uv)) { _Symbol = uv._Symbol; _QuantityType = uv._QuantityType; _UnitDimension = uv._UnitDimension; _IsDefaultUnit = uv._IsDefaultUnit; _IsBaseUnit = uv._IsBaseUnit; _ReferenceUnit = uv._ReferenceUnit; _ReferenceUnitNumerator = uv._ReferenceUnitNumerator; _ReferenceUnitDenominator = uv._ReferenceUnitDenominator; } else { //read the current attributes MemberInfo info = this.GetType(); object[] attributes = (object[])info.GetCustomAttributes(true); //get the UnitAttribute UnitAttribute ua = (UnitAttribute)attributes.SingleOrDefault <object>(ut => ut is UnitAttribute); if (ua != null) { _Symbol = ua.Symbol; _QuantityType = ua.QuantityType; _UnitDimension = QuantityDimension.DimensionFrom(_QuantityType); if (ua is DefaultUnitAttribute) { _IsDefaultUnit = true; //indicates that this unit is the default when creating the quantity in this system //also default unit is the unit that relate its self to the SI Unit. } else { _IsDefaultUnit = false; } } else { throw new UnitException("Unit Attribute not found"); } if (_QuantityType.Namespace == "QuantitySystem.Quantities.BaseQuantities") { _IsBaseUnit = true; } else { _IsBaseUnit = false; } //Get the reference attribute ReferenceUnitAttribute dua = (ReferenceUnitAttribute)attributes.SingleOrDefault <object>(ut => ut is ReferenceUnitAttribute); if (dua != null) { if (dua.UnitType != null) { _ReferenceUnit = (Unit)Activator.CreateInstance(dua.UnitType); } else { //get the SI Unit Type for this quantity //first search for direct mapping Type SIUnitType = GetDefaultSIUnitTypeOf(_QuantityType); if (SIUnitType != null) { _ReferenceUnit = (Unit)Activator.CreateInstance(SIUnitType); } else { //try dynamic creation of the unit. _ReferenceUnit = new Unit(_QuantityType); } } _ReferenceUnitNumerator = dua.Numerator; _ReferenceUnitDenominator = dua.Denominator; } uv._Symbol = _Symbol; uv._QuantityType = _QuantityType; uv._UnitDimension = _UnitDimension; uv._IsDefaultUnit = _IsDefaultUnit; uv._IsBaseUnit = _IsBaseUnit; uv._ReferenceUnit = _ReferenceUnit; uv._ReferenceUnitNumerator = _ReferenceUnitNumerator; uv._ReferenceUnitDenominator = _ReferenceUnitDenominator; CachedUnitsValues.Add(this.GetType(), uv); } }