Area and Volume Units ?

Feb 3, 2014 at 6:37 AM
Hi,

I created classes for Unit Types like Length, Mass, Temperature and some other more complex units. In advance , I defined necessary units to use in the code more easily( including prefixes). Also i defined new unit system called IU (Imperial Units).Example:
public class LengthUnit
    {
public static IPhysicalUnit SI_METER = (IPhysicalUnit)PhysicalMeasure.Physics.SI_Units.BaseUnits[(int)(MeasureKind.Length)];

public static IPhysicalUnit SI_MEGAMETER = (IPhysicalUnit)(new PhysicalMeasure.CombinedUnit(new PrefixedUnitExponent(6, SI_METER, 1)));

public static IPhysicalUnit SI_KILOMETER = (IPhysicalUnit)(new PhysicalMeasure.CombinedUnit(new PrefixedUnitExponent(3, SI_METER, 1)));

 public static IPhysicalUnit SI_ANGSTROM = (IPhysicalUnit)(new ConvertibleUnit("angstrom", "angstrom", PhysicalMeasure.Physics.SI_Units.BaseUnits[(int)(MeasureKind.Length)], new ScaledValueConversion(1.0 / 10000000000.0)));

 public static IPhysicalUnit IU_FEET = (IPhysicalUnit)
PhysicalMeasure.Physics.IU_Units.BaseUnits[(int)(MeasureKind.Length)]; /* [ft] = 1.0 / 0.3048 * [m]  */

 public static IPhysicalUnit IU_YARD = (IPhysicalUnit)(new PhysicalMeasure.ConvertibleUnit("yard", "yd", IU_FEET, new ScaledValueConversion(1.0 / 3.0))); /* [yd] = 1.0 / 3.0 * [ft] */}
My question is with the same logic i want to create Area and Volume Classeses and predefine all necessary units.
    public class AreaUnit
    {
        public static IPhysicalUnit SI_SQUAREMETER = LengthUnit.SI_METER.Pow(2).Unit;
}
Meter Square is ok. But what about the other prefixed units kilometersquare, hectometersquare etc. And also as i define Imperial Units yards square, inch square? How can i handle that situation?

Thank you in advance,
Coordinator
Feb 8, 2014 at 1:39 PM
Hello cemsacma.
First I am sorry for the late reply. I have been off-mail for the last week.
I am not sure that I understand your question. The LengthUnit class you have made seams OK to me, and can be used if that is need. But the Area class seams to make the complicated, and going for a volume class would be made the code long. And if you also have to use combination as speed or current densities or what ever, the list would be nearly infinite.
I would have made new part to the partial class Physics with all the base units, named derivated units and unit system and conversion to/from SI. All for the Imperial Units system. I have made some non-SI unit systems in the Physics class already, for example CGS. I think you should do something like:
static partial class Physics {

        public static readonly BaseUnit[] IU_BaseUnits = new BaseUnit[] {  new BaseUnit(null, (SByte)MeasureKind.Length,   "feet", "ft"),  // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.Mass, "NOT kilogram", "NOT Kg"), /* NOT kg */  // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.Time, "second", "s"),  // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.ElectricCurrent, "ampere", "A"),   // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.ThermodynamicTemperature, "kelvin", "K"),  // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.AmountOfSubstance, "mol", "mol"),  // or what is the right base unit for IU
                                                                    new BaseUnit(null, (SByte)MeasureKind.LuminousIntensity, "candela", "cd") }; // or what is the right base unit for IU
      ....
        public static readonly UnitSystem IU_Units = new UnitSystem("IU", UnitPrefixes /*  I don't know how this works for IU. Maybe just null */,
                                                                  IU_BaseUnits,   ....  );

      ....
      public static readonly UnitSystemConversion SI_to_IU_Conversion = new UnitSystemConversion(SI_Units, IU_Units,   ....     );

} // End of partial class Physics 
Then you can make a conversion from the UI system to the SI system:

You would also need to somehow replace/overload the UnitSystemConversions array or the GetUnitSystemConversion function. I can maybe make that a more extensible/dynamical in my code. To make it work with the already released code for PhysicalMeasure, you could place the IU objects directly in the Physics class in the PhysicalMeasure.cs file.

I hope this can help you to solve you problem, else you are welcome ask me again.

/KiloBravo
Feb 10, 2014 at 7:43 AM
Hi KiloBravo,

First of all thanks for your reply.

