Angle

From Unify Community Wiki
(Difference between revisions)
Jump to: navigation, search
(New page: Category: BooCategory: Scripts Author: Adrian == Description == This is a helper class that greatly simplifies working with euler angles. It allows to calculate wi...)
 
Line 149: Line 149:
  
 
To be able to use Angle from all your classes (JavaScript, Boo and C#), it's best to put it into your "Standard Assets/Scripts" folder.
 
To be able to use Angle from all your classes (JavaScript, Boo and C#), it's best to put it into your "Standard Assets/Scripts" folder.
 +
 +
== History ==
 +
 +
* 4. May 2008
 +
Fixed a bug in Angle.Diffrence(Angle), now wraps correctly and never exceeds 180 degrees.
 +
* 13. April 2008
 +
Initial release
  
 
== Code (Angle.boo) ==
 
== Code (Angle.boo) ==
Line 283: Line 290:
 
      
 
      
 
     def Difference(ang as Angle):
 
     def Difference(ang as Angle):
         return Angle(Mathf.Abs(cast(single,(_angle - ConvertToLocal(ang)))))
+
         diff = Mathf.Abs(cast(single,(_angle - ConvertToLocal(ang))))
 +
        if (diff > 180):
 +
            diff = 360 - diff
 +
        return Angle(diff)
 
      
 
      
 
     # ---------------------------------------- #
 
     # ---------------------------------------- #

Revision as of 17:26, 4 May 2008

Author: Adrian

Contents

Description

This is a helper class that greatly simplifies working with euler angles. It allows to calculate with angles using regular operators, compare angles with each other and automatically wraps angles. The class supports both degree and radian and will try guess the type when calculating or comparing with float values.

Usage

Angle supports both degree and radian. When creating an Angle, you can specify the type of the Angle or use Angle's default mode. <javascript>// Create an Angle with default type (Degree) var a = Angle(50); // Specify Angle type var a = Angle(2.34, AngleMode.Radian); // Change the default mode Angle.defaultMode = AngleMode.Radian </javascript>

Angle's automatically convert their type so it's possible to mix radian and degree. <javascript>var a = Angle(90, AngleMode.Degree); var b = Angle(Mathf.PI / 2, AngleMode.Radian); var c = a + b; Debug.Log(c.Deg + " / " + c.Rad); // Prints: 180 / 3.1415... </javascript>

It's possible to mix regular float values with Angles. float values will assumed to be the same type as the Angle they interact with. <javascript>var a = Angle(90); // Angle in degree var b = a - 180; // Assumes 180 to be same type (degree) Debug.Log(b) // Prints: 270 deg </javascript>

When comparing angles, wrapping will be considered. The circle is split into two parts and an Angle is less if it's inside the left-hand part and bigger if it's inside the right-hand part. Smaller and bigger than will neither match the same nor the opposite Angle, smaller and equal or bigger and equal with both math the same and the opposite Angle. <javascript>var a = Angle(180); Debug.Log(90 < a); // True Debug.Log(270 < a); // False Debug.Log(0 < a); // False Debug.Log(0 <= a); // True </javascript>

Supported Operations

Following operations are supported. <javascript>var a = Angle(90); var b = Angle(90); var c;

// Addition c = a + b; // c == Angle(180) c = a + 90; // c == Angle(180) c = 90 + a; // c == Angle(180)

// Subtraction c = a - b; // c == Angle(0) c = a - 90; // c == Angle(0) c = 90 - a; // c == Angle(0)

// Multiplication c = a * 2; // c == Angle(180) c = 2 * a; // c == Angle(180) // Note: a * b is not supported since it would be of type deg^2 or rad^2. Use a * b.Deg if needed.

// Division c = a / b; // c == 1 c = a / 90; // c == Angle(1) c = 90 / a; // c == 1 (90 is assumed to be Angle(90))

// Modulus c = a % b; // c == 0 c = a % 90; // c == Angle(0) c = 90 % a; // c == 0 (90 is assumed to be Angle(90))

// Equality c = (a == b); // c == true c = (a == 90); // c == true c = (90 == a); // c == true

// Inequality c = (a != b); // c == false c = (a != 90); // c == false c = (90 != a); // c == false

// Less than c = (a < b); // c == false c = (a < 90); // c == false c = (90 < a); // c == false

// Less than or equal c = (a <= b); // c == true c = (a <= 90); // c == true c = (90 <= a); // c == true

// Bigger than c = (a > b); // c == false c = (a > 90); // c == false c = (90 > a); // c == false

// Bigger than or equal c = (a >= b); // c == true c = (a >= 90); // c == true c = (90 >= a); // c == true

// Complement (~) c = ~a; // c == Angle(270) </javascript>

Methods

Angle objects support following operations: <javascript>// Create Angle with default type var a = Angle(90); // Create Angle with given type a = Angle(90, AngleMode.Degree); // Create empty Angle with type a = Angle(AngleMode.Degree); // Clone Angle a = Angle(a);

// Get and set current Angle's mode (converts the angle) Debug.Log(a.Mode); a.Mode = AngleMode.Radian;

// Get and set angle as degrees or radians Debug.Log(a.Deg + " / " + a.Rad); a.Deg = 90; a.Rad = Mathf.PI / 2;

// Calculations (makes no copy) a.Add(a); a.Add(Math.PI); a.Subtract(a); a.Subtract(Math.PI); a.Multiply(2); a.Divide(2); a.Reverse();

// Difference to another Angle a.Difference(a);

// Comparison var b = Angle(180); a.Equals(b); a.Opposite(b); a.LessThan(b); a.LessThanOrEqual(b); a.GreaterThan(b); a.GreaterThanOrEqual(b); </javascript>

Installation

To be able to use Angle from all your classes (JavaScript, Boo and C#), it's best to put it into your "Standard Assets/Scripts" folder.

History

  • 4. May 2008

Fixed a bug in Angle.Diffrence(Angle), now wraps correctly and never exceeds 180 degrees.

  • 13. April 2008

Initial release

Code (Angle.boo)

<boo>import UnityEngine

  1. Angle can be in Degree or Radian mode

enum AngleMode:

   Degree
   Radian

class Angle:

   # Default mode
   public static defaultMode as AngleMode = AngleMode.Degree
   
   # Radian or Degree mode?
   _mode as AngleMode = AngleMode.Degree
   
   Mode as AngleMode:
       get:
           return _mode
       set:
           _angle = GetAs(value)
           _mode = value
   
   static names as Hash = {AngleMode.Degree: "deg", AngleMode.Radian: "rad"}
   
   # ---------------------------------------- #
   
   # Angle value
   _angle as double
   
   # Get and set angle as radians
   Rad as double:
       get:
           return GetAs(AngleMode.Radian)
       set:
           SetAs(value,AngleMode.Radian)
   
   # Get and set angle as degrees
   Deg as double:
       get:
           return GetAs(AngleMode.Degree)
       set:
           SetAs(value,AngleMode.Degree)
   
   # ---------------------------------------- #
   
   # Make a new angle with default mode
   def constructor(ang as double):
       SetAs(ang, Angle.defaultMode)
   
   # Make a new angle with given mode
   def constructor(ang as double, m as AngleMode):
       _mode = m
       SetAs(ang, m)
   
   # Create zero Angle with given mode
   def constructor(m as AngleMode):
       _mode = m
   
   def constructor(a as Angle):
       _mode = a.Mode
       _angle = a.GetAs(_mode)
   
   # ---------------------------------------- #
   
   # Get angle as radian or dergee
   def GetAs(m as AngleMode):
       wrap()
       if m == _mode:
           return _angle
       elif m == AngleMode.Degree:
           return _angle * Mathf.Rad2Deg
       else:
           return _angle * Mathf.Deg2Rad
   
   # Set angle as radian or degree
   def SetAs(value as double, m as AngleMode):
       if m == _mode:
           _angle = value
       elif m == AngleMode.Degree:
           _angle = value * Mathf.Deg2Rad
       else:
           _angle = value * Mathf.Rad2Deg
   
   # Covert to string with type
   def ToString():
       wrap()
       return _angle.ToString() + " " + names[_mode]
   
   # ---------------------------------------- #
   
   # Wrap the angle around for < 0 and > 2*Half()
   private def wrap():
       if _angle < 0:
           _angle += 2*Half()
       elif _angle >= 2*Half():
           _angle = _angle % (2*Half())
   
   # Convert an Angle to local mode
   private def ConvertToLocal(a as Angle):
       return a.GetAs(_mode)
   
   # Get half angle based on mode
   private def Half() as double:
       if (_mode == AngleMode.Degree):
           return 180
       else:
           return Mathf.PI
   
   # ---------------------------------------- #
   
   def Add(ang as Angle):
       _angle += ConvertToLocal(ang)
   
   def Add(ang as double):
       _angle += ang
   
   def Subtract(ang as Angle):
       _angle -= ConvertToLocal(ang)
   
   def Subtract(ang as double):
       _angle -= ang
   
   def Multiply(ang as double):
       _angle *= ang
   
   def Divide(ang as double):
       _angle /= ang
   
   def Reverse():
       _angle += Half()
   
   def Difference(ang as Angle):
       diff = Mathf.Abs(cast(single,(_angle - ConvertToLocal(ang))))
       if (diff > 180):
           diff = 360 - diff
       return Angle(diff)
   
   # ---------------------------------------- #
   
   def Equals(ang as Angle):
       wrap()
       return _angle == ConvertToLocal(ang)
   
   def Opposite(ang as Angle):
       return ((_angle + Half() == ConvertToLocal(ang)) or (_angle == ConvertToLocal(ang) + Half()))
   
   def LessThan(big as Angle):
       return not GreaterThan(big) and not Equals(big) and not Opposite(big)
   
   def LessThanOrEqual(small as Angle):
       #Debug.Log(_angle + " <= " + small)
       return not GreaterThan(small)
   
   def GreaterThan(other as Angle):
       #Debug.Log(_angle + " > " + other)
       wrap()
       small = ConvertToLocal(other)
       if ((_angle == small)
               or
           (_angle >= Half() and (small > _angle or small <= _angle - Half()))
               or
           (_angle < Half() and (small > _angle and small <= _angle + Half()))):
           return false
       return true
   
   def GreaterThanOrEqual(big as Angle):
       return not LessThan(big)
   
   # ---------------------------------------- #
   
   # Addition (+)
   static def op_Addition(ang1 as Angle, ang2 as Angle):
       ang1 = Angle(ang1)
       ang1.Add(ang2)
       return ang1
   
   static def op_Addition(ang1 as Angle, ang2 as double):
       return op_Addition(ang1,Angle(ang2,ang1.Mode))
   
   static def op_Addition(ang1 as double, ang2 as Angle):
       return op_Addition(Angle(ang1,ang2.Mode),ang2)
   
   # Subtraction (-)
   static def op_Subtraction(ang1 as Angle, ang2 as Angle):
       ang1 = Angle(ang1)
       ang1.Subtract(ang2)
       return ang1
   
   static def op_Subtraction(ang1 as Angle, ang2 as double):
       return op_Subtraction(ang1,Angle(ang2,ang1.Mode))
   
   static def op_Subtraction(ang1 as double, ang2 as Angle):
       return op_Subtraction(Angle(ang1,ang2.Mode),ang2)
   
   # Multiplication (*)
   static def op_Multiply(ang1 as Angle, mult as double):
       ang1 = Angle(ang1)
       ang1.Multiply(mult)
       return ang1
   
   static def op_Multiply(mult as double, ang as Angle):
       return op_Multiply(ang, mult)
   
   # Division (/)
   static def op_Division(ang1 as Angle, div as double):
       ang1 = Angle(ang1)
       ang1.Divide(div)
       return ang1
   
   static def op_Division(ang1 as double, div as Angle):
       return op_Division(Angle(ang1, div.Mode), div)
   
   static def op_Division(ang1 as Angle, ang2 as Angle):
       return ang1.GetAs(AngleMode.Radian) / ang2.GetAs(AngleMode.Radian)
   
   # Modulus (%)
   static def op_Modulus(ang1 as Angle, ang2 as Angle):
       return (ang1.GetAs(ang1.Mode) % ang2.GetAs(ang1.Mode))
   
   static def op_Modulus(ang1 as Angle, div as double):
       return Angle(ang1.GetAs(ang1.Mode) % div, ang1.Mode)
   
   static def op_Modulus(ang1 as double, div as Angle):
       return op_Modulus(Angle(ang1, div.Mode), div)
   
   # Equality (==)
   static def op_Equality(ang1 as Angle, ang2 as Angle):
       return ang1.Equals(ang2)
   
   static def op_Equality(ang1 as Angle, ang2 as double):
       return op_Equality(ang1,Angle(ang2,ang1.Mode))
   
   static def op_Equality(ang1 as double, ang2 as Angle):
       return op_Equality(Angle(ang1,ang2.Mode),ang2)
   
   # Inequality (!=)
   static def op_Inequality(ang1 as Angle, ang2 as Angle):
       return not ang1.Equals(ang2)
   
   static def op_Inequality(ang1 as Angle, ang2 as double):
       return op_Inequality(ang1,Angle(ang2,ang1.Mode))
   
   static def op_Inequality(ang1 as double, ang2 as Angle):
       return op_Inequality(Angle(ang1,ang2.Mode),ang2)
   
   # Less than (<)
   static def op_LessThan(small as Angle, big as Angle):
       return small.LessThan(big)
   
   static def op_LessThan(ang1 as Angle, ang2 as double):
       return op_LessThan(ang1,Angle(ang2,ang1.Mode))
   
   static def op_LessThan(ang1 as double, ang2 as Angle):
       return op_LessThan(Angle(ang1,ang2.Mode),ang2)
   
   # Less than or equal (<=)
   static def op_LessThanOrEqual(small as Angle, big as Angle):
       return small.LessThanOrEqual(big)
   
   static def op_LessThanOrEqual(ang1 as Angle, ang2 as double):
       return op_LessThanOrEqual(ang1,Angle(ang2,ang1.Mode))
   
   static def op_LessThanOrEqual(ang1 as double, ang2 as Angle):
       return op_LessThanOrEqual(Angle(ang1,ang2.Mode),ang2)
   
   # Greater than (>)
   static def op_GreaterThan(big as Angle, small as Angle):
       return big.GreaterThan(small)
   
   static def op_GreaterThan(ang1 as Angle, ang2 as double):
       return op_GreaterThan(ang1,Angle(ang2,ang1.Mode))
   
   static def op_GreaterThan(ang1 as double, ang2 as Angle):
       return op_GreaterThan(Angle(ang1,ang2.Mode),ang2)
   
   # Greater than or equal (>=)
   static def op_GreaterThanOrEqual(big as Angle, small as Angle):
       return big.GreaterThanOrEqual(small)
   
   static def op_GreaterThanOrEqual(ang1 as Angle, ang2 as double):
       return op_GreaterThanOrEqual(ang1,Angle(ang2,ang1.Mode))
   
   static def op_GreaterThanOrEqual(ang1 as double, ang2 as Angle):
       return op_GreaterThanOrEqual(Angle(ang1,ang2.Mode),ang2)
   
   # Complement (~)
   static def op_OnesComplement(ang as Angle):
       ang = Angle(ang)
       ang.Reverse()
       return ang
   
   # ---------------------------------------- #

</boo>

Personal tools
Namespaces

Variants
Actions
Navigation
Extras
Toolbox