-
Notifications
You must be signed in to change notification settings - Fork 0
/
Vector2D.java
143 lines (113 loc) · 3.39 KB
/
Vector2D.java
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
138
139
140
141
142
143
import java.lang.Math;
public class Vector2D {
public float [] v = new float[2];
public Vector2D() {
v[0] = v[1] = 0;
}
public Vector2D( float x, float y ) {
v[0] = x;
v[1] = y;
}
public Vector2D( Point2D P ) {
v[0] = P.p[0];
v[1] = P.p[1];
}
public void copy( float x, float y ) {
v[0] = x;
v[1] = y;
}
public void copy( Vector2D V ) {
v[0] = V.v[0];
v[1] = V.v[1];
}
public float x() { return v[0]; }
public float y() { return v[1]; }
public float lengthSquared() {
return x()*x() + y()*y();
}
public float length() {
return (float)Math.sqrt( lengthSquared() );
}
// The returned angle is in [0, 2*pi]
public float angle() {
return angle( 0 );
}
// The returned angle is in [lowerBound, lowerBound+2*pi]
public float angle(
float lowerBound // in radians
) {
float l = length();
if ( l <= 0 )
return lowerBound;
float angle = (float)Math.asin(y()/l);
// Now angle is in [-pi/2,pi/2]
if ( x() < 0 )
angle = (float)Math.PI - angle;
// Now angle is in [-pi/2,3*pi/2]
float TwoPi = (float)( 2*Math.PI );
float upperBound = lowerBound + TwoPi;
while ( angle > upperBound )
angle -= TwoPi;
while ( angle < lowerBound )
angle += TwoPi;
// Now angle is in [lowerBound, upperBound]
return angle;
}
public Vector2D negated() {
return new Vector2D(-x(),-y());
}
public Vector2D normalized() {
float l = length();
if ( l > 0 ) {
float k = 1/l; // scale factor
return new Vector2D(k*x(),k*y());
}
else return new Vector2D(x(),y());
}
// returns the dot-product of the given vectors
static public float dot( Vector2D a, Vector2D b ) {
return a.x()*b.x() + a.y()*b.y();
}
// returns the sum of the given vectors
static public Vector2D sum( Vector2D a, Vector2D b ) {
return new Vector2D( a.x()+b.x(), a.y()+b.y() );
}
// returns the difference of the given vectors
static public Vector2D diff( Vector2D a, Vector2D b ) {
return new Vector2D( a.x()-b.x(), a.y()-b.y() );
}
// returns the product of the given vector and scalar
static public Vector2D mult( Vector2D a, float b ) {
return new Vector2D( a.x()*b, a.y()*b );
}
// Computes the angle of rotation from v1 to v2 around the origin.
// The angle returned is in the interval [-pi,pi],
// where a positive angle corresponds to a counterclockwise rotation
// (assuming x+ right, y+ up).
static public float computeSignedAngle( Vector2D v1, Vector2D v2 ) {
//return Vector3D.computeSignedAngle(
// new Vector3D( v1.x(), v1.y(), 0 ),
// new Vector3D( v2.x(), v2.y(), 0 ),
// new Vector3D( 0, 0, 1 )
//);
float productOfLengths = v1.length() * v2.length();
if ( productOfLengths <= 0 )
return 0;
// Compute the z component of the cross product of v1 and v2
// (Note that the x and y components of the cross product are zero,
// because the z components of a and b are both zero)
double crossProduct_z = v1.x()*v2.y() - v1.y()*v2.x();
double sineOfAngle = Math.abs(crossProduct_z) / productOfLengths;
// Due to numerical inaccuracies, the sine we computed
// may be slightly more than 1.
// Calling arcsin on such a value could be bad, so we don't.
double angle = ( sineOfAngle >= 1 ) ? Math.PI/2 : Math.asin( sineOfAngle );
// Compute the dot product of v1 and v2
float dotProduct = Vector2D.dot( v1, v2 );
if ( dotProduct < 0 )
angle = Math.PI - angle;
if ( crossProduct_z < 0 )
angle = - angle;
return (float)angle;
}
}