forked from bonder/jarm
-
Notifications
You must be signed in to change notification settings - Fork 0
/
vector.js
128 lines (109 loc) · 2.81 KB
/
vector.js
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
// TODO: Convert methods so that they accept either 1 argument which is a vector,
// or 2 arguments that are x/y coordinates
function Vector(x, y){
this.x = x;
this.y = y;
}
Vector.intersectRect = function(v1, v2, x, y, width, height){
var left, right;
if (v1.x < v2.x){
left = v1;
right = v2;
}else{
left = v2;
right = v1;
}
if (v1.inRect(x, y, width, height) || v2.inRect(x, y, width, height)){
return true;
}else if (v1.x == v2.x){
if (width == 0){
return v1.x == x;
}
var intersectY = (-height / width) * (v1.x - x) + y;
return intersectY >= Math.min(v1.y, v2.y) && intersectY <= Math.max(v1.y, v2.y);
}else if (width == 0){
var intersectY = ((left.y - right.y) / (left.x - left.y)) * (x - v1.x) + v1.y;
return intersectY >= y && intersectY <= y + height;
}else{
var m1 = (right.y - left.y) / (right.x - left.x);
var m2 = -height / width;
if (m1 == m2){
return left.y - m1 * left.x == y - m2 * x;
}else{
var intersectX = (left.y - y + m2 * x - m1 * left.x) / (m1 - m2);
return intersectX >= left.x && intersectX <= right.x &&
intersectX >= x && intersectX <= x + width;
}
}
}
Vector.prototype.times = function(v){
return new Vector(this.x * v, this.y * v);
}
Vector.prototype.norm = function(){
return Math.sqrt(this.x * this.x + this.y * this.y);
}
Vector.prototype.normSq = function(){
return this.x * this.x + this.y * this.y;
}
Vector.prototype.dot = function(v){
return this.x * v.x + this.y * v.y;
}
Vector.prototype.plus = function(x, y){
if (y === undefined){
y = x.y;
x = x.x;
}
return new Vector(this.x + x, this.y + y);
}
Vector.prototype.minus = function(v){
return new Vector(this.x - v.x, this.y - v.y);
}
Vector.prototype.translate = function(x, y){
if (y === undefined){
this.x += x.x;
this.y += x.y;
}else{
this.x += x;
this.y += y;
}
return this;
}
Vector.prototype.unit = function(){
if (this.x == this.y && this.x == 0)
return new Vector(0, 0);
return this.times(1 / this.norm());
}
Vector.prototype.zero = function(){
this.x = this.y = 0;
return this;
}
/**
* Clip a vector to be within a certain width/height.
* Negative values are set to zero.
*/
Vector.prototype.clip = function(width, height){
if (height === undefined){
height = width;
}
if (this.x < 0){
this.x = 0;
}else if(this.x > width){
this.x = width;
}
if (this.y < 0){
this.y = 0;
}else if(this.y > height){
this.y = height;
}
return this;
}
Vector.prototype.isZero = function(){
return this.x == 0 && this.y == 0;
}
Vector.prototype.clone = function(){
return new Vector(this.x, this.y);
}
Vector.prototype.inRect = function(x, y, width, height){
return this.x > x && this.x < x + width &&
this.y > y && this.y < y + height;
}