/// <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())); } }
public static AnyQuantity <double> GetUnitizedQuantityOf <TQuantity>(double value) where TQuantity : BaseQuantity, new() { MetricUnit unit = UnitOf <TQuantity>(); AnyQuantity <double> aq = unit.GetThisUnitQuantity <double>(); aq.Value = value; return(aq); }
private static AnyQuantity <double> MakeQuantity(MetricUnit unit, MetricPrefix siPrefix, double value) { //assign its prefix unit.UnitPrefix = siPrefix; //create the corresponding quantity AnyQuantity <double> qty = unit.GetThisUnitQuantity <double>(); //assign the unit to the created quantity qty.Unit = unit; //assign the value to the quantity qty.Value = value; return(qty); }
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> /// Group all similar units so it remove units that reached exponent zero /// also keep track of prefixes of metric units. /// </summary> /// <param name="bulk_units"></param> /// <returns></returns> private List <Unit> GroupUnits(List <Unit> bulk_units) { List <Unit> units = FlattenUnits(bulk_units); if (units.Count == 1) { return(units); } List <Unit> GroupedUnits = new List <Unit>(); Dictionary <Type, Unit> us = new Dictionary <Type, Unit>(); foreach (Unit un in units) { if (us.ContainsKey(un.GetType())) { //check for prefixes before accumulating units // otherwise I'll lose the UnitExponent value. if (un is MetricUnit) { //check prefixes to consider milli+Mega for example for overflow MetricPrefix accumPrefix = ((MetricUnit)us[un.GetType()]).UnitPrefix; MetricPrefix sourcePrefix = ((MetricUnit)un).UnitPrefix; try { //Word about MetricPrefix // The prefix takes the unit exponent as another exponent to it // so if we are talking about cm^2 actually it is c^2*m^2 // suppose we multiply cm*cm this will give cm^2 // so no need to alter the prefix value // however remain a problem of different prefixes // for example km * cm = ?m^2 // k*c = ?^2 // so ? = (k+c)/2 ;) // if there is a fraction remove the prefixes totally and substitute them // in the overflow flag. // about division // km / cm = ?<1> // k/c = ? or in exponent k-c=? double targetExponent = us[un.GetType()].unitExponent + un.unitExponent; double accumExponent = accumPrefix.Exponent * us[un.GetType()].unitExponent; double sourceExponent = sourcePrefix.Exponent * un.unitExponent; double resultExponent = (accumExponent + sourceExponent); if (!(us[un.GetType()].IsInverted ^ un.IsInverted)) { //multiplication if (resultExponent % targetExponent == 0) { //we can get the symbol of the sqrt of this double unknown = resultExponent / targetExponent; ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.FromExponent(unknown); } else { //we can't get the approriate symbol because we have a fraction // like kilo * centi = 3-2=1 1/2=0.5 or 1%2=1 // so we will take the whole fraction and make an overflow ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.None; if (resultExponent != 0) { unitOverflow += Math.Pow(10, resultExponent); _IsOverflowed = true; } } } else { //division //resultExponent = (accumExponent - sourceExponent); ((MetricUnit)us[un.GetType()]).UnitPrefix = MetricPrefix.None; if (resultExponent != 0) //don't overflow in case of zero exponent target because there is not prefix in this case { unitOverflow += Math.Pow(10, resultExponent); _IsOverflowed = true; } } } catch (MetricPrefixException mpe) { ((MetricUnit)us[un.GetType()]).UnitPrefix = mpe.CorrectPrefix; unitOverflow += Math.Pow(10, mpe.OverflowExponent); _IsOverflowed = true; } } us[un.GetType()].UnitExponent += un.UnitExponent; us[un.GetType()].UnitDimension += un.UnitDimension; } else { us[un.GetType()] = (Unit)un.MemberwiseClone(); } } foreach (Unit un in us.Values) { if (un.UnitExponent != 0) { GroupedUnits.Add(un); } else { //zero means units should be skipped // however we are testing for prefix if the unit is metric // if the unit is metric and deprecated the prefix should be taken into consideration if (un is MetricUnit) { MetricUnit mu = (MetricUnit)un; if (mu.UnitPrefix.Exponent != 0) { _IsOverflowed = true; unitOverflow += Math.Pow(10, mu.UnitPrefix.Exponent); } } } } return(GroupedUnits); }
/// <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); }