With the same logic as you have done above i have already coded necessary changes like below:
    public static partial class Physics
    {
        public static readonly BaseUnit[] IU_BaseUnits = new BaseUnit[] {  new BaseUnit(null, (SByte)MeasureKind.Length, "feet", "ft"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.Mass, "pound", "lb"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.Time, "second", "s"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.ElectricCurrent, "ampere", "A"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.ThermodynamicTemperature, "fahrenheit ", "°F"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.AmountOfSubstance, "mol", "mol"), 
                                                                    new BaseUnit(null, (SByte)MeasureKind.LuminousIntensity, "candela", "cd") };

        public static readonly UnitSystem IU_Units = new UnitSystem("IU", null, IU_BaseUnits, null, null); //I did not code NamedDerived and Convertible units here. Instead i put them other newly created classes like LenghtUnit, MassUnit, Temperature Unit etc. Maybe it is better to put them here

        public static UnitSystem[] UnitSystems = new UnitSystem[] { SI_Units, CGS_Units, MGD_Units, MGM_Units, IU_Units };

        public static readonly UnitSystemConversion SItoIUConversion = new UnitSystemConversion(SI_Units, IU_Units, new ValueConversion[] { new ScaledValueConversion(1.0/0.3048),  /* 1.0/0.3048 m       <SI> = 1 ft        <IU>  */
                                                                                                                                     new ScaledValueConversion(0.45359237),               /* 0.45359237 Kg      <SI> = 1 lbs        <IU>  */
                                                                                                                                     new IdentityValueConversion(),                 /* 1 s       <SI> = 1 s           <IU>  */
                                                                                                                                     new IdentityValueConversion(),                 /* 1 A       <SI> = 1 A           <IU>  */
                                                                                                                                     new LinearValueConversion(-459.67,9.0/5.0),    /* 1 K       <SI> = (1 F +459.67)  * 5.0/9.0        <IU>  */
                                                                                                                                     new IdentityValueConversion(),                 /* 1 mol     <SI> = 1 mol         <IU>  */
                                                                                                                                     new IdentityValueConversion(),                 /* 1 candela <SI> = 1 candela     <IU>  */
                                                                                                                                    });

        public static IList<UnitSystemConversion> UnitSystemConversions = new List<UnitSystemConversion> { SItoCGSConversion, SItoMGDConversion, MGDtoMGMConversion, SItoIUConversion };
}
Why i prefer to create new classes like LengthUnit, MassUnit, EnergyUnit, ThermalConductivityUnit etc is bcuz while coding it would be easy to code with intellicense. Also i created an attribute to set unit's unitFamily. So i will be able to know if a unit is SI, IU or both.
    public class UnitFamilyAttribute : Attribute
    {
        public string UnitFamily { get; set; }

        public UnitFamilyAttribute(string unitFamily)
        {
            this.UnitFamily = unitFamily;
        }
    }

    public class UnitFamilyConstants
    {
        public const string SI = "SI"; //International System of Units
        public const string IU = "IU"; //Imperial Units (British Imperial Unit System)
        public const string SIIU = "SIIU"; //Both SI and Imperial Unit
    }
Here is how i code in newly created LengthUnit class
    public class LengthUnit
    {
        //Feet
        [UnitFamily(UnitFamilyConstants.IU)]
        public static IPhysicalUnit IU_FEET = (IPhysicalUnit)PhysicalMeasure.Physics.IU_Units.BaseUnits[(int)(MeasureKind.Length)]; /* [ft] = 1.0 / 0.3048 * [m]  */
        //Yard
        [UnitFamily(UnitFamilyConstants.IU)]
        public static IPhysicalUnit IU_YARD = (IPhysicalUnit)(new PhysicalMeasure.ConvertibleUnit("yard", "yd", IU_FEET, new ScaledValueConversion(1.0 / 3.0))); /* [yd] = 1.0 / 3.0 * [ft] */
}
From up to now i have no problem but when it comes to create AreaUnits i don't know how to do. Below you can see my AreaUnit class:
    public class AreaUnit
    {
        //Meter^2 - Base Area Unit
        [UnitFamily(UnitFamilyConstants.SI)]
        public static IPhysicalUnit SI_SQUAREMETER = LengthUnit.SI_METER.Pow(2).Unit;
}
But i want other area units to define in this class like kilometersquare, decimetersquare, hectares , inchsquare, yardsquare. But how? How can i define an IPhysicalUnit type areaunit for SquareKilometer?

I hope i made myself clear :)

Thanks for your patience and help
Coordinator
Feb 12, 2014 at 9:19 PM
HI cemsacma.

I think I understand your problem now. It is that, when an unit is squared with .Pow(2) the result is a PhysicalQuantity not an PhysicalUnit. Your method works for baseunits because the PhysicalQuantity's factor is 1, so your can throw it away by using .Unit. One solution could be to define a UnitSystem for each of your lenght units. This would give you a baseUnit for each length unit, which could be squared the same way you have done for SI.Meter. But is is surely not a very nice way to do it.

The best way is properly to use PhysicalMeasure.CombinedUnit, which has different constructors to create derived units, and which can be casted to an IPhysicalUnit.
May be something like this:
 public static IPhysicalUnit IU_SQUAREYARD = LenghtUnit.IU_Yard.CombinePow(2);
I am looking forward to hear if it can help you.
If it is ok with you I would like to include your code for IU system and convertions into the library. If you make any derivated or converterable unit for IU, I would inclule them also.