Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Thunder Measurement Unit Conversion Framework

0.00/5 (No votes)
23 Dec 2005 1  
An article on a unit conversion library written in C#/.NET.

Introduction

The Thunder library provides extensible measurement unit conversion functionality, allowing a program that may need to work with multiple units and perform unit conversion to do so with ease. This article introduces Thunder, describes the functionality and how to use the library, and provides a sample program that uses the library to perform a variety of unit conversions. Also provided is a configuration file containing lots of pre-made common units.

Theory of Unit Conversion in Thunder

Any unit can be converted into another as long as they measure the same thing. From simple conversions (like millimeters to meters) to more complex ones (such as Kelvin to Fahrenheit), every conversion consists of basic mathematical formulae which usually involve some simple multiplication, addition, or division.

Thunder works on the principle that every unit belongs to a category (i.e. Temperature, Mass, Energy etc.) and every category has a standard unit (e.g. Kelvin for temperature). The standard unit gives Thunder a point of reference for the unit category. Every other unit listed in the unit configuration file contains the mathematical data to convert it into the standard. All the Thunder library does is simply convert the original unit into the standard, then convert the standard value into the output unit.

The unit definitions are represented as XML in the Thunder configuration file. Below is a sample of the provided units file:

<Unit name="Kelvin">
    <Symbol default="true">K</Symbol>
    <Multiply>1</Multiply>
</Unit>

<Unit name="Celcius">
    <Symbol default="true">C</Symbol>
    <Add>273.15</Add>
</Unit>

Each unit resides within a "Unit" tag, the full name of the unit is in the property of the tag, and the data for the unit is inside the tag. Each unit can have multiple symbols associated with it (a symbol meaning a shorthand affix for the unit, such as "cm" for centimeters) and one of the symbols can be promoted to the default.

See the provided "units.xml" for full comments and examples.

Using the Code

There is just one main class that is needed to provide the conversion, and this is available via the IUnitConverter interface. This provides a single point of entry into all of the conversion functionality, and contains some methods:

  • LoadUnitsFile - Given a path to a unit configuration file, will load the units within the file into the converter.
  • InitTables - Unloads all the loaded units and returns the converter to a blank state.
  • GetUnitByName - Gets an object representing a unit by giving the name of the unit (e.g. "Kelvin").
  • GetUnitBySymbol - Same as GetUnitByName, only takes a unit symbol as a reference (e.g. "mm" or "km" etc.).
  • CompatibleUnits - Returns a boolean to determine if two units are compatible. For example, "mm" and "km" are compatible, however "mm" and "kg" are not.
  • ConvertUnits - The heart of the functionality, takes the current value, current unit, and the target unit. Returns an error code and outputs the converted value in an out parameter.
  • ParseUnitString - Given a string of value and unit, separates out the value and unit (example input: "5 kg").
  • CreateDataString - Creates a "data string" (more on data strings later).
public static void main( )
{
    IUnitConverter uc = Thor.Units.InterfaceFactory.CreateUnitConverter( );
    uc.LoadUnitsFile(@".\units.xml");
    
    double result;
    
    uc.ConvertUnits(5.0, "kg", "g", out result);
    
    //"result" now holds 5kg as grams


    ...
    
    return 0;
}

The code above shows instantiating the unit converter, and converting 5 kilograms to grams. However, programs will tend to work with textboxes or strings containing unit/value combinations such as "5 kg". Handling this is shown in the code below:

public static void main( )
{
    IUnitConverter uc = 
      Thor.Units.InterfaceFactory.CreateUnitConverter( );
    uc.LoadUnitsFile(@".\units.xml");
    
    //5 Kilogram input (space between value and units optional)

    string initial = "5 kg";
    //Convert to grams in this example

    string target_unit = "g";
    
    //Some placeholder variables

    string initial_units = "":
    double initial_val = 0.0;
    double result = 0.0;
    
    //Break up the input string

    uc.ParseUnitString(initial, out initial_val, out initial_units);

    //Perform conversion

    uc.ConvertUnits(initial_val, initial_units, 
                      target_unit, out result);
    
    //Print out the result.

    Console.WriteLine("{0} = {1}{2}", initial, result, target_unit);
    return 0;
}

You can also look at the demo project, "Thor.TestApp", which allows a user to input any initial value and target unit, and see the conversion in real time.

The DataString class

The DataString class is an object that represents a value and a unit. It can be used as part of the backend of a user interface to provide validation services or access to the conversion system in a different way.

Take the following code:

...
uc = Thor.Units.InterfaceFactory.CreateUnitConverter( );
uc.OnError += new UnitEventHandler(uc_OnError);
uc.LoadUnitsFile(@".\units.xml");

DataString d1 = uc.CreateDataString("kg");
DataString d2 = uc.CreateDataString("kg");

//Give the data strings some value

d1.SetValue("2 kg");
d2.SetValue("500 g");    //0.5kg


DataString d3 = d1 + d2;

Console.WriteLine(d3.ToString( ));
//Should be 2.5kg in this example.

...

This shows the unit converter being instantiated, then two data strings created with an initial unit - this is important as it sets the unit group that the data strings belong to (in this case, weight). The value of the two data strings is then set (notice, the string given is a complete value/unit pair - this changes the unit of the data string). The data strings are then added together, notice that they are being added but are actually in different units ("kg" vs. "g"), the converter automatically handles this and the output is "2.5kg". This would work great for programs that need to manipulate unitized data but want to allow a user to enter the data in units they are familiar with. The hard coded values in this example could easily be the contents of a textbox or something.

Points of Interest

You can add values in any units you like! Editing the XML file is easy and feel free to post if you get stuck.

Study the code - notice that the data string also supports max/min bounds and unit locking (so it always gives text output as one kind of unit). See the DataStringFlags enum for more information.

In the \Bin directory of the source ZIP is the example units.xml configuration file and the precompiled binaries.

History

  • v1.00 - Initial version.

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here