@r47onfire/hyperspace
v1.0.0
Published
Simple dimensional analysis and unit conversion library designed for basing games in physical units
Readme
hyperspace
Simple dimensional analysis and unit conversion library designed for basing games in physical units.
Install
pnpm install @r47onfire/hyperspaceQuick start
import { UnitSystem, basicUnits, physicsUnits, dataUnits } from "@r47onfire/hyperspace";
const U = new UnitSystem();
basicUnits(U); // installs basic length, time, mass, temperature
physicsUnits(U); // installs newtons, pascals, joules, watts, etc.
dataUnits(U); // installs bytes, kilobytes, megabytes, etc.
// Convert units numerically
const v = U.parse(100, "km/h");
U.convert(v, "m/s") // => 27.777777...
// Format as a string
U.format(v, "m/s") // => "27.777777... meters seconds^-1"
U.format(v, "m/s", false) // => "27.777777... m/s"
// Format as compound unit
U.format(U.parse(3661, "s"), ["h", "min", "s"])
// => "1 hour 1 minute 1 second"
// Format as best unit
U.format(U.parse(214523, "B"), ["B", "KB", "MB"], true)
// => "214.523 KB"
// Unit recognition
U.parse(5, "kg*m/s^2").kind // => "force" (equivalent to newtons)Define units
// base dimension kind name
U.addKind("length");
// derived dimension kind with composition exponents
U.addKind("speed", { length: 1, time -1 });
// base unit: name, abbreviation, kind, aliases
U.addBase("meters", "m", "length", ["metres"]);
// converted unit: name, abbreviation, conversion factor, reference unit
U.addConversion("centimeters", "cm", 100, "m", ["centimetres"]);
// unit = base * perBase
// non-affine unit: 2 numbers are ratio and offset
U.addOffsetConversion("celsius", "°C", 1, -273.15, "kelvin", ["℃"]);
U.addOffsetConversion("fahrenheit", "°F", 1.8, 32, "celsius", ["℉"]);
// unit = base * perBase + zeroOffsetMath with units
U.parseUnit("N*m") // => the entry for Joules
U.add(a, b), U.sub(a, b), // must be the same dimensions, error if not
U.mul(a, b), U.div(a, b), // can be different dimensions
U.pow(a, n) // n must be a dimensionless numberMetadata
U.kinds // => ["length", "time", ...]
U.dimensionsOf("force") // => { mass: 1, length: 1, time: -2 }
U.baseFor("length") // => "meters"
U.expand("velocity") // => { length: 1, time: -1 }Built-in units
Provided by basicUnits():
- meters, centimeters, kilometers, feet, inches (length)
- pixels as configurable ratio length unit (default 64 pixels per meter)
- seconds milliseconds, minutes, hours (time)
- hertz (frequency = 1/time)
- kilograms, grams (mass)
- celsius, fahrenheit, kelvin (temperature)
- names "area", "volume", "velocity", "acceleration" (for length^2, length^3, length/time, and length/time^2)
Provided by physicsUnits():
- amperes (current)
- newtons (force = mass*acceleration)
- pascals (pressure = force/area)
- joules (energy = force*length)
- watts (power = energy/time)
- coulombs (charge = current*time)
- volts (voltage = energy/charge)
- ohms (resistance = voltage/current)
- farads (capacitance = charge/voltage)
- webers (magnetic flux = voltage*time)
- henries (inductance = flux/current)
- teslas (magnetic field density = flux/area)
Provided by dataUnits():
- bits, bytes (data)
- kilobytes, megabytes, gigabytes, terabytes (factor of 1000 scaling)
- kibibytes, mebibytes, gibibytes, tebibytes (factor of 1024 scaling)
- name "bitrate" for data/time
Caveats
No support for differentiating between normal frequency and angular frequency. For example:
const L = U.parse(0.001, "henries") const C = U.parse(0.001, "farads"); // resonant angular frequency = 1/sqrt(L*C) = 1000 rad/s const omega0 = U.pow(U.mul(L, C), -0.5); U.format(omega0, "Hz") // => "1000 Hz" - should error!!No support for logarithmic units (e.g. decibels) yet.
