Overview

Units and measures are common in engineering data, so the rosemath library provides definitions to identify and convert between the most frequently used units. Application-specific code build upon these definitions to process the more extensive data models found in STEP, IFC, CIS/2, and others.

All definitions are in the rose_unit.h header file.

The RoseUnit enum provides a simple value for commonly used units. The RoseMeasureType enum characterizes different types of quantites. The RoseUnitSet class holds a collection of units for each of the different types of quantities.

The rose_unit_convert() function changes a numeric value from one unit to another. You can get the name of a unit with rose_unit_get_name() or the kind of quantity with rose_unit_get_measure_name().

RoseUnit (enum)

enum RoseUnit {
        roseunit_unknown=0,
        roseunit_as_is,	// no conversion 

        /* length */
        roseunit_mm,	// millimeters
        roseunit_cm,	// centimeters
        roseunit_m,	// meters
        roseunit_in,	// inches
        roseunit_ft, 	// feet
        roseunit_micrometre,	// millionth of a meter
        roseunit_nanometre,	// billionth of a meter 
        roseunit_milliinch,     // thousandth of an inch
        roseunit_microinch,	// millionth of an inch	

        /* area */
        roseunit_mm2,	// square millimeters
        roseunit_cm2,	// square centimeters
        roseunit_m2,	// square meters
        roseunit_in2,	// square inches
        roseunit_ft2,	// square feet

        /* volume */
        roseunit_mm3,	// cubic millimeters
        roseunit_cm3,	// cubic centimeters
        roseunit_m3,	// cubic meters
        roseunit_in3,	// cubic inches
        roseunit_ft3,	// cubic feet

        /* angle */
        roseunit_deg,	// degrees
        roseunit_rad, 	// radians

        /* solid angle */
        roseunit_steradian, // steradian

        /* time */
        roseunit_sec,	// seconds
        roseunit_min,	// minutes
        roseunit_hour,	// hours

        /* feedrates - linear speed */
        roseunit_mmps,	// millimeters per second
        roseunit_mmpm,	// millimeters per minute
        roseunit_cmps,	// centimeters per second
        roseunit_mps,	// meters per second
        roseunit_ips,	// inches per second
        roseunit_ipm,	// inches per minute
        roseunit_fps,	// feet per second
        roseunit_fpm,	// feet per minute

        /* feed per revolution */
        roseunit_mmprev,	// millimeters per revolution
        roseunit_iprev,		// inches per revolution

        /* feed per tooth */
        roseunit_mmptooth,	// millimeters per tooth
        roseunit_iptooth,	// inches per tooth

        /* spinspeeds - rotational speed */
        roseunit_hertz,	// revolutions per second (hz)
        roseunit_rpm,	// revolutions per minute
        // change to use a revolution context dependent unit


        /* pressure */
        roseunit_pa,	// pascals
        roseunit_kpa,	// kilopascal
        roseunit_mpa,	// megapascal
        roseunit_psi,	// pounds per square inch

        /* force */
        roseunit_newton, // newtons
        roseunit_lbf,	// pound force

        /* power */
        roseunit_watt,	// watts
        roseunit_kw,	// kilowatts
        roseunit_hp,	// horsepower

        /* torque - full names to avoid confusion with nanometers */
        roseunit_newton_meter,	// newton meters
        roseunit_pound_foot,	// pound foot

        /* temperature */
        roseunit_celsius, 	// degree Celsius
        roseunit_kelvin, 	// degree Kelvin
        roseunit_fahrenheit,	// degree Fahrenheit
        roseunit_rankine,	// degree Rankine
        
	/* symbolic units */
        roseunit_count,
        roseunit_parameter,
        roseunit_ratio,
        roseunit_revolution,
        roseunit_tooth,

	/* COMING NEXT RELEASE */
	/* mass units */
	roseunit_mg,
	roseunit_gram,
	roseunit_kg,
	roseunit_tonne, 	// megagram, aka metric ton

	roseunit_ounce,
	roseunit_pound,
	roseunit_ton,		// short ton  907.18474 kg
	roseunit_long_ton,	// long ton   1016.0469088 kg

	// other si base units
	roseunit_ampere,
	roseunit_becquerel,
	roseunit_candela,
	roseunit_coulomb,
	roseunit_farad,
	roseunit_gray,
	roseunit_henry,
	roseunit_joule,
	roseunit_lumen,
	roseunit_lux,
	roseunit_mole,
	roseunit_ohm,
	roseunit_siemens,
	roseunit_sievert,
	roseunit_tesla,
	roseunit_volt,
	roseunit_weber,

	// Extra units
	roseunit_kN,		// force, kilonewtons 

	/* mass density */
	roseunit_kg_per_m3,
	roseunit_g_per_cm3,
	roseunit_oz_per_in3,
	roseunit_lb_per_in3,
	roseunit_lb_per_ft3,

	/* area density */
	roseunit_kg_per_m2,
	roseunit_g_per_cm2,
	roseunit_oz_per_in2,
	roseunit_lb_per_in2,	// not roseunit_psi, which is force / area
	roseunit_lb_per_ft2,

        /* maximum number of elements defined, used for creating arrays,
         * bounds checking when cast to an int and such
         */
        ROSEUNIT_MAX_VALUE
};

The RoseUnit enumeration identifies common units. Application-specific code can process the general definitions from STEP, IFC, CIS/2 or others into these enums for easier processing.

RoseMeasureType (enum)

enum RoseMeasureType {
        rosemeasure_unknown = 0,
        rosemeasure_accel,		// linear acceleration
        rosemeasure_angle,
        rosemeasure_ang_accel,		// angular acceleration
        rosemeasure_ang_speed,		// angular frequency
        rosemeasure_area,
        rosemeasure_count,
        rosemeasure_force,
        rosemeasure_length,
        rosemeasure_mass,
        rosemeasure_parameter,
        rosemeasure_power,
        rosemeasure_pressure,
        rosemeasure_ratio,
        rosemeasure_revolution,
        rosemeasure_solid_angle,
        rosemeasure_speed,		// linear velocity
        rosemeasure_temp,
        rosemeasure_time,
        rosemeasure_tooth,
        rosemeasure_torque,
        rosemeasure_volume,

	/* COMING NEXT RELEASE */
	rosemeasure_amtofsubstance,
	rosemeasure_capacitance,
	rosemeasure_charge,
	rosemeasure_conductance,
	rosemeasure_current,
	rosemeasure_resistance,
	rosemeasure_voltage,
	rosemeasure_energy,
	rosemeasure_frequency,		// temporal frequency
	rosemeasure_illuminance,
	rosemeasure_inductance,
	rosemeasure_lumflux,
	rosemeasure_lumintensity,
	rosemeasure_magfluxdensity,
	rosemeasure_magflux,
	rosemeasure_absorbdose,
	rosemeasure_equivdose,
	rosemeasure_radioactivity,

	rosemeasure_massdensity,	// mass per volume
	rosemeasure_areadensity,	// mass per area

	/* maximum number of elements defined, used for creating 
         * arrays, bounds checking when cast to an int and such
	 */
	ROSEMEASURE_MAX_VALUE
};

The RoseMeasureType enumeration identifies kinds of quantities which can simplify reasoning with units and measures.

rose_unit_convert()

double rose_unit_convert(
        double val, 
        RoseUnit as_is, 
        RoseUnit to_be
        );

The rose_unit_convert() function converts a value between two units and returns the result. The conversion may be a constant factor returned by rose_unit_get_conversion() or more complex conversions like °Fahrenheit to °Celsius. The function returns ROSE_NULL_REAL if no conversion exists or the input is null.

double val;

// 10in, returns 254mm
val = rose_unit_convert (10, roseunit_in, roseunit_mm);

// 5cm, returns 50mm
val = rose_unit_convert (5, roseunit_cm, roseunit_mm);

// 63.5cm, returns 25in
val = rose_unit_convert (63.5, roseunit_cm, roseunit_in);

// freezing point, returns 32F
val = rose_unit_convert (0, roseunit_celsius, roseunit_fahrenheit);

// boiling point, return 212F
val = rose_unit_convert (100, roseunit_celsius, roseunit_fahrenheit);

rose_unit_find()

RoseUnit rose_unit_find (const char * lookup_by_name);

The rose_unit_find() function returns the RoseUnit enum value identifying a unit. The function takes a string name and finds the unit matching a known long or short name, regardless of case.

RoseUnit u;

// the following all return roseunit_in
u = rose_unit_find(inch);
u = rose_unit_find(in);
u = rose_unit_find(INCH);
u = rose_unit_find(IN);

// the following returns roseunit_unknown
u = rose_unit_find(foobar);

rose_unit_find_rational()

RoseUnit rose_unit_find_rational(
        RoseUnit num, 
        RoseUnit denom
        );

The rose_unit_find_rational() function returns the unit corresponding to the "num" unit over the "denom" parameter, if it exists. If the result is not an element of RoseUnit, the function returns roseunit_unknown.

The rose_unit_get_numerator() and rose_unit_get_denominator() functions are used to find values in the opposite direction.

RoseUnit u;

// inches per second, returns roseunit_ips
u = rose_unit_find_rational(roseunit_in, roseunit_sec);

// revolutions per second, returns roseunit_hertz
u = rose_unit_find_rational(roseunit_revolution, roseunit_sec);

// nonsense, returns roseunit_unknown
u = rose_unit_find_rational(roseunit_kpa, roseunit_rpm);

rose_unit_find_related_by_factor()


RoseUnit rose_unit_find_related_by_factor(
	RoseUnit base,
	double factor
 	);

The rose_unit_find_related_by_factor() function searches the known conversions for a unit that when multiplied by the conversion factor results in the given unit. The function will first try to match the conversion factor to within ROSE_EPSILON. If that fails, it will try to match conversion factors within 1%. This function is used with STEP data to help identify units given as general conversion values. The function returns roseunit_unknown if no match can be found.

This finds (returned unit) * factor = base

RoseUnit u;

// will return roseunit_in for inch
u = rose_unit_find_related_by_factor(roseunit_mm, 25.4);

// will also return inch
u = rose_unit_find_related_by_factor(roseunit_cm, 2.54);

rose_unit_get_conversion()

double rose_unit_get_conversion (
        RoseUnit as_is, 
        RoseUnit to_be
        );

The rose_unit_get_conversion() function returns the floating point conversion factor that relates two units. The function returns ROSE_NULL_REAL if no conversion exists between the units. It returns zero if a conversion may exist but requires custom action.

The following code fragment shows the behavior of the conversion factor.

RoseUnit asis;
RoseUnit tobe;
double cf = rose_unit_get_conversion (asis, tobe);

if (ROSE_FLOAT_IS_NULL(cf))
    printf (no conversion exists\n);
else if (cf == 0)
    printf (CUSTOM\n);
else
    printf (%s == %g * %s\n,
    	   rose_unit_get_name(tobe),
 	   cf,
	   rose_unit_get_name(asis) );

Calling this code produces the following output

// asis = roseunit_in
// tobe = roseunit_mm
mm == 25.4 * in

// asis = roseunit_m
// tobe =  roseunit_mm
mm == 1000 * m

// asis = roseunit_deg 
// tobe =  roseunit_rad
radian == 0.0174533 * deg
    
// asis = roseunit_celsius
// tobe =  roseunit_fahrenheit
CUSTOM

// asis = roseunit_mm
// tobe = roseunit_rad 
no conversion exists

rose_unit_get_denominator()

RoseUnit rose_unit_get_denominator (RoseUnit u);

The rose_unit_get_denominator() function is the companion of the rose_unit_find_rational() and rose_unit_get_numerator() functions. Together, these functions can be used for simple reasoning on units.

The function returns the denominator of a rational unit. For example, calling this on meters per second (roseunit_mps) will return second (roseunit_sec). If the input is not a rational unit, the function returns roseunit_unknown.

rose_unit_get_fullname()

const char * rose_unit_get_fullname (RoseUnit u);  

The rose_unit_get_fullname() function returns a formal name for the unit, such as millimetere. The rose_unit_get_name() function returns the common abbreviation.

rose_unit_get_measure_name()

const char * rose_unit_get_measure_name (RoseMeasureType vt);

The rose_unit_get_measure_name() function returns a descriptive name for a given value type.

rose_unit_get_measure_type()

RoseMeasureType rose_unit_get_measure_type (RoseUnit u);
RoseMeasureType rose_unit_get_measure_type (const char * lookup_by_name);

The rose_unit_get_measure_type() function returns the RoseMeasureType enum value describing the type of quantity for a unit.

The version that takes a string name finds the value type matching a known name, regardless of case. These functions return rosemeasure_unknown if the unit enum is unknown or the measure name is not recognized.

rose_unit_get_name()

const char * rose_unit_get_name (RoseUnit u);

The rose_unit_get_name() function returns a concise name for the unit, such as mm. The rose_unit_get_fullname() returns a formal name for the unit, such as millimetere.

rose_unit_get_numerator()

RoseUnit rose_unit_get_numerator (RoseUnit u);

The rose_unit_get_numerator function is the companion of the rose_unit_find_rational() and rose_unit_get_denominator() functions.

The function returns the numerator of a rational unit. For example, calling this on meters per second (roseunit_mps) will return meter (roseunit_m). If the input is not a rational unit, the function returns the original input value.