I wanted to make a reflection algorithm that avoided the sqrt function, and this is what I came up with:
Vector3D.prototype.reflectOver = function(vectorToReflectOver){ //return a reflected vector
var t = (vectorToReflectOver.dot(vectorToReflectOver))/(this.dot(vectorToReflectOver));
var reflectedVector = vectorToReflectOver.multiply(2).subtract(this.multiply(t));
return reflectedVector;
}
The reasoning behind it is that if we want to reflect a vector V_1 over another vector V_2, we want to find a vector V_3 such that V_2 + V_3 is the reflection vector. First we must find the vector t*V_1 such that t*V_1 - V_2 = V_3. This is what t is in the function. Any ideas?
Just to be clear, the dot function refers to a dot product, multiply multiplies a scalar to a vector, subtract subtracts two vectors. The function is called like so, v.reflectOver(n), where v and n are two vectors. Furthermore, this doesn't throw an error. This is a performance error, not a compiler or runtime error.
It's a little hard to say where you went wrong, but if you draw it out on paper, you should get something like this:
this.project_onto(other.as_unit_vector()).multiply(2).subtract(this)
Related
I am working on a program for a task in Linear Algebra that performs computations on vectors and matrices of floating point numbers.
i.e.,
v = [3.14159, 2.256, 1.5783, 6.782]
A = [ 9.7 2.333 5.467 5.2123
6.789 4.789 5.671 9.111
1.113 4.562 8.223 5.2125
6.666 7.8181 3.426 4.3567]
A part of the program performs the same operations on an input vector as it does on a specified row of an input matrix, handled by a function in C++. In C++, the same function can accept input of either a vector or matrix by having it accept a pointer to a specific array element; as long as the pointer arithmetic is meticulous and, knowing memory layout is row-major, it works. I am wondering if the same can be done in JavaScript.
I could write either of two functions:
i) A function that expects a vector.
Passing the vector in works.
However, passing in the matrix doesn't work.
I had hoped to pass in the pointer to, say, the first element in the second row (the element containing 6.789). Then to access the entire row by something like A[0][i]. But JavaScript doesn't like that.
ii) A function that expects a matrix.
Passing the matrix in works.
However, passing in the vector doesn't work. If I try to access the vector elements as v[0][i], JavaScript doesn't like that.
Either my syntax is incorrect, or I am trying to do something that cannot be done.
The vector and array cannot be changed in form (i.e., flattened, etc.) because the rest of the program needs them to keep their forms; the vector needs to remain a vector and the matrix needs to remain a matrix.
In JavaScript, is it possible to pass a pointer to a specific array element into a function and then, within the function, have the vector (or row of matrix) treated as just a regular array?
If not, is there a suggested work-around?
Does this do what you're after?
function doSomethingWithVectorOrMatrixRow(vectorOrMatrix, matrixRow) {
const aVector = matrixRow === undefined ? vectorOrMatrix : vectorOrMatrix[matrixRow];
return doSomething(aVector);
}
/* Use it as */ doSomethingWithVectorOrMatrixRow(v);
/* or */ doSomethingWithVectorOrMatrixRow(A, 1);
Although of course it would be more efficient to store a matrix as a flat Array, and simply operate on a given range of that Array, which would work equally well for a vector (range = whole vector), but you say you can't change the data structure used.
Whatever it is I'm doing, I don't know what it's called, but I need help because I know it can be done with math. This is for a simulation I'm building, and the role it plays is very difficult to explain, but it has something to do with defining the properties of an object.
Here is my JavaScript: https://jsfiddle.net/vdocnmzu/
DM.prototype.get = function(coords){
var dist;
val = 0;
for(var j,i = 0; i < this.distortions.length; i += 1){
dist = 0;
for(j = 0; j < coords.length; j += 1){
dist += Math.pow( coords[j] - this.distortions[i].coords[j], 2);
}
dist = Math.pow(dist,.5);
if( dist <= this.distortions[i].range){
val += Math.cos( (dist/this.distortions[i].range) * Math.PI/2 ) * this.distortions[i].amp;//;
}
}
return val;
}
What's happening is this: I have this 3D cube, where I can pick x & y, and get Z(the grayscale pixel color). In this sample code, I'm picking a grid of points across the entire x,y plane of the cube. The "bubbles" you see (you may need to refresh a few times) are multiple points being picked and creating that image.
What I'm trying to do is not have bubbles, but rather, organic flows between bubbles.
Right now, the z value comes from these "distortion points" that each of these 3DCubes have. It can have any amount of these points.
These "distortion points" don't have to be points. They can be sets of points, or lines, or any type of base geometry to define the skeleton of some type of distance function.
I think that distance function is what I'm struggling with, because I only know how to do it with points. I feel like lines would still be too rigid. What's the math associated with doing this with curves? Distance to a curve? Are there more approaches to this? If there's not a good single 1 to pick, it's okay to have a collection as well.
Your question is very complicated to understand. The overall feeling is that your expectations are too high. Some advanced math 101 might help (feel free to google buzzwords):
Defining a curve is an very hard problem that challenged the brightest mathematicians of the history. From the naive approach of the greeks, through the calculus of Newton and Leibniz, passing by Euler and Gauss, to the mathematical analysis of Weisstreiss, the word curve changed meaning several times. The accepted definition nowadays says that curves are continous functions in two variables, where continous is a very special word that has an exact meaning coined in the 19th century (naively is a function without jumps from one value to another). Togheter with the notion of continuity, came the notions of connected, compact, differentiable (and so on) curves, which defined new conditions for special curves. The subject developed to what is now known as topology and mathematical analysis.
Mathematicians usually uses definitions to reproduce a class of ideas that can be brought and thought togheter. To their surprise, the definition of continuity did include really weird functions to be curves: space-filling-curves, fractals!!! They called them monsters at the time.
After this introduction, lets go back to your question. You need a geometrical object to calculate distances from a point. Lets avoid weird curves and go from continous to differentiable. Now it's better. A (conected compact) differentiable function can be expanded in Taylor series, for example, which means that all functions of this class can be written as an infinite sum of polynomial functions. In two dimensions, you need to calculate matrices involved in this expansion (Calculus in many variables is a pre-requisite). Another step further is truncating this expansion in some degree, lets say 3. Then the general curve in this case is: ax + by + cx^2 + dy^2 + ex^3 + fy^3 + gx^2y + hxy^2 + ixy + j = 0 (ab...j are free parameters). Oh! This is reasonable, you might think. Well, actually there is a name for this kind of curve: algebraic curve of deggre 3. This is an active research theme of algebraic geometry, which is a very hard field even among mathematicians. Generally speaking, there are milestone theorems about the general behavior of those curves, which involves singularities and intersection points that are allowed in the general case.
In essence, what you are looking for does not exist, and is a very hard subject. Your algorithm works with points (really cool pictures by the way) and you should baby step it into a straight line. This step already requires you to think about how to calculate distance between a point and a straight line. This is another subject that was developed in general in the 19th century, togheter with mathematical analysis: metric spaces. The straightfoward answer to this question is defining the distance between a point and a line to be the smallest distance from the point to all line points. In this case, it can be shown that the distance is the modulus of the vector that connects the point to the line in a 90 degrees angle. But this is just one definition among infinte possible ones. To be considered a distance (like the one I just described and the euclidean distance) there is a set of axioms that needs to be verified. You can have hyperbolic metrics, discrete metrics, metrics that count words, letters, LotsOfFamousPeople metric spaces... the possibilities are infinite.
So, baby steps. Do it with straight lines and euclidean minimum distance metric. Play around with other metrics you find on google. Understand the axioms and make your own!!! Going to second degree polynomials is already a big challenge, as you have to understand everything that those curves can make (they can really do weird unexpect stuff) and define a distance to it (metric space).
Well thats it! Good luck with your project. Looks really cool!
Note: I have absolutely no clue about Vector math, especially not in 3D.
I am currently working on some Javascript code that determines if a Finger that got captured by a Leap Motion Controller is extended (i.e. completely straight) or not.
Leap Motion provides us with an API that gives us Object for Hands, Fingers and Bones. Bones in particular have several properties, such as position Vectors, direction Vectors and so on, see here for the Documentation.
My idea was to take the Distal Phalang (tip of your finger) and Proximal Phalang (first bone of your finger), calculate the angle between them by getting the dot product of the two direction Vectors of the bones and then decide if it is straight or not. Like this, essentially:
var a = hand.indexFinger.distal.direction();
var b = hand.indexFinger.proximal.direction();
var dot = Leap.vec3.dot(a,b);
var degree = Math.acos(dot)*180/Math.PI;
The issue here is that these values are not reliable, especially if other fingers move about. It seems like the direction Vectors of the bones change when other fingers change direction (???).
For example, when all my Fingers are extended, the value of degree is roughly 0 and fluctuates between -5 and 5. When I make a fist, the value shoots up to 10, 15, 20. Logging the values of the direction Vectors reveals that they indeed do get changed, but how does this make sense? The Finger doesn't move, so its direction should stay the same.
Even worse for the thumb, the values don't add up there at all. An extended thumb can get values similar to the IndexFinger, but rotation the thumb upwards or downwards has changes in the range of 60 degrees!
I've tried using positional values instead, which gives me NaN results because the values seem to be to big.
So, my question is: how could I reliably calculate the angle between two Vectors? What am I missing here?
The correct formula is
cos(angle) = dot(a,b)/(norm(a)*norm(b))
where norm is the euclidean norm or length.
You should have gotten a wrong result, but the lengths of a and b should be constant, so the result should have been consistently wrong…
dot product is the cosine of the angle between vectors if those vectors are normalized. So be sure that a and b are normalized prior to calculate the dot product
I've managed to get a function working which will calculate and return the angle between one point and another. I've called it the lookAt function, because it's basically causing one transform to look at another one. Here it is:
this.lookAt = function(target) {
var d = target.subtract(this.position)
this.rotation = Math.atan2(d.y, d.x) + Math.PI/2;
return this.rotation;
}
In this function's context, this refers to a surrounding object which has the variables rotation (a rotation in radians) and position, a Vector2 class which has a few basic math functions and stores x and y values. d is a Vector2 created by calling a helper function on the variable target, which subtracts one Vector2 from another.
This works as expected--if I call this function on an object, the rotation correctly "looks at" the target. However, I'd like to know why I had to add π / 2 (which is 1 radian, correct?). I got the original equation from this question, but the answer did not add π / 2 to the equation, whereas I have to.
Could somebody explain the math behind this? Also, I haven't gotten to that much trigonometry yet (besides what my Algebra course introduced me to), so please explain this as if you were talking to a very small child. :-)
I need help/advice for improving/commenting my current design please :)
This relates to collision detection in a simple game: Dynamic bodies (moving ones) might collide with static bodies (i.e. ground, walls). I'm porting my Obj-C model to Javascript and am facing memory/performance questions as to my way of implementing this.
I'm using a very basic approach: An array of arrays represents my level in terms of physic opacity.
bit set to 0: Transparent area, bodies can go through
bit set to 1: Opaque area, bodies collide
Testing the transparency/opacity of a pixel simply goes as follows:
if (grid[x][y]) {
// collide!
}
My knowledge of JS is pretty limited in termes of performance/memory and can't evaluate how good this approach is :) No idea of the efficiency of using arrays that being said.
Just imagine a 1000-pixel wide level that's 600px high. It's a small level but this already means an array containing 1000 arrays each containing up to 600 entries. Besides, I've not found a way to ensure I create a 1bit-sized element like low-level languages have.
Using the following, can I be sure an entry isn't something "else" than a bit?
grid[x][y] = true;
grid[x][y] = false;
Thanks for your time and comments/advices!
J.
If you have an 1000x600 grid, you can guarantee you have at least 601 arrays in memory (1001 if you do it the other way round).
Rather than doing this, I would consider using either 1 array, or (preferrably) one object with a mapping scheme.
var map = {};
map["1x1"] = 1;
map["1x3"] = 1;
// assume no-hits are empty and free to move through
function canGoIn(x, y) {
return map.hasOwnProperty(x + "x" + y);
};
Alternately;
var map = [];
var width = 600;
map.push(0);
map.push(1);
// etc
function canGoIn(x, y) {
return map[(x * width) + y] == 1;
}
a boolean value won't be stored as just one bit, and that is also true for any other language I know (C included).
If you are having memory issues, you should consider implementing a bitarray like this one: https://github.com/bramstein/bit-array/blob/master/lib/bit-array.js
You will have to make your 2d array into a simple vector and converting your x, y coordinates like this: offset = x + (y * width);
Browsing an array will still lead to a multiplication to evaluate the offset so using a vector is equivalent to arrays.
But I suspect that calling a function (in case your using a bit-array) and doing some evaluations inside will lead to poorer performances.
I don't think you can gain performances and save memory at the same time.