/// <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()));
            }
        }
Example #2
0
        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);
        }
Example #3
0
        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);
        }
Example #4
0
        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();
            }
        }
Example #5
0
        /// <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);
        }