11,633,454 members (79,753 online)

Thunder Measurement Unit Conversion Framework

, 23 Dec 2005 46.9K 704 30
 Rate this:
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>
</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( );

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( );

//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);

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.

A list of licenses authors might use can be found here

Share

 Web Developer United Kingdom
Born in England, I have been programming since a very early age when my dad gave me prewritten programs to type in and run on a Sinclair ZX81 machine (seeing my name printed out on a TV screen was enough to keep me entertained!). I later did work using basic and STOS basic on the Atari ST and after that got my first PC and used Microsoft's QBasic. Later when I was about 13 I was in an airport and saw a trial copy of Visual Basic on a magazine, which I bought and it got me hooked on the Microsoft development tools.

Currently I am studying a software engineering degree and have been working with .NET since 1.0. I have just moved over to Visual Studio 2005/.NET 2.0 and am loving it! During my degree I have worked for a year at DuPont, where I ended up changing a lot of their old existing software over to .NET and improving it in the process! Since then I have been back and done some consulting work involving maintaining some of their older C++/MFC software.

While most of my current interestes involve .NET I am also confident in working with C++ in Win32, VB, Java, and have even done some development work on the Linux platform (although most of this involved ensuring that software I wrote in C++ was platform independent).

I have a strong passion for software technology, both higher level and more recently, systems level stuff (the dissertation I am doing for my degree is to implement a small compiler and virtual machine in C# for a Pascal-style language).

You may also be interested in...

 First Prev Next
 http://www.unidata.ucar.edu/software/udunits/udunits-2/udunits2.html danong29-Jan-09 11:02 danong 29-Jan-09 11:02
 Re: http://www.unidata.ucar.edu/software/udunits/udunits-2/udunits2.html 5unkR28-Sep-09 21:10 5unkR 28-Sep-09 21:10
 Culture issue Nicolas Mohamed24-Dec-07 2:59 Nicolas Mohamed 24-Dec-07 2:59
 Temperature conversion is not correct! JAY.ca5-May-06 22:13 JAY.ca 5-May-06 22:13
 We know 1000 C = 1832 F. However, the app gives 1000c = 2076.12 F! Is the author possible to correct it? Jay.ca
 Re: Temperature conversion is not correct! guyinfun6-Feb-07 10:39 guyinfun 6-Feb-07 10:39
 Re: Temperature conversion is not correct! hanan.ta2-Oct-09 6:07 hanan.ta 2-Oct-09 6:07
 bad conversion jwaltman3-Mar-06 10:06 jwaltman 3-Mar-06 10:06
 License fkohan24-Jan-06 5:42 fkohan 24-Jan-06 5:42
 Re: License Rob Harwood24-Jan-06 5:46 Rob Harwood 24-Jan-06 5:46
 Last Visit: 31-Dec-99 18:00     Last Update: 28-Jul-15 22:04 Refresh 1