gtsocial-umbx

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README | LICENSE

angle.go (3673B)


      1 // Copyright 2014 Google Inc. All rights reserved.
      2 //
      3 // Licensed under the Apache License, Version 2.0 (the "License");
      4 // you may not use this file except in compliance with the License.
      5 // You may obtain a copy of the License at
      6 //
      7 //     http://www.apache.org/licenses/LICENSE-2.0
      8 //
      9 // Unless required by applicable law or agreed to in writing, software
     10 // distributed under the License is distributed on an "AS IS" BASIS,
     11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12 // See the License for the specific language governing permissions and
     13 // limitations under the License.
     14 
     15 package s1
     16 
     17 import (
     18 	"math"
     19 	"strconv"
     20 )
     21 
     22 // Angle represents a 1D angle. The internal representation is a double precision
     23 // value in radians, so conversion to and from radians is exact.
     24 // Conversions between E5, E6, E7, and Degrees are not always
     25 // exact. For example, Degrees(3.1) is different from E6(3100000) or E7(31000000).
     26 //
     27 // The following conversions between degrees and radians are exact:
     28 //
     29 //       Degree*180 == Radian*math.Pi
     30 //   Degree*(180/n) == Radian*(math.Pi/n)     for n == 0..8
     31 //
     32 // These identities hold when the arguments are scaled up or down by any power
     33 // of 2. Some similar identities are also true, for example,
     34 //
     35 //   Degree*60 == Radian*(math.Pi/3)
     36 //
     37 // But be aware that this type of identity does not hold in general. For example,
     38 //
     39 //   Degree*3 != Radian*(math.Pi/60)
     40 //
     41 // Similarly, the conversion to radians means that (Angle(x)*Degree).Degrees()
     42 // does not always equal x. For example,
     43 //
     44 //   (Angle(45*n)*Degree).Degrees() == 45*n     for n == 0..8
     45 //
     46 // but
     47 //
     48 //   (60*Degree).Degrees() != 60
     49 //
     50 // When testing for equality, you should allow for numerical errors (ApproxEqual)
     51 // or convert to discrete E5/E6/E7 values first.
     52 type Angle float64
     53 
     54 // Angle units.
     55 const (
     56 	Radian Angle = 1
     57 	Degree       = (math.Pi / 180) * Radian
     58 
     59 	E5 = 1e-5 * Degree
     60 	E6 = 1e-6 * Degree
     61 	E7 = 1e-7 * Degree
     62 )
     63 
     64 // Radians returns the angle in radians.
     65 func (a Angle) Radians() float64 { return float64(a) }
     66 
     67 // Degrees returns the angle in degrees.
     68 func (a Angle) Degrees() float64 { return float64(a / Degree) }
     69 
     70 // round returns the value rounded to nearest as an int32.
     71 // This does not match C++ exactly for the case of x.5.
     72 func round(val float64) int32 {
     73 	if val < 0 {
     74 		return int32(val - 0.5)
     75 	}
     76 	return int32(val + 0.5)
     77 }
     78 
     79 // InfAngle returns an angle larger than any finite angle.
     80 func InfAngle() Angle {
     81 	return Angle(math.Inf(1))
     82 }
     83 
     84 // isInf reports whether this Angle is infinite.
     85 func (a Angle) isInf() bool {
     86 	return math.IsInf(float64(a), 0)
     87 }
     88 
     89 // E5 returns the angle in hundred thousandths of degrees.
     90 func (a Angle) E5() int32 { return round(a.Degrees() * 1e5) }
     91 
     92 // E6 returns the angle in millionths of degrees.
     93 func (a Angle) E6() int32 { return round(a.Degrees() * 1e6) }
     94 
     95 // E7 returns the angle in ten millionths of degrees.
     96 func (a Angle) E7() int32 { return round(a.Degrees() * 1e7) }
     97 
     98 // Abs returns the absolute value of the angle.
     99 func (a Angle) Abs() Angle { return Angle(math.Abs(float64(a))) }
    100 
    101 // Normalized returns an equivalent angle in (-π, π].
    102 func (a Angle) Normalized() Angle {
    103 	rad := math.Remainder(float64(a), 2*math.Pi)
    104 	if rad <= -math.Pi {
    105 		rad = math.Pi
    106 	}
    107 	return Angle(rad)
    108 }
    109 
    110 func (a Angle) String() string {
    111 	return strconv.FormatFloat(a.Degrees(), 'f', 7, 64) // like "%.7f"
    112 }
    113 
    114 // ApproxEqual reports whether the two angles are the same up to a small tolerance.
    115 func (a Angle) ApproxEqual(other Angle) bool {
    116 	return math.Abs(float64(a)-float64(other)) <= epsilon
    117 }
    118 
    119 // BUG(dsymonds): The major differences from the C++ version are:
    120 //   - no unsigned E5/E6/E7 methods