summaryrefslogtreecommitdiff
path: root/src/com/google/common/geometry/S1Angle.java
blob: 152052f372f1077cab7bd2d269b2fc7fe1151b94 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
/*
 * Copyright 2005 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.google.common.geometry;


public strictfp class S1Angle implements Comparable<S1Angle> {

  private double radians;

  public double radians() {
    return radians;
  }

  public double degrees() {
    return radians * (180 / Math.PI);
  }

  public long e5() {
    return Math.round(degrees() * 1e5);
  }

  public long e6() {
    return Math.round(degrees() * 1e6);
  }

  public long e7() {
    return Math.round(degrees() * 1e7);
  }

  /**
   * The default constructor yields a zero angle.
   */
  public S1Angle() {
    this.radians = 0;
  }

  private S1Angle(double radians) {
    this.radians = radians;
  }

  /**
   * Return the angle between two points, which is also equal to the distance
   * between these points on the unit sphere. The points do not need to be
   * normalized.
   */
  public S1Angle(S2Point x, S2Point y) {
    this.radians = x.angle(y);
  }

  @Override
  public boolean equals(Object that) {
    if (that instanceof S1Angle) {
      return this.radians() == ((S1Angle) that).radians();
    }
    return false;
  }

  @Override
  public int hashCode() {
    long value = Double.doubleToLongBits(radians);
    return (int) (value ^ (value >>> 32));
  }

  public boolean lessThan(S1Angle that) {
    return this.radians() < that.radians();
  }

  public boolean greaterThan(S1Angle that) {
    return this.radians() > that.radians();
  }

  public boolean lessOrEquals(S1Angle that) {
    return this.radians() <= that.radians();
  }

  public boolean greaterOrEquals(S1Angle that) {
    return this.radians() >= that.radians();
  }

  public static S1Angle max(S1Angle left, S1Angle right) {
    return right.greaterThan(left) ? right : left;
  }

  public static S1Angle min(S1Angle left, S1Angle right) {
    return right.greaterThan(left) ? left : right;
  }

  public static S1Angle radians(double radians) {
    return new S1Angle(radians);
  }

  public static S1Angle degrees(double degrees) {
    return new S1Angle(degrees * (Math.PI / 180));
  }

  public static S1Angle e5(long e5) {
    return degrees(e5 * 1e-5);
  }

  public static S1Angle e6(long e6) {
    // Multiplying by 1e-6 isn't quite as accurate as dividing by 1e6,
    // but it's about 10 times faster and more than accurate enough.
    return degrees(e6 * 1e-6);
  }

  public static S1Angle e7(long e7) {
    return degrees(e7 * 1e-7);
  }

  /**
   * Writes the angle in degrees with a "d" suffix, e.g. "17.3745d". By default
   * 6 digits are printed; this can be changed using setprecision(). Up to 17
   * digits are required to distinguish one angle from another.
   */
  @Override
  public String toString() {
    return degrees() + "d";
  }

  @Override
  public int compareTo(S1Angle that) {
    return this.radians < that.radians ? -1 : this.radians > that.radians ? 1 : 0;
  }
}