-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathDimension.php
More file actions
154 lines (138 loc) · 4.9 KB
/
Dimension.php
File metadata and controls
154 lines (138 loc) · 4.9 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
<?php
namespace MetaTunes\MeasurementClasses;
use ProcessWire\Wire;
use function ProcessWire\wire;
/**
* @property $dimensionArray
*
*/
/**
* #pw-summary Dimension objects are used within Measurement and BaseMeasurement objects to store the dimension of the measurement object
*
* #pw-body =
* If the relevant config file defines a dimension (see below) then a Measurement object will have a dimension attribute.
* This is an object (of class Dimension) with one data item : dimensionArray.
* Each SI base unit (of which there are seven) is associated with a text key as follows:
```
const TIME = 'time';
const LENGTH = 'length';
const MASS = 'mass';
const CURRENT = 'current';
const TEMPERATURE = 'temperature';
const SUBSTANCE_AMOUNT = 'substance_amount';
const LUMINOSITY = 'luminosity';
````
* The dimension of any SI derived unit is an array where the values for each key is the exponent of the relevant base dimension.
* So, for example, acceleration has a dimensionArray ``['length' => 1, 'time' => -2]``.
* Each quantity that has an SI base unit or SI derived unit as its base unit can therefore be associated with such an object.
* This enables dimensional analysis to be carried out on such quantities when (for example) multiplying and dividing them.
* However, quantities which do not have a base or derived SI unit as their base unit cannot be given a dimension.
* The config files include some SI base quantities and some SI derived quantities, but not all of them.
* It is therefore quite possible, for example, to construct a *Measurement::combineMeasurements()* which results in a SI derived quantity for which there is no config file (in which case a 'BaseMeasurement' object is returned).
* It is (technically) possible for users to extend the dimensions by artificially adding new ones, providing they are represented by unique text keys, but the user is then responsible for the meaningfulness and consistency of the result.
* #pw-body
*/
class Dimension extends Wire {
/** @var string */
public $dimensionArray;
// Define standard dimensions
const TIME = 'time';
const LENGTH = 'length';
const MASS = 'mass';
const CURRENT = 'current';
const TEMPERATURE = 'temperature';
const SUBSTANCE_AMOUNT = 'substance_amount';
const LUMINOSITY = 'luminosity';
public function __construct(?array $dimension = []) {
$this->dimensionArray = $dimension;
parent::__construct();
}
/**
* Get quantities that are consistent with this dimension
*
* @return array
*/
public function getQuantities() {
$allQuantities = Measurement::getQuantities();
$consistentQuantities = [];
foreach($allQuantities as $quantity) {
$m = new Measurement($quantity);
$quantityDimension = $m->dimension;
/* @var $quantityDimension Dimension */
if($quantityDimension && $this->dimensionArray == $quantityDimension->dimensionArray) $consistentQuantities[] = $quantity;
}
return $consistentQuantities;
}
/**
* Multiply by another dimension
* The result is simply the product of the dimensions.
* So ````['length' => 1]```` multiplied by ````['length' => 2, 'time' => -1]```` is ````['length' => 3, 'time' => -1]````
*
* @param Dimension $dim
* @param bool $divide
* @return $this
*/
public function multiplyBy(Dimension $dim, bool $divide = false): Dimension {
$dimArray1 = $this->dimensionArray;
$dimArray2 = $dim->dimensionArray;
$newDimensionArray = [];
foreach($dimArray1 as $key => $value) {
if(array_key_exists($key, $dimArray2)) {
if($divide) {
$newDimensionArray[$key] = $value - $dimArray2[$key];
} else {
$newDimensionArray[$key] = $value + $dimArray2[$key];
}
} else {
$newDimensionArray[$key] = $value;
}
}
$newItems = array_diff_key($dimArray2, $dimArray1);
foreach($newItems as $key => $newItem) {
if($divide) {
$newDimensionArray[$key] = - $newItem;
} else {
$newDimensionArray[$key] = $newItem;
}
}
$result = new Dimension($newDimensionArray);
return $result->simplify();
}
/**
* Divide by another dimension (analogous to multiplyBy())
*
* @see MetaTunes\MeasurementClasses\Dimension::multiplyBy
* @param Dimension $dim
* @return $this|Dimension
*/
public function divideBy(Dimension $dim) {
return $this->multiplyBy($dim, true);
}
/**
* Raise dimension to a power
* Value of dimension is multiplied by exponent.
* E.g ````['length' => 2]```` raised to power 3 is ````['length' => 6]````
*
* @param float $exponent
* @return $this
*/
public function power(float $exponent) {
$newDimensionArray = [];
foreach($this->dimensionArray as $key => $value) {
$newDimensionArray[$key] = $value * $exponent;
}
$result = new Dimension($newDimensionArray);
return $result->simplify();
}
/**
* Removes zero dimensions
*
* @return $this
*/
private function simplify() {
foreach($this->dimensionArray as $key => $value) {
if($value == 0) unset($this->dimensionArray[$key]);
}
return $this;
}
}