Further clarify geometric meaning of the river painting in rP11137 and r20429.
[0ad.git] / binaries / data / mods / public / globalscripts / vector.js
blob0f0f85926f93ebde4b486213682d512c1b88e7f6
1 /////////////////////////////////////////////////////////////////////
2 //      Vector2D
3 //
4 //      Class for representing and manipulating 2D vectors
5 //
6 /////////////////////////////////////////////////////////////////////
8 // TODO: Type errors if v not instanceof Vector classes
9 // TODO: Possibly implement in C++
11 function Vector2D(x, y)
13         if (arguments.length == 2)
14                 this.set(x, y);
15         else
16                 this.set(0, 0);
19 Vector2D.prototype.clone = function()
21         return new Vector2D(this.x, this.y);
24 // Mutating 2D functions
26 // These functions modify the current object,
27 // and always return this object to allow chaining
29 Vector2D.prototype.set = function(x, y)
31         this.x = x;
32         this.y = y;
33         return this;
36 Vector2D.prototype.add = function(v)
38         this.x += v.x;
39         this.y += v.y;
40         return this;
43 Vector2D.prototype.sub = function(v)
45         this.x -= v.x;
46         this.y -= v.y;
47         return this;
50 Vector2D.prototype.mult = function(f)
52         this.x *= f;
53         this.y *= f;
54         return this;
57 Vector2D.prototype.div = function(f)
59         this.x /= f;
60         this.y /= f;
61         return this;
64 Vector2D.prototype.normalize = function()
66         let magnitude = this.length();
67         if (!magnitude)
68                 return this;
70         return this.div(magnitude);
73 /**
74  * Rotate a radians anti-clockwise
75  */
76 Vector2D.prototype.rotate = function(a)
78         let sin = Math.sin(a);
79         let cos = Math.cos(a);
81         let x = this.x * cos + this.y * sin;
82         let y = this.y * cos - this.x * sin;
84         this.x = x;
85         this.y = y;
87         return this;
90 // Numeric 2D info functions (non-mutating)
92 // These methods serve to get numeric info on the vector, they don't modify the vector
94 /**
95  * Return the vector that forms a right angle with this one.
96  */
97 Vector2D.prototype.perpendicular = function()
99         return new Vector2D(-this.y, this.x);
103  * Computes the scalar product of the two vectors.
104  * Geometrically, this is the product of the length of the two vectors and the cosine of the angle between them.
105  * If the vectors are orthogonal, the product is zero.
106  */
107 Vector2D.prototype.dot = function(v)
109         return this.x * v.x + this.y * v.y;
113  * Computes the non-zero coordinate of the cross product of the two vectors.
114  * Geometrically, the cross of the vectors is the 3D vector perpendicular to the two 2D vectors.
115  * This returned length of that vector equals the area of the parallelogram that the vectors span.
116  */
117 Vector2D.prototype.cross = function(v)
119         return this.x * v.y - this.y * v.x;
122 Vector2D.prototype.lengthSquared = function()
124         return this.dot(this);
127 Vector2D.prototype.length = function()
129         return Math.sqrt(this.lengthSquared());
133  * Compare this length to the length of v,
134  * @return 0 if the lengths are equal
135  * @return 1 if this is longer than v
136  * @return -1 if this is shorter than v
137  * @return NaN if the vectors aren't comparable
138  */
139 Vector2D.prototype.compareLength = function(v)
141         return Math.sign(this.lengthSquared() - v.lengthSquared());
144 Vector2D.prototype.distanceToSquared = function(v)
146         return Math.euclidDistance2DSquared(this.x, this.y, v.x, v.y);
149 Vector2D.prototype.distanceTo = function(v)
151         return Math.euclidDistance2D(this.x, this.y, v.x, v.y);
154 // Static 2D functions
156 // Static functions that return a new vector object.
157 // Note that object creation is slow in JS, so use them only when necessary
159 Vector2D.from3D = function(v)
161         return new Vector2D(v.x, v.z);
164 Vector2D.add = function(v1, v2)
166         return new Vector2D(v1.x + v2.x, v1.y + v2.y);
169 Vector2D.sub = function(v1, v2)
171         return new Vector2D(v1.x - v2.x, v1.y - v2.y);
174 Vector2D.mult = function(v, f)
176         return new Vector2D(v.x * f, v.y * f);
179 Vector2D.div = function(v, f)
181         return new Vector2D(v.x / f, v.y / f);
184 Vector2D.avg = function(vectorList)
186         return Vector2D.sum(vectorList).div(vectorList.length);
189 Vector2D.sum = function(vectorList)
191         var sum = new Vector2D();
192         vectorList.forEach(v => sum.add(v));
193         return sum;
196 /////////////////////////////////////////////////////////////////////
197 //      Vector3D
199 //      Class for representing and manipulating 3D vectors
201 /////////////////////////////////////////////////////////////////////
203 function Vector3D(x, y, z)
205         if (arguments.length == 3)
206                 this.set(x, y, z);
207         else
208                 this.set(0, 0, 0);
211 Vector3D.prototype.clone = function()
213         return new Vector3D(this.x, this.y, this.z);
216 // Mutating 3D functions
218 // These functions modify the current object,
219 // and always return this object to allow chaining
221 Vector3D.prototype.set = function(x, y, z)
223         this.x = x;
224         this.y = y;
225         this.z = z;
226         return this;
229 Vector3D.prototype.add = function(v)
231         this.x += v.x;
232         this.y += v.y;
233         this.z += v.z;
234         return this;
237 Vector3D.prototype.sub = function(v)
239         this.x -= v.x;
240         this.y -= v.y;
241         this.z -= v.z;
242         return this;
245 Vector3D.prototype.mult = function(f)
247         this.x *= f;
248         this.y *= f;
249         this.z *= f;
250         return this;
253 Vector3D.prototype.div = function(f)
255         this.x /= f;
256         this.y /= f;
257         this.z /= f;
258         return this;
261 Vector3D.prototype.normalize = function()
263         let magnitude = this.length();
264         if (!magnitude)
265                 return this;
267         return this.div(magnitude);
270 // Numeric 3D info functions (non-mutating)
272 // These methods serve to get numeric info on the vector, they don't modify the vector
274 Vector3D.prototype.dot = function(v)
276         return this.x * v.x + this.y * v.y + this.z * v.z;
280  * Returns a vector perpendicular to the two given vectors.
281  * The length of the returned vector corresponds to the area of the parallelogram with the vectors for sides.
282  */
283 Vector3D.prototype.cross = function(v)
285         return new Vector3D(
286                 this.y * v.z - this.z * v.y,
287                 this.z * v.x - this.x * v.z,
288                 this.x * v.y - this.y * v.x);
291 Vector3D.prototype.lengthSquared = function()
293         return this.dot(this);
296 Vector3D.prototype.length = function()
298         return Math.sqrt(this.lengthSquared());
302  * Compare this length to the length of v,
303  * @return 0 if the lengths are equal
304  * @return 1 if this is longer than v
305  * @return -1 if this is shorter than v
306  * @return NaN if the vectors aren't comparable
307  */
308 Vector3D.prototype.compareLength = function(v)
310         return Math.sign(this.lengthSquared() - v.lengthSquared());
313 Vector3D.prototype.distanceToSquared = function(v)
315         return Math.euclidDistance3DSquared(this.x, this.y, this.z, v.x, v.y, v.z);
318 Vector3D.prototype.distanceTo = function(v)
320         return Math.euclidDistance3D(this.x, this.y, this.z, v.x, v.y, v.z);
323 Vector3D.prototype.horizDistanceToSquared = function(v)
325         return Math.euclidDistance2DSquared(this.x, this.z, v.x, v.z);
328 Vector3D.prototype.horizDistanceTo = function(v)
330         return Math.sqrt(this.horizDistanceToSquared(v));
333 // Static 3D functions
335 // Static functions that return a new vector object.
336 // Note that object creation is slow in JS, so use them only when really necessary
338 Vector3D.add = function(v1, v2)
340         return new Vector3D(v1.x + v2.x, v1.y + v2.y, v1.z + v2.z);
343 Vector3D.sub = function(v1, v2)
345         return new Vector3D(v1.x - v2.x, v1.y - v2.y, v1.z - v2.z);
348 Vector3D.mult = function(v, f)
350         return new Vector3D(v.x * f, v.y * f, v.z * f);
353 Vector3D.div = function(v, f)
355         return new Vector3D(v.x / f, v.y / f, v.z / f);
359 // make the prototypes easily accessible to C++
360 const Vector2Dprototype = Vector2D.prototype;
361 const Vector3Dprototype = Vector3D.prototype;