202 lines
7.5 KiB
PHP
202 lines
7.5 KiB
PHP
<?php
|
|
namespace PhpUnitsOfMeasure;
|
|
|
|
/**
|
|
* Physical quantities with this trait
|
|
* have units which are metric and therefore have
|
|
* a standard set of prefixes.
|
|
*/
|
|
trait HasSIUnitsTrait
|
|
{
|
|
/**
|
|
* Given the patterns for generating the names and aliases,
|
|
* generate the various metric units of measure and add
|
|
* them to this physical quantity.
|
|
*
|
|
* Names and Aliases are created by replacing identifiers in the respective
|
|
* patterns. The current allowed replacement identifiers are:
|
|
* %p = the abbreviated SI prefix, like 'M' for 'megameter' or 'k' for 'kilogram'
|
|
* %P = the full SI prefix, like 'mega' for 'megameter' or 'kilo' for 'kilogram'
|
|
* %U = uppercase version of %P
|
|
*
|
|
* So for instance, in order to generate 'kg', 'mg', and 'g' names for SI units, the
|
|
* appropriate pattern would be '%pg'. Similarly, to generate 'kilogram', 'milligram',
|
|
* and 'gram' aliases, the pattern would be '%Pgram'.
|
|
*
|
|
* The $siUnit given in the 1st parameter must be some SI unit in the series of units
|
|
* to be generated by this method. This value is necessary to establish a conversion
|
|
* factor between this continuum of SI units and the Physical Quantity's native unit.
|
|
*
|
|
* The second parameter provides a scaling factor between the given SI unit in the first parameter
|
|
* and the base unit of the SI continuum (ie, 'grams', 'meters', 'seconds', etc). For instance,
|
|
* if a Kilogram unit of measure was passed for the 1st parameter, it would be necessary to
|
|
* then pass 1e-3 in the 2nd parameter to indicate that a gram is 1/1000 of the given unit.
|
|
*
|
|
* @param UnitOfMeasure $siUnit A unit in this physical quantity that is an SI unit of measure
|
|
* @param integer $toBaseSiUnitFactor The power-of-ten factor that converts the given SI unit into the not-prefixed SI base unit (ie 1e-3 for kilograms)
|
|
* @param string $namePattern The pattern to apply to the base unit's name to generate a new SI unit name
|
|
* @param array $aliasPatterns The collection of alias patterns to use in generating a new SI unit's aliases
|
|
* @param integer $powerFactor Use power factor for squares, qubic and other multiplication of SI factor (ie. square is 2, qubic is 3)
|
|
*/
|
|
protected static function addMissingSIPrefixedUnits(
|
|
UnitOfMeasure $siUnit,
|
|
$toBaseSiUnitFactor,
|
|
$namePattern,
|
|
array $aliasPatterns = [],
|
|
$powerFactor = NULL
|
|
) {
|
|
/**
|
|
* The standard set of SI prefixes
|
|
*/
|
|
$siPrefixes = [
|
|
[
|
|
'abbr_prefix' => 'Y',
|
|
'long_prefix' => 'yotta',
|
|
'factor' => 1e24
|
|
],
|
|
[
|
|
'abbr_prefix' => 'Z',
|
|
'long_prefix' => 'zetta',
|
|
'factor' => 1e21
|
|
],
|
|
[
|
|
'abbr_prefix' => 'E',
|
|
'long_prefix' => 'exa',
|
|
'factor' => 1e18
|
|
],
|
|
[
|
|
'abbr_prefix' => 'P',
|
|
'long_prefix' => 'peta',
|
|
'factor' => 1e15
|
|
],
|
|
[
|
|
'abbr_prefix' => 'T',
|
|
'long_prefix' => 'tera',
|
|
'factor' => 1e12
|
|
],
|
|
[
|
|
'abbr_prefix' => 'G',
|
|
'long_prefix' => 'giga',
|
|
'factor' => 1e9
|
|
],
|
|
[
|
|
'abbr_prefix' => 'M',
|
|
'long_prefix' => 'mega',
|
|
'factor' => 1e6
|
|
],
|
|
[
|
|
'abbr_prefix' => 'k',
|
|
'long_prefix' => 'kilo',
|
|
'factor' => 1e3
|
|
],
|
|
[
|
|
'abbr_prefix' => 'h',
|
|
'long_prefix' => 'hecto',
|
|
'factor' => 1e2
|
|
],
|
|
[
|
|
'abbr_prefix' => 'da',
|
|
'long_prefix' => 'deca',
|
|
'factor' => 1e1
|
|
],
|
|
[
|
|
'abbr_prefix' => '',
|
|
'long_prefix' => '',
|
|
'factor' => 1
|
|
],
|
|
[
|
|
'abbr_prefix' => 'd',
|
|
'long_prefix' => 'deci',
|
|
'factor' => 1e-1
|
|
],
|
|
[
|
|
'abbr_prefix' => 'c',
|
|
'long_prefix' => 'centi',
|
|
'factor' => 1e-2
|
|
],
|
|
[
|
|
'abbr_prefix' => 'm',
|
|
'long_prefix' => 'milli',
|
|
'factor' => 1e-3
|
|
],
|
|
[
|
|
'abbr_prefix' => 'µ',
|
|
'long_prefix' => 'micro',
|
|
'factor' => 1e-6
|
|
],
|
|
[
|
|
'abbr_prefix' => 'n',
|
|
'long_prefix' => 'nano',
|
|
'factor' => 1e-9
|
|
],
|
|
[
|
|
'abbr_prefix' => 'p',
|
|
'long_prefix' => 'pico',
|
|
'factor' => 1e-12
|
|
],
|
|
[
|
|
'abbr_prefix' => 'f',
|
|
'long_prefix' => 'femto',
|
|
'factor' => 1e-15
|
|
],
|
|
[
|
|
'abbr_prefix' => 'a',
|
|
'long_prefix' => 'atto',
|
|
'factor' => 1e-18
|
|
],
|
|
[
|
|
'abbr_prefix' => 'z',
|
|
'long_prefix' => 'zepto',
|
|
'factor' => 1e-21
|
|
],
|
|
[
|
|
'abbr_prefix' => 'y',
|
|
'long_prefix' => 'yocto',
|
|
'factor' => 1e-24
|
|
],
|
|
];
|
|
|
|
// Determine the conversion factor from the no-prefix SI unit to the physical quantity's native unit
|
|
$noPrefixToNativeUnitFactor = $siUnit->convertValueToNativeUnitOfMeasure(1) * $toBaseSiUnitFactor;
|
|
|
|
// For each of the standard SI prefixes, attempt to register a new unit of measure
|
|
foreach ($siPrefixes as $prefixDefinition) {
|
|
// Build a function for resolving a pattern into a unit name
|
|
$parsePattern = function ($pattern) use ($prefixDefinition) {
|
|
return strtr(
|
|
$pattern,
|
|
[
|
|
'%p' => $prefixDefinition['abbr_prefix'],
|
|
'%P' => $prefixDefinition['long_prefix'],
|
|
'%U' => strtoupper($prefixDefinition['long_prefix'])
|
|
]
|
|
);
|
|
};
|
|
|
|
// Generate the base name of the new unit
|
|
$name = $parsePattern($namePattern);
|
|
|
|
// Determine the factor that converts the new unit into the physical quantity's
|
|
// native unit of measure.
|
|
if (is_int($powerFactor) && $powerFactor != 0) {
|
|
$prefixDefinition['factor'] = pow($prefixDefinition['factor'], $powerFactor);
|
|
}
|
|
$toNativeUnitFactor = $noPrefixToNativeUnitFactor * $prefixDefinition['factor'];
|
|
|
|
// Instantiate the new unit of measure
|
|
$newUnit = UnitOfMeasure::linearUnitFactory($name, $toNativeUnitFactor);
|
|
|
|
// Generate the aliases of the new unit
|
|
foreach ($aliasPatterns as $aliasPattern) {
|
|
$newUnitAlias = $parsePattern($aliasPattern);
|
|
$newUnit->addAlias($newUnitAlias);
|
|
}
|
|
|
|
// If the unit doesn't conflict with any of the already-existing units, register it
|
|
if (!static::unitNameOrAliasesAlreadyRegistered($newUnit)) {
|
|
static::addUnit($newUnit);
|
|
}
|
|
}
|
|
}
|
|
}
|