forked from mbk-lab/rui_orig
2
0
Fork 0
rui/angleUnit.go

213 lines
5.0 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package rui
import (
"fmt"
"math"
"strconv"
"strings"
)
// AngleUnitType : type of enumerated constants for define a type of AngleUnit value.
// Can take the following values: Radian, Degree, Gradian, and Turn
type AngleUnitType uint8
const (
// Radian - angle in radians
Radian AngleUnitType = 0
// Radian - angle in radians * π
PiRadian AngleUnitType = 1
// Degree - angle in degrees
Degree AngleUnitType = 2
// Gradian - angle in gradian (1400 of a full circle)
Gradian AngleUnitType = 3
// Turn - angle in turns (1 turn = 360 degree)
Turn AngleUnitType = 4
)
// AngleUnit describe a size (Value field) and size unit (Type field).
type AngleUnit struct {
Type AngleUnitType
Value float64
}
// Deg creates AngleUnit with Degree type
func Deg(value float64) AngleUnit {
return AngleUnit{Type: Degree, Value: value}
}
// Rad create AngleUnit with Radian type
func Rad(value float64) AngleUnit {
return AngleUnit{Type: Radian, Value: value}
}
// PiRad create AngleUnit with PiRadian type
func PiRad(value float64) AngleUnit {
return AngleUnit{Type: PiRadian, Value: value}
}
// Grad create AngleUnit with Gradian type
func Grad(value float64) AngleUnit {
return AngleUnit{Type: Gradian, Value: value}
}
// Equal compare two AngleUnit. Return true if AngleUnit are equal
func (angle AngleUnit) Equal(size2 AngleUnit) bool {
return angle.Type == size2.Type && angle.Value == size2.Value
}
func angleUnitSuffixes() map[AngleUnitType]string {
return map[AngleUnitType]string{
Degree: "deg",
Radian: "rad",
PiRadian: "pi",
Gradian: "grad",
Turn: "turn",
}
}
// StringToAngleUnit converts the string argument to AngleUnit
func StringToAngleUnit(value string) (AngleUnit, bool) {
var angle AngleUnit
ok, err := angle.setValue(value)
if !ok {
ErrorLog(err)
}
return angle, ok
}
func (angle *AngleUnit) setValue(value string) (bool, string) {
value = strings.ToLower(strings.Trim(value, " \t\n\r"))
setValue := func(suffix string, unitType AngleUnitType) (bool, string) {
val, err := strconv.ParseFloat(value[:len(value)-len(suffix)], 64)
if err != nil {
return false, `AngleUnit.SetValue("` + value + `") error: ` + err.Error()
}
angle.Value = val
angle.Type = unitType
return true, ""
}
if value == "π" {
angle.Value = 1
angle.Type = PiRadian
return true, ""
}
if strings.HasSuffix(value, "π") {
return setValue("π", PiRadian)
}
if strings.HasSuffix(value, "°") {
return setValue("°", Degree)
}
for unitType, suffix := range angleUnitSuffixes() {
if strings.HasSuffix(value, suffix) {
return setValue(suffix, unitType)
}
}
if val, err := strconv.ParseFloat(value, 64); err == nil {
angle.Value = val
angle.Type = Radian
return true, ""
}
return false, `AngleUnit.SetValue("` + value + `") error: invalid argument`
}
// String - convert AngleUnit to string
func (angle AngleUnit) String() string {
if suffix, ok := angleUnitSuffixes()[angle.Type]; ok {
return fmt.Sprintf("%g%s", angle.Value, suffix)
}
return fmt.Sprintf("%g", angle.Value)
}
// cssString - convert AngleUnit to string
func (angle AngleUnit) cssString() string {
if angle.Type == PiRadian {
return fmt.Sprintf("%grad", angle.Value*math.Pi)
}
return angle.String()
}
// ToDegree returns the angle in radians
func (angle AngleUnit) ToRadian() AngleUnit {
switch angle.Type {
case PiRadian:
return AngleUnit{Value: angle.Value * math.Pi, Type: Radian}
case Degree:
return AngleUnit{Value: angle.Value * math.Pi / 180, Type: Radian}
case Gradian:
return AngleUnit{Value: angle.Value * math.Pi / 200, Type: Radian}
case Turn:
return AngleUnit{Value: angle.Value * 2 * math.Pi, Type: Radian}
}
return angle
}
// ToDegree returns the angle in degrees
func (angle AngleUnit) ToDegree() AngleUnit {
switch angle.Type {
case Radian:
return AngleUnit{Value: angle.Value * 180 / math.Pi, Type: Degree}
case PiRadian:
return AngleUnit{Value: angle.Value * 180, Type: Degree}
case Gradian:
return AngleUnit{Value: angle.Value * 360 / 400, Type: Degree}
case Turn:
return AngleUnit{Value: angle.Value * 360, Type: Degree}
}
return angle
}
// ToGradian returns the angle in gradians (1400 of a full circle)
func (angle AngleUnit) ToGradian() AngleUnit {
switch angle.Type {
case Radian:
return AngleUnit{Value: angle.Value * 200 / math.Pi, Type: Gradian}
case PiRadian:
return AngleUnit{Value: angle.Value * 200, Type: Gradian}
case Degree:
return AngleUnit{Value: angle.Value * 400 / 360, Type: Gradian}
case Turn:
return AngleUnit{Value: angle.Value * 400, Type: Gradian}
}
return angle
}
// ToTurn returns the angle in turns (1 turn = 360 degree)
func (angle AngleUnit) ToTurn() AngleUnit {
switch angle.Type {
case Radian:
return AngleUnit{Value: angle.Value / (2 * math.Pi), Type: Turn}
case PiRadian:
return AngleUnit{Value: angle.Value / 2, Type: Turn}
case Degree:
return AngleUnit{Value: angle.Value / 360, Type: Turn}
case Gradian:
return AngleUnit{Value: angle.Value / 400, Type: Turn}
}
return angle
}