Related
There are two points lastPoint and prePoint. They determine a line.
I try to calculate slope of this line using this:
let kbase = (lastPoint.Y - prePoint.Y) / (lastPoint.X - prePoint.X);
let bbase = lastPoint.Y - kbase * lastPoint.X; //y = kx + b -> y - kx;
let ybase = `${kbase} * x + ${bbase}`;
So, if Y are equals then kbase is zero, it means straight line equation is y = b.
After that I try to calculate slope of perpendicular line to the first line, but I get error, because 1 / kbase where kbase == 0.
let kh = -1 * (1 / kbase);
let bh = startPoint.Y - kh * startPoint.X;
let yh = `${kh} * x + ${bh}`;
How to find a slope of perpendicular line if line equation is y = b?
The explicit form of a line equation, y = mx + p does not allow to represent verticals, as the slope is infinite.
For your purposes, you can use the implicit form, ax + by + c = 0, which does not have this problem. An orthogonal line can be given the equation bx - ay + d = 0.
As others have said, the slope of a vertical line is undefined. This is just how it works mathematically, and there are no problems with your code, and your math is correct. As you have realized, a horizontal line is a function that follows the form y = ox+b and its slope is 0. The perpendicular line of a horizontal line results in a vertical line which is not a function. This means that there are several values of y that correspond to one value you of x. Here is why that is important.
The general way of calculating slop is the change in y over the change in x.
Because a vertical line is not a function, there are multiple y's for one x. Here is an example. Let's say that we had the equation x=5. Here are some points: (5,1),(5,2),(5,3)(5,7). If you calculated slope with the first two points, it would result in (2-1)/(5-5) which is 1/0, and if you calculated slope with the last two points,
it would result in (7-3)/(5-5) which is 4/0. If you continued to do this, you would have an infinite number of undefined values for the slope of a vertical line. Keep in mind that 1/0 does not necessarily equal 2/0 or 6/0.Even if you tried to find a horizontal line and take the inverse reciprocal, which you did, you would not be able to find a defined value.
For example, if slope is the change in y over the change in x, then the inverse reciprocal would be -1 * the change in x over the change in y. Let's say that we had the horizontal line y = 0x + 5. The coefficient of the x or slope is 0. Four points would be (5,5), (9,5), (3,5) (6,5), and the two slope calculations for the slope of the perpendicular line would be 4/0 and 3/0 which leads to the same situation as last time.
To conclude, the answer to your question "How to find a slope of perpendicular line if line equation is y = b?" is that there is no defined value for the slope of a perpendicular line, and you definitely wont find one through the code you are using.
What I'm attempting to do
Loop through two axes and generating a shape with a width and height, either less or equal to the length of the nested for-loops, and calculate the distance from all positions to the center of that shape.
Main Issue(s)
How do I specify the width and height of an ellipse shape to draw using a nested for-loop with different dimensions to that ellipse?
For example a nested for-loop which goes for 0 to 45 in the X axis, and 0 to 100 in the Y axis but draws an ellipse with a width of 39 and a height of 90 - with the remaining difference used as padding (3 on either side, and 5 on top and bottom).
I have this half working using the EdgeOrInBounds function below, however I'm having trouble understanding why the values I'm using are giving the results they are.
Using a nested for-loop the same as above, but specifying an ellipse with a width of 30 and a height of 70 doesn't have the expected padding, it instead draws an ellipse with only one extra sprite surrounding all sides.
How do I calculate the distance from the center of the ellipse to the positions generated by the nested for-loop as a value between zero and one?
For example, any position outside the ellipse returns a value of zero and any position within the ellipse returns the distance scaled between zero and one from the center of the ellipse.
Similar to above, I have this half working as I can return a value of zero for all posiitons outside of the ellipse, but I do not understand how scale the distances for positions within the ellipse.
Bonus Issue(s)
I'm doing this on a platform where code isn't easily shareable and there are few built in functions, so I've had to create my own versions stolen from based on examples from the Nvidia developer site.
I have a basic understanding of some C# and JavaScript, but zero understanding of mathematical formulas.
Ellipse Function(s)
bool EdgeOrInBounds (Vector2 position) {
int x = ((int) Math.Pow (position.x - center.x, 2) / (int) Math.Pow (radius.x, 2));
int y = ((int) Math.Pow (position.y - center.y, 2) / (int) Math.Pow (radius.y, 2));
return (x + y <= 1);
}
Distance Function(s)
float distance (Vector2 position) {
return (sqrt (dot (centerPosition - position, centerPosition - position));
}
float dot (Vector2 a, Vector2 b) {
return (a.x * b.x + a.y * b.y);
}
float sqrt (float a) {
return (1.0 / pow (a, -0.5));
}
Variables
int mapWidth = 45;
int mapHeight = 100;
Vector2 radius = new Vector2 (mapWidth - 8, mapHeight - 4);
Vector2 center = new Vector2 (mapWidth / 2, mapHeight / 2);
Nested For Loops
for (int x = 0; x < width; x ++) {
for (int y = 0; y < height; y ++) {
// Store current position to reference in a minute
Vector2 position = new Vector2 (x, y);
// Check if position is within bounds or lies on the edge of the ellipse
if (EdgeOrInBounds (position)) {
// Calculate distance from center to current position
float dist = distance (position);
}
}
}
Example Image:
Closing Remarks
I know I haven't done a good job of explaining what I'm tring to achieve, so I'd like to apologize in advance, and I'd also like to thank anyone who reads this as any help would be very much appreciated.
Cheers.
To get color shade better under control, you could use an elliptic spiral, instead of a square grid traverse. Start out with the two radii, use X=R1 * Cos(angle) and Y=R2 * Sin(angle), where you gradually decrease R1 and R2 to zero. Your loop will use polar coordinates (angle,r), see below. You are then sure of the size of your "plot" and you won't need to test distances underways. It can probably do without any distance function for color scaling, but I'm not sure how to do that properly.. I have included a few options.
// The image is 440x240, I want ellipse in the center, margins 20 pix
// Parameters, dependent on size and shape of elllipse
Point pc = new Point(220,120); // pixel center
double r1=200; // radius 1 margin 2x20 on 440
double r2=100; // radius 2 margin 2x20 on 240
// Covering all pixels
int rmax = (int)Math.Max(r1,r2);
// scaling for color
var ravgmax = (r1+r2)/2.0;
// Find suitable loop counts
var nr = rmax; // number of radius steps in loop
var nh = 2*nr*Math.PI); // number of angles in loop
// Prepare initial loop displacements
var h=0.0;
var dr1 = r1/(nr*nh);
var dr2 = r2/(nr*nh);
var dh=(Math.PI*2.0)/nh;
// The loop
for (int i=0; i<nr; i++)
{
for (int j=0; j<(int)nh; j++)
{
var p = new PointF((float)(pc.X+r1*Math.Cos(h)),(float)(pc.Y+r2*Math.Sin(h)));
// vanilla shading
// int grayscale = 255 - (int)(255 * ((r1+r2)/2.0)/ravgmax );
// elliptical option without using distance, scale along axes
// grayscale = 255 - (int)(Math.Abs(p.X-pc.X)*255/200+Math.Abs((p.Y-pc.Y)*255/100)/2;
// "Distance grayscale" which is circular, not elliptical
int grayscale = (int)(255 * floatFDistance(p,pc)/rmax);
PlotF(p,grayscale); // you provide: plotpixel(PointF, int)
r1-=dr1; r2-=dr2;
h+=dh;
}
}
}
float floatFDistance(PointF p1, PointF p2)
{
double d1 = (p1.X - p2.X);
double d2 = (p1.Y - p2.Y);
return (float)(Math.Sqrt(d1 * d1 + d2 * d2));
}
I want to apply a forward force in relation to the object's local axis, but the engine I'm using only allows to me apply a force over the global axis.
I have access to the object's global rotation as a quaternion. I'm not familiar with using quats however (generally untrained in advanced maths). Is that sufficient information to offset the applied force along the desired axis? How?
For example, to move forward globally I would do:
this.entity.rigidbody.applyForce(0, 0, 5);
but to keep that force applied along the object's local axis, I need to distribute the applied force in a different way along the axes, based on the object's rotational quat, for example:
w:0.5785385966300964
x:0
y:-0.815654993057251
z:0
I've researched quaternions trying to figure this out, but watching a video on what they are and why they're used hasn't helped me figure out how to actually work with them to even begin to figure out how to apply the offset needed here.
What I've tried so far was sort of a guess on how to do it, but it's wrong:
Math.degrees = function(radians) {
return radians * 180 / Math.PI;
};
//converted this from a python func on wikipedia,
//not sure if it's working properly or not
function convertQuatToEuler(w, x, y, z){
ysqr = y * y;
t0 = 2 * (w * x + y * z);
t1 = 1 - 2 * (x * x + ysqr);
X = Math.degrees(Math.atan2(t0, t1));
t2 = 2 * (w * y - z * x);
t2 = (t2 >= 1) ? 1 : t2;
t2 = (t2 < -1) ? -1 : t2;
Y = Math.degrees(Math.asin(t2));
t3 = 2 * (w * z + x * y);
t4 = 1 - 2 * (ysqr + z * z);
Z = Math.degrees(Math.atan2(t3, t4));
console.log('converted', {w, x, y, z}, 'to', {X, Y, Z});
return {X, Y, Z};
}
function applyGlobalShift(x, y, z, quat) {
var euler = convertQuatToEuler(quat.w, quat.x, quat.y, quat.z);
x = x - euler.X; // total guess
y = y - euler.Y; // total guess
z = z - euler.Z; // total guess
console.log('converted', quat, 'to', [x, y, z]);
return [x, y, z];
}
// represents the entity's current local rotation in space
var quat = {
w:0.6310858726501465,
x:0,
y:-0.7757129669189453,
z:0
}
console.log(applyGlobalShift(-5, 0, 0, quat));
Don't laugh at my terrible guess at how to calculate the offset :P I knew it was not even close but I'm really bad at math
Quaternions are used as a replacement for euler angles. Your approach, thus, defeats their purpose. Instead of trying to use euler angles, levy the properties of a quaternion.
A quaternion has 4 components, 3 vector components and a scalar component.
q = x*i + y*j + z*k + w
A quaternion therefore has a vector part x*i + y*j + z*k and a scalar part w. A vector is thus a quaternion with a zero scalar or real component.
It is important to note that a vector multiplied by a quaternion is another vector. This can be easily proved by using the rules of multiplication of quaternion basis elements (left as an exercise for the reader).
The inverse of a quaternion is simply its conjugate divided by its magnitude. The conjugate of a quaternion w + (x*i + y*j + z*k) is simply w - (x*i + y*j + z*k), and its magnitude is sqrt(x*x + y*y + z*z + w*w).
A rotation of a vector is simply the vector obtained by rotating that vector through an angle about an axis. Rotation quaternions represent such an angle-axis rotation as shown here.
A vector v can be rotated about the axis and through the angle represented by a rotation quaternion q by conjugating v by q. In other words,
v' = q * v * inverse(q)
Where v' is the rotated vector and q * v * inverse(q) is the conjugation operation.
Since the quaternion represents a rotation, it can be reasonably assumed that its magnitude is one, making inverse(q) = q* where q* is the conjugate of q.
On separating q into real part s and vector part u and simplifying the quaternion operation (as beautifully shown here),
v' = 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
Where dot returns the dot product of two vectors, and cross returns the cross product of two vectors.
Putting the above into (pseudo)code,
function rotate(v: vector3, q: quaternion4) -> vector3 {
u = vector3(q.x, q.y, q.z)
s = q.w
return 2 * dot(u, v) * u + (s*s - dot(u, u)) * v + 2 * s * cross(u, v)
}
Now that we know how to rotate a vector with a quaternion, we can use the world (global) rotation quaternion to find the corresponding world direction (or axis) for a local direction by conjugating the local direction by the rotation quaternion.
The local forward axis is always given by 0*i + 0*j + 1*k. Therefore, to find the world forward axis for an object, you must conjugate the vector (0, 0, 1) with the world rotation quaternion.
Using the function defined above, the forward axis becomes
forward = rotate(vector3(0, 0, 1), rotationQuaternion)
Now that you have the world forward axis, a force applied along it will simply be a scalar multiple of the world forward axis.
I've been trying to solve this problem for a number of days now but I must be missing something.
Known Variables:
vi = Initial Velocity
t = Animation Duration
d = Distance.
end velocity should always be zero
The function I'm trying to create: D(0...t) = the current distance for a given time
Using this information I want to be able to create a smooth animation curve with varying velocity (ease-in/ease-out).
The animation must be able ease-in from an initial velocity.
The animation must be exactly t seconds and must be travel exactly d units.
The curve should lean towards the average velocity with acceleration occurring at the beginning and the end portions of the curve.
I'm open to extra configuration variables.
The best I've been able to come up with is something that doesn't factor in the initial velocity. I'm hoping someone smarter can help me out. ;)
Thank you!
p.s. I'm working with an ECMAScript variant
Here is a different solution, where there isn't any time interval where the velocity is constant. Instead, velocity as a function of time is a second-order polynomial, and the acceleration is linear in time (positive at the beginning, and negative at the end). Maybe you can try it.
Let me rename your variables a bit. Let
T = final time = animation duration
V = initial velocity (>0)
D = total distance (>0)
We are searching for a smooth function v(t) (velocity as a function of time) such that:
v(0) = V
v(T) = 0
the integral from 0 to T of v(t)dt is D
With a (concave) second-order polynomial we can satisfy all the three constraints. Hence, let
v(t) := at^2 + bt + c
and let's solve for a, b, c. The first constraint v(0) = V gives immediately c = V.
The second constraint reads
aT^2 + bT + V = 0
On the other hand, the integral of v(t) is d(t) = 1/3 a t^3 + 1/2 b t^2 + Vt (this is the distance covered up to time t), hence the third constraint reads
d(T) = 1/3 a T^3 + 1/2 b T^2 + VT = D
The last two equations seem messy, but they are just two linear equations in the two unknowns a, b, and they should be easily solvable. If I did my computations correctly, the final result is
a = 3V/T^2 - 6D/T^3, b = 6D/T^2 - 4V/T
If you substitute a, b, c in the expression of d(t), you obtain the covered distance as a function of time.
I believe you want to solve your problem in 3 parts.
First, you need to solve for the minimum velocity necessary to complete the distance in time T.
This would be pretty simple (D/t) = v(min)
It assumes instantaneous acceleration from v(initial) to v(min) and again deceleration over a time period of 0s at the beginning and end.
so for example say your v(i) is 5px/s.
you want a 100px movement over 10 seconds.
v(min) = 100px/10s = 10px/s
Second, you want a smooth acceleration from v(initial) to v(min). this will take some period of time t(acc). Assuming the acceleration and deceleration will be equal, then you can just figure for one of them, then multiply by 2.
We can call the function that describes the distance travelled during accelleration D(accel).
Lets keep it easy to start and say we want the duration of accelleration to be 1s
so your equation for total distance travelled is going to be
D(total) = D(accel) + D(v(max) )
When you know that D(accel) is for 2s total, you can calculate
D(accel) = ( V(ini) + V(max) ) /2) * (2seconds)
and
D(v(max)) = V(max) * 8s
solving for V(max) we get
100px = D(accel) + D(v(max))
100px = ( 5px/s + VMax) /2 *(2s)) + VMax *8s
100px = 5px + (Vmax * 1s) + Vmax *8s
95px = 9Vmax *s
VMax = 95px/9s
VMax = 10.556px/s
You can now go back and replace your 1s acceleration window with a formula that defines the acceleration window as a % of the overall time period or some other thing.
Also note that for animation purposes, you will have to break 10.556px/s down into per frame px movements and account for time appropriately.
abustin, since you don't like the 3 segment solution, you may want to try looking at Bezier curves to solve this problem. Bezier curve can be utilized to interpolate time as well as distance, so you can define a few control points near the ends of your motion to generate acceleration, where the middle "segment" will be defined such that the velocity is close to constant. Utilizing splines is a possibility too.
Using constant accelerations:
Definitions:
Vi - Initial velocity
Va - Average velocity
Vo - Ending velocity
D - Total distance to be traveled
T - Total time for travel
t1 - Acceleration time from beginning to Va
t2 - Acceleration time from Va to Vo
The equation to solve is:
(Vi+Va)/2*t1 + Va*(T-t2-t1) + (Va+Vo)/2*t2 = D
You should decide how much time the initial acceleration (t1) and the final acceleration (t2) takes and then you are left with only one unknown -> Va, which can be easily solved.
EDIT: find the distance as a function of time:
Well, now that you know the velocities, it is easy to figure out the distance traveled:
D(t) = Vi*t + 0.5*t^2*(Va-Vi)/t1 {0<t<t1}
D(t) = Va*(t-t1) + D1 {t1<t<t3}
D(t) = Va*(t-t3)+0.5*(t-t3)^2*(Vo-Va)/t2 + D2 {t3<t<T}
where t3=(T-t2), D1 and D2 are the distance traveled at the end of the first and second segments, which can be found from the respective functions:
D1 = 0.5*(Va+Vi)*t1
D2 = D1 + Va*(t3-t1)
EDIT 2: Solving for Va:
(Vi+Va)/2*t1 + Va*(T-t2-t1) + (Va+Vo)/2*t2 = D
Remember that t1 and t2 are the problem parameters that you choose. You decide what fraction of the movement the object accelerates and decelerates. Let's say t1=t2=0.1*T. Substitution then gives:
(Vi+Va)/2*(0.1T) + Va*(T-(0.1T)-(0.1T)) + (Va+Vo)/2*(0.1T) = D
Va*(0.1T/2 + T-0.1T-0.1T + 0.1T/2) + Vi*(0.1T)/2 + Vo*(0.1T)/2 = D
Va*(0.9T) + Vi*(0.05T) + Vo*(0.05T) = D
Va*(0.9T) = D - Vi*(0.05T) + Vo*(0.05T)
Va = (D - (Vi + Vo)*(0.05T)) / (0.9T)
Got it?
Federico's solution is a nice one, but I found the acceleration of a linear acceleration solution a bit too abrupt, and I ended up forging ahead with a double parabola solution where the acceleration is constant, first in one direction and then in the other, until the object ends at 1 with a velocity 0. (I did try solving it with variable starts and ends, but it was too difficult. Instead, my implementation just scales the inputs and outputs before passing them through the function.)
The math was high school stuff, but I'll go over it for completeness' sake.
given v, the initial velocity, we have two parabolas, the left and the right
ly = m(t - ax)^2 + ay, where t is the time input, ranging from 0 to 1, and ax, ay, and m are constants we need to find, given v.
ry = -m(t - 1)^2 + 1
Note, they both take m as their steepness, because they accelerate at the same rate. ry uses -m because it accelerates in the other direction.
We have a number of constraints to solve for
ly(0) = 0, the value is 0 at t = 0
ly'(0) = v, the differential of the equation(the velocity) is v(the initial velocity, given) at t = 0
ly(h) = ry(h), the two parabolas connect at some given halfway point (which is not actually halfway unless v = 0)
ly'(h) = ry'(h), the velocity is the same at that halfway point, no sudden jerks
I went through a number of approaches from here on out, but in the end it seemed that the only way was to solve for m in terms of v. We arrive at the formula mm + m(v - 2) - (vv)/4. Applying the quadratic formula, we get m = ((2 - v) ± sqrt(2vv - 4v + 4))/2
Meaning that either
m = ((2 - v) + sqrt(2v*v - 4v + 4))/2
or
m = ((2 - v) - sqrt(2v*v - 4v + 4))/2
And we find that we can decide which it is by looking at the initial velocity,
let sqrt_part = Math.sqrt(2*sq(initial_velocity) - 4*initial_velocity + 4)
let m = (2 - initial_velocity + (initial_velocity < 2 ? sqrt_part : -sqrt_part))/2
from there, the rest of the variables (ax, ay and h) are quite easy to work out.
There is a rust implementation of the formulai here https://gist.github.com/makoConstruct/df173c3a4e0854b535869fdc2acdeeb1
Rust's syntax is pretty ordinary, so you wont have much trouble translating that to JS. Feel free to post your port in the comments.
I want to ask about efficient algorithm.
Example i have equation :
x = y + z;
if the value of variable y = 1, variable z = 2 so variable x is 3
But how to get value of y automatically if variable x = 3 and variable z = 2 with that equation? without create new equation y = x - z
I hope can get sample code using C# or javascript.
Another example, if the equation is
a = (((x + y - z)/2)*10)^4
The equation is from program, user submit value of 3 varibles.
User submit variable (x, y, z) or (y, z, a) or (z, a, x) or (a, x, y)
if user input value for var x, y and z, program can displaying value of a with that equation. Without create a = ...
if user input value for var y, z and a, program can displaying value of x with that equation. Without create x = ...
if user input value for var z, a and x, program can displaying value of y with that equation. Without create y = ...
if user input value for var a, x and y, program can displaying value of z with that equation. Without create z = ...
What you are looking for is an 'equation solver'. This is non-trivial and there is quite a bit of research on this and some well-known large mathematical software do this.
For more details, please google 'Algorithms for Computer Algebra'.
You have to resolve the equations with respect to the unknown variable:
x = y + z;
is equivalent to
y = x - z;
and
z = x - y;
For the second equation it is more difficult. If a < 0 there will be no solution. Otherwise you can first take the 4th root:
a = (((x + y - z)/2)*10)^4 <=> sqrt(sqrt(a)) = +/- (x + y + z) * 5
Then resolve it with respect to x, y or z. Note that you will get two solutions in general.
There are programs and libraries that can do these calculations automatically: Check for "symbolic math" or "computer algebra systems".
i sense a deep research of math on that problem you present, you can serach on google about equation algorithm solve that a link of wikipedia
Yes in case you have a simple workflow of some basic algorithm to find a variable
let us suppose this environment;
since there are always going to be three variables, you can valid that only one of the three is null and then select the equation of the variable you want to find if non are null then you send a message that no value are null
The original equation is x=y+z-a
x=5; y=7; z=2; a=null;
If (!x.hasValue ()){
x= y + z - a;
}
....
Else if (!a.hasValue ()){
a = -(x + y + a);
}Else{Console.Write("Don't give value to all variable");}
This isn't how it works. In programming languages you don't really have equations but rather assignments. You can assign a right-side value to the variable on the left side.
So the only way to obtain y, when having x and z is by running
y = x - z
EDIT: you may want to create something like
myFunction(double? x=null, double? y=null, double? z=null, double? a=null)
And then inside you check which variable is null (so not used), and perform your calculations accordingly. You would run it like this
var something = myFunction(x: 1, y: 2, a: 3)
If you don't want to write a new line of code and get the result of 'y' when 'x' is diferent to zero within the same equation, try this ...
// equation : x = y + z
var x=3,y=0,z=2;
x = ((x!=0) ? (x-z) : y ) + z;
console.log("Result : "+ x);
// or saving the value in 'y'
x = ((x!=0) ? y = (x-z) : y ) + z;
console.log("Result 2 : "+ x);
Answering the first question:
Y = X - Z
is the only possible solution. There aren't other ways to calculate Y.
This because computers can't solve equations (or better, they can be programmed to solve them, but only using 'Y = X - Z') , they can change the value of a variable. In this case we set the Y value to (X - Z) value.
Answering the second question:
You can solve that equation doing
X = fourth square of (...)
or you can use libraries that do all this work by themselves, like 'computer algebra system' (Also cited by #FrankPuffer)
Definitely: you can solve the equations doing inverse operation, like 'Y = X - Z', or by using libraries that simplify writing code.