A PHP support for string, decimal, radian and object angles, providing goniometric algebra and comparison between angles.
- Requirements
- Installation
- Quick Start
- Usage
- FakerPHP support
- API documentation
- PHP v8.4+
- BC Math PHP extension
composer require marcoconsiglio/goniometry
Import this class to represent angles.
use MarcoConsiglio\Goniometry\Angle;Create an Angle object (-360°/+360°).
$alfa = Angle::createFromValues(180, 30);
$beta = Angle::createFromString("180° 30'");
$gamma = Angle::createFromDecimal(180.5);
$delta = Angle::createFromRadian(M_PI); // 180°Create an AngularDistance object (-180°/+180°).
$alfa = AngularDistance::createFromValues(180, 30);
$beta = AngularDistance::createFromString("180° 30'");
$gamma = AngularDistance::createFromDecimal(180.5);
$delta = AngularDistance::createFromRadian(M_PI); // 180°Both Angle and AngularDistance implements the Angle interface.
This creates an angle from its values in degrees, minutes and seconds:
$alfa = Angle::createFromValues(180, 12, 43.4618, Rotation::CLOCKWISE); // -180° 12' 43.4618"Rotation::COUNTER_CLOCKWISE is the plus sign, Rotation::CLOCKWISE is the minus sign.
A null angle (exactly Rotation::COUNTER_CLOCKWISE.
This creates an angle from its textual representation:
$beta = Angle::createFromString("-180° 12' 43.4618\"");This is possible thanks to the regular expressions
Angle::DEGREES_REGEX;
Angle::MINUTES_REGEX;
Angle::SECONDS_REGEX;These regex expressions treat degrees and minutes as int type, but seconds are treated as a float type.
You can create a negative Angle if the string representation start with the minus (-) sign.
The NoMatchException is thrown when you try to create an angle:
- with more than
$\pm360^\circ$ - with more than
$59'$ - with more than
$59.\overline{9}''$ .
This create an angle from its decimal representation:
$gamma = Angle::createFromDecimal(180.2119); // 180.2119°
$gamma = Angle::createFromDecimal(-180.2119); // -180.2119°
$gamma = Angle::createFromDecimal(301.0); // 1.0°This create an angle from its radian representation:
$delta = Angle::createFromRadian(M_PI); // π ≅ 180°
$delta = Angle::createFromRadian(
new Radian(Number::π())
); // π = 180°
$delta = Angle::createFromRadian(-M_PI); // -π ≅ -180°
$delta = Angle::createFromRadian(2 * M_PI); // 2π ≅ 0°If you need a precise π value, you can pass a Radian object constructed with the Number::π() static method that return the π constant with an arbitrary precision up to 54 digits.
The Radian class extend the ModularNumber class, whose API is documented in marcoconsiglio/modular-arithmetic.
For more info on Number::π() check the API of marcoconsiglio/bcmath-extended.
You can obtain sexagesimal values separated in an array (simple by default, or associative):
$values = $alfa->getDegrees();
echo $values[0]; // int
echo $values[1]; // int
echo $values[2]; // float
$values = $alfa->getDegrees(true);
echo $value['degrees']; // int
echo $value['minutes']; // int
echo $value['seconds']; // floatThe angle's direction determines the sign of the degrees value.
There are read-only properties too:
/** @var Degrees */
(string) $alfa->degrees; // 180°
/** @var Minutes */
(string) $alfa->minutes; // 12'
/** @var Seconds */
(string) $alfa->seconds; // 43"
/** @var Rotation */
$alfa->direction; // Rotation::CLOCKWISE (-1)The Degrees, Minutes, and Seconds extends ModularNumber, whose API is documented in marcoconsiglio/modular-arithmetic.
You can cast Degrees, Minutes, and Seconds to string.
Positive angles are represented by the enum constant
Rotation::COUNTER_CLOCKWISE; // 1while negative angles are represented by the opposite enum constant:
Rotation::CLOCKWISE; // -1You can toggle the rotation direction:
$beta = $alfa->oppositeRotation();Since the Angle instance is immutable, the toggleRotation() method returns a copy with the opposite sign.
You can check if an Angle is clockwise or counterclockwise.
// If $alfa is a positive angle
$alfa->isCounterClockwise(); // true
$alfa->isClockwise(); // false
// If $beta is a negative angle
$beta->isCounterClockwise(); // false
$beta->isClockwise(); // trueYou can calc the opposite direction of an object implementing the Angle interface with the method oppositeDirection().
$alfa = Angle::createFromDecimal(90.0);
$beta = $alfa->oppositeDirection();
(string) $beta; // 180° 0' 0"You can cast the angle to float type, with optional precision up to PHP_FLOAT_DIG decimal places:
$alfa->toFloat(); // 180.211971543295645
$alfa->toFloat(4); // 180.2119
$alfa->toFloat(200) // 180.211971543295645You can specify a precision up to PHP_FLOAT_DIG decimal places.
If the number of decimal places is not set, PHP_FLOAT_DIG is used.
If you need an arbitrary precision, you can obtain a SexadecimalDegrees instance representing the sexadecimal value of the angle.
$sexadecimal = $alfa->toSexadecimalDegrees();
/** @var Number */
(string) $sexadecimal->value;// 180.2119715432956455962174521226543543
/** @var float */
$sexadecimal->value(); // 180.211971543295645
/** @var float */
$sexadecimal->value(3); // 180.212
/** @var float */
$sexadecimal->value(12); // 180.211971543296The $value property is a Number object extending the BCMath\Number class, whose API is documented in marcoconsiglio/bcmath-extended.
The value() method cast the SexadecimalDegrees object to float.
You can specify a precision up to PHP_FLOAT_DIG decimal places.
If the number of decimal places is not set, PHP_FLOAT_DIG is used.
You can cast the angle to radian (float), with optional precision up to PHP_FLOAT_DIG decimal places:
$alfa->toRadian(); // 3.141592653589793
$alfa->toRadian(3); // 3.141
$alfa->toRadian(200); // 3.141592653589793 You can specify a precision up to PHP_FLOAT_DIG decimal places.
If the number of decimal places is not set, PHP_FLOAT_DIG is used.
You can cast the angle to a string representation:
(string) $alfa; // 180° 30' 25.757385"WARNING! In this case, maximum precision is unknown. The Seconds class uses the BCMath extension behind the scenes. The seconds value is stored with arbitrary precision, so in some cases the number of seconds could potentially have many digits, making the string very long.
You can compare an Angle or AngularDistance object against a sexadecimal or sexagesimal value.
Comparisons are performed with absolute values (congruent comparison), meaning that
If you need a relative comparison, you should cast the angle to a sexadecimal float and then perform the arithmetic comparison,
meaning that
Each comparison can be performed against
- a
stringangle (sexagesimal), - an
int(sexagesimal degrees), - a
float(sexadecimal degrees), - or another instance implementing the
Angleinterface.
Comparisons via radian values are not available.
You can specify an optional precision expressed as the number of decimal places used to round the angle value. The precision is only used when comparing against a float (sexadecimal).
$alfa = Angle::createFromDecimal(89.999);
$alfa->isEqualTo(90.0, 0); // true with precision 0
$alfa->isEqualTo(90.0, 3); // false with precision 3$alfa = Angle::createFromDecimal(180);
$beta = Angle::createFromDecimal(90);
$gamma = Angle::createFromDecimal(360);
$alfa->isGreaterThan(90); // true 180 > 90
$alfa->gt("90° 0' 0\""); // true 180 > 90
$alfa->isGreaterThan($gamma); // false 180 > 360
$alfa->gt($gamma); // false 180 > 360$alfa = Angle::createFromDecimal(180);
$beta = Angle::createFromDecimal(90);
$gamma = Angle::createFromDecimal(90);
$alfa->isGreaterThanOrEqualTo(90); // true 180 ≧ 90
$alfa->gte("180 0' 0\""); // true 180 ≧ 180
$beta->isGreaterThanOrEqualTo($alfa); // true 90 ≧ 180
$beta->gte(90); // true 90 ≧ 90$alfa = Angle::createFromDecimal(90);
$beta = Angle::createFromDecimal(180);
$alfa->isLessThan(180); // true 90 < 180
$alfa->lt(180); // true 90 < 180
$alfa->isLessThan($beta); // true 90 < 180
$beta->lt($alfa); // false 180 < 90$alfa = Angle::createFromDecimal(90);
$beta = Angle::createFromDecimal(180);
$alfa->isLessThanOrEqualTo(180); // true 90 ≦ 180
$alfa->lte(90); // true 90 ≦ 90
$alfa->isLessThanOrEqualTo($beta); // false 90 ≦ 180
$alfa->lte($beta); // false 90 ≦ 180$alfa = Angle::createFromDecimal(180);
$beta = Angle::createFromDecimal(180);
$gamma = Angle::createFromDecimal(-180);
$alfa->isEqualTo($beta); // true 180 ≅ 180
$alfa->eq($gamma); // true 180 ≅ -180$alfa = Angle::createFromDecimal(90);
$beta = Angle::createFromDecimal(180);
$alfa->isDifferentThan(180); // true 90 ≇ 180
$alfa->not(180); // true 90 ≇ 180
$alfa->isDifferentThan(-90); // false 90 ≇ -90
$beta->not($alfa); // true 180 ≇ 90When comparing two Angles sometimes their difference is negligible. In this case you can use a fuzzy comparison specifing a delta error Angle within which the comparison will be succesful.
Delta (Δ) is the double of epsilon error (±ε).
$alfa = Angle::createFromDecimal(90.345);
$beta = Angle::createFromValue(90);
$delta = Angle::createFromValue(4); // ±2° error
$alfa->fuzzyEqual($beta, $delta); // true
$alfa->feq($beta, $delta); // trueYou can sum two angles. An angle of type AngularDistance do not have the absSum() methods.
The relative sum can return both positive or negative angle.
$alfa = Angle::createFromDecimal(180);
$beta = Angle::createFromDecimal(-270);
$gamma =
$alfa // 180° +
->sum($beta); // -270° =
(string) $gamma; // -90° The absolute sum will always return a positive angle.
$alfa = Angle::createFromDecimal(180);
$beta = Angle::createFromDecimal(-270);
$gamma =
$alfa // 180° +
->absSum($beta); //-270° =
(string) $gamma; // 270°$alfa = Angle::createFromDecimal(-180);
$beta = Angle::createFromDecimal(-270);
$gamma =
$alfa // -180° +
->absSum($beta); // -270°
(string) $gamma; // 270°This library provides support to FakerPHP through the WithAngleFaker trait. Here's a list of the available methods.
| Method | Return type | Min (included) | Min (excluded) | Max (included) | Max (excluded) |
|---|---|---|---|---|---|
randomPrecision() |
int |
0 | PHP_FLOAT_DIG |
||
randomDegrees() |
Degrees |
0° | 359° | ||
randomMinutes() |
Minutes |
0' | 59' | ||
randomSeconds() |
Seconds |
0" | 60" | ||
randomAngle() |
Angle |
-360° | +360° | ||
positiveRandomAngle() |
Angle |
0° | +360° | ||
negativeRandomAngle() |
Angle |
-360° | 0° | ||
randomDirection() |
Direction |
CLOCKWISE |
COUNTER_CLOCKWISE |
||
randomSexagesimalString() |
string |
-360° | +360° | ||
randomSexagesimal() |
SexagesimalDegrees |
-360° | +360° | ||
positiveRandomSexagesimal() |
SexagesimalDegrees |
0° | +360° | ||
negativeRandomSexagesimal() |
SexagesimalDegrees |
-360° | 0° | ||
randomSexadecimal() |
float |
-360° | +360° | ||
positiveRandomSexadecimal() |
float |
0° | +360° | ||
negativeRandomSexadecimal() |
float |
-360° | 0° | ||
randomRadian() |
Radian |
-2π | +2π | ||
positiveRandomRadian() |
Radian |
0 | +2π | ||
negativeRandomRadian() |
Radian |
-2π | 0 | ||
positiveRandomAngularDistance() |
AngularDistance |
0° | +180° | ||
negativeRandomAngularDistance() |
AngularDistance |
-180° | 0° |
Check the API documentation to find out more info about these methods.
You can read the code documentation in ./docs/html/index.html.