How to transform one numerical scale into another? - math

Let's say I have a numerical scale and I want to transform it into a different scale so that the relationship is proportional. For example, I have a scale from 2 to 6 and I want to transform it into another scale from 50 to 250, so that 4, which is the midpoint of the first scale, corresponds to 150, which is the midpoint of the second scale.
Does anyone know how this can be done mathematically for any two scales? What formula or equation must be applied to each element of the first scale to convert it into its corresponding of the second scale?
Thanks in advance.

You can transform it to [0,1] from [a,b] and then transform it to [c,d].
x in [a,b] => y = (x-a)/(b-a) in [0,1]
y in [0,1] => z = (d-c)*y + c in [c,d]
Hence x to z is:
x in [a,b] => z = (d-c) * (x-a) / (b-a) + c in [c,d]

Related

Scaling the X axis of a rotated ellipse

I have a scatter plot and I'm allowing points to be selected by drawing an ellipse like so:
In the above image the X axis and Y axis are scaled differently. I'm trying to implement functionality to allow the scale of each axis to be changed, but I'm having trouble scaling the ellipse shape with the axis. Changing the scale of the X axis to match the Y axis gives this:
I know I can scale the cx value of the ellipse with the X axis to get the new centre of the ellipse, but I don't know how to work out the new rx, ry and rotation angle. So my question is given a rotated ellipse with values cx, cy, rx, ry and rotation in radians, how do I calculate the new values for the ellipse given a scale value s for either the X axis or Y Axis? For clarity the rotation is done about the centre (cx, cy) of the ellipse.
I think I understand your problem. For an axis-aligned ellipse with points (x,y), the shape of (a*x,b*y) is still an ellipse with some arbitrary scaling factors a and b acting on the major and minor radii.
But for a rotated ellipse this is not true. In addition to the major and minor radii scaling differently, the rotation angle might differ also.
So mathematically the problem is as such: The parametric points of a rotated ellipse are
with θ the rotation angle r_1 and r_2 the original ellipse radii. The parameter t goes from 0 to 2π.
Now to find the modified parameters such that the ellipse matches a scaled version of the above
The above two are combined into one equation to be solved for r_1' and r_2' as well as θ' for all values of t.
Unfortunately, there is no solution that I can think of, because the combined 2×2 matrix on the RHS in front of the vector needs to be diagonalized by finding the appropriate rotation θ' to bring it down to this form
which is trivially solved for r_1' and r_2'.
But the rotation needs to satisfy two contradictory equations
tan(θ') = (a/b)*tan(θ) and tan(θ') = (b/a)*tan(θ)
which can only be solved if the two scaling factors are identical => a==b.
I suggest posting this problem into the [Mathematics.SE] as math problem, before trying to implement it as an algorithm. Maybe you will have better luck.
The computation is not that easy.
The equation of a rotated ellipse centered at the origin is
(c x + s y)² / a² + (s x - c y)² / b² = 1 = A x² + 2B xy + C y²
(c, s denote the cosine and sine of the rotation angle.) After development, the quadratic coefficients are
A = c² / a² + s² / b², 2B = 2 cs / a² - 2 sc / b², C = s² / a² + c² / b².
When you have the coefficients, you can retrieve 1/a², 1/b², c, s as the Eigenvalues and first Eigen vector of the 2x2 matrix
|A B|
|B C|
and the rotation angle is given by tan Θ = s / c.
Now let us stretch the abscissas by applying a coefficient r, giving
A' = r² A, B' = r B, C' = C.
The matrix becomes
|r²A rB|
|rB C|
and again, you will find the axis and cosine/sine of the angle by computing the Eigenvalues and first Eigenvector.
The Eigenvalues are roots of the polynomial
z² + (r²A + C) z + r²(AC - B²)
where A, B, C are computed as above, and the Eigenvector follows
(r²A - z) c + rB s = 0
from which you draw s/c.

What is the Correct Way to Scale then Rotate a set of Points?

I have 4 points, point A(x1, y1), point B(x2, y1), and point C(x2, y2), point D(x2, y3) creating two scales: Scale1 yRange(B, D), Scale2 yRange(B, C).
I want to scale the y axis only, so that point D is scaled down to point C, so that the angle between CAB is a certain degree. Then I want to rotate the scaled point C around point B a certain degree, obtaining point E. Then I want to find the real value of point E on the un-scaled coordinate grid where original point D is located. I think I need to use affine transformations, but all examples are rotate first, then scale. But I need to scale first, then rotate. How do I find this new value? I know how to perform rotations alone and a bit of scaling alone, but not together.
Maybe I am confused, after I perform the scaling and rotation, I would not need to scale back, because the new value of E equates to F? I know there are plenty of examples, but I can not wrap my head around this...
Here is my objective. I have the 3 points A, B and D. I want to scale so that DAB equates to let's say 60 degrees, creating point C, then perform several point rotations on C inside the scaled grid. I ultimately want to find the value of F, and the other rotated points, which lies in geometrical positions inside the original unscaled grid that I can not calculate unless I scale the 3 original points to said degree first. The scaled grid contains the correct ratio I need in order to rotate my points. I need to do all my rotations inside the scaled grid, without losing values, but changing aspect ratio, and then take those new points inside the scaled grid and plot them in the unscaled grid, which will then lose correct aspect ratios, which is fine.
Coding in python.
Here's a Python3 program that I think does what you want:
import math
# Use a negative angle since we're rotating clockwise
rotate_C_angle = math.radians(-60)
A = [0, 0]
B = [100, 0]
D = [100, 250]
# Create point D such that angle CAB = target_angle_CAB
target_angle_CAB = math.radians(60)
C = [B[0], B[0] * math.tan(target_angle_CAB)]
# What do we scale B by in order to get C
scale_factor = C[1] / D[1]
# Rotate C around B by rotate_C_angle
# (translate C by -Bx, then rotate, then translate back)
E = [
C[0] - C[1] * math.sin(rotate_C_angle),
C[1] * math.cos(rotate_C_angle)
]
# Scale E back
F = [E[0], E[1] / scale_factor]
This is assuming that A is at the origin. If it isn't then subtract Ax from all the x coordinates and Ay from the y coordinates, then do the calculations before translating back again.
Whether you need to scale back E to F depends on what you're doing. What happens here assumes that the scaling transformation along y does not get rotated.

Add random spread to directional vector

Let's say I have a unit vector a = Vector(0,1,0) and I want to add a random spread of something between x = Vector(-0.2,0,-0.2) and y = Vector(0.2,0,0.2), how would I go about doing that?
If I were to simply generate a random vector between x and y, I'd get a value somewhere in the bounds of a square:
What I'd like instead is a value within the circle made up by x and y:
This seems like a simple problem but I can't figure out the solution right now. Any help would be appreciated.
(I didn't ask this on mathoverflow since this isn't really a 'research level mathematics question')
If I read your question correctly, you want a vector in a random direction that's within a particular length (the radius of your circle).
The formula for a circle is: x2 + y2 = r2
So, if you have a maximum radius, r, that constrains the vector length, perhaps proceed something like this:
Choose a random value for x, that lies between -r and +r
Calculate a limit for randomising y, based on your chosen x, so ylim = sqrt(r2 - x2)
Finally, choose a random value of y between -ylim and +ylim
That way, you get a random direction in x and a random direction in y, but the vector length will remain within 0 to r and so will be constrained within a circle of that radius.
In your example, it seems that r should be sqrt(0.22) which is approximately 0.28284.
UPDATE
As 3D vector has length (or magnitude) sqrt(x2+y2+z2) you could extend the technique to 3D although I would probably favour a different approach (which would also work for 2D).
Choose a random direction by choosing any x, y and z
Calculate the magnitude m = sqrt(x2+y2+z2)
Normalise the direction vector (by dividing each element by its magnitude), so x = x/m, y = y/m, z=z/m
Now choose a random length, L between 0 and r
Scale the direction vector by the random length. So x = x * L, y = y * L, z = z * L

How to get a vector field that maps the slopes of an equation

Hey so I'm reading this article by Chris Hecker where he has an image of a Parabola surrounded by the a vector field of it's derivative:
However he never mentions how exactly he got the vector field equation, and never even states it. He does say he overlayed the vector field of the slopes in Figure 1, by drawing the solution to the slope equation, dy/dx = 2x, as a short vector at each coordinate on the grid.
How do you create a vector field of the slopes of an equation in the vector field syntax of
V = xi + yj
The Figure title would be clearer if it read:
The curve y = x^2, and the vector field dy/dx = 2x for the general case y = x^2 + C
There are three equations at work in the graph above:
y = x^2 - The equation for the parabola drawn - This is the one long solid curve
y = x^2 + C -The equation for all parabolas that fit on the vector field - C is a constant. This is the equation for all parabolas that fit on that vector field
dy/dx = 2x The equation for the slope field. - This is the slope or derivative of the both the curve drawn and all the possible curves that can be drawn with y = x^2 + C for all constant Cs.
Note that C is a constant, since the derivative of y = x^2 + C with any C is 2x. So the vector field shows how to draw all the different parabolas with different Cs.
So there are two ways to calculate the vector field:
Iterate over your desired range of x and y and calculate the slope, dy/dx- 2x independent of y in this case - at each point. This is how the author did it.
Draw a bunch of parabolas by slowly varying C in y = x^2 + C over a desired range of - let's say - x calculating y.
For a differential equation dy/dx = f(x,y) (e.g., dy/dx = 2x in this case, with f(x,y) = 2x), the vector field (F) will be F = i + f(x,y)j (so in your case, F = i + 2x j )

Given vector of one axis, how do I find vectors of other two axes?

This is a maths problem I am not exactly sure how to do. The vector is not aligned to an axis, so just rotating 90 degrees around x, y or z won't necessarily give me the other axes.
I can think of a couple of different scenarios you might be asking about.
Given: A pre-existing coordinate system
In a 2D system, your axes/basis are always [1,0] and [0,1] -- x and y axes.
In a 3D system, your axes/basis are always [1,0,0], [0,1,0], and [0,0,1] -- x, y, and z.
Given: One axis in an arbitrary-basis 2D coordinate system
If you have one axis in an arbitrary-basis 2D coordinate system, the other axis is the orthogonal vector.
To rotate a vector orthogonally counter-clockwise:
[x_new, y_new] = [ -y_old, x_old]
To rotate a vector orthogonally clockwise:
[x_new, y_new] = [ y_old, -x_old]
To summarize:
Given: x-axis = [ a, b]
Then: y-axis = [-b, a]
Given: y-axis = [ c, d]
Then: x-axis = [ d, -c]
Given: Two axes in an arbitrary-basis 3D coordinate system
To do this, find the cross product.
[a,b,c] x [d,e,f] = [ b*f - c*e, c*d - a*f, a*e - b*d ]
Following these three guidelines:
(x axis) x (y axis) = (z axis)
(y axis) x (z axis) = (x axis)
(z axis) x (x axis) = (y axis)
Given: One axis in an arbitrary-basis 3D coordinate system
There is not enough information to find the unique solution this problem. This is because, if you look at the second case (One axis in an arbitrary-basis 2D coordinate system), you first need to find an orthogonal vector. However, there are an infinite amount of possible orthogonal vectors to a single axis in 3D space!
You can, however, find one of the possible solutions.
One way to find an arbitrary one of these orthogonal vectors by finding any vector [d,e,f] where:
[a,b,c] = original axis
[d,e,f] = arbitrary orthogonal axis (cannot be [0,0,0])
a*d + b*e + c*f = 0
For example, if your original axis is [2,3,4], you'd solve:
2 * d + 3 * e + 4 * f = 0
That is, any value of [d,e,f] that satisfies this is a satisfactory orthogonal vector (as long as it's not [0,0,0]). One could pick, for example, [3,-2,0]:
2 * 3 + 3 *-2 + 4 * 0 = 0
6 + -6 + 0 = 0
As you can see, one "formula" that works to is [d,e,f] = [b,-a,0]...but there are many other ones that can work as well; there are, in fact, an infinite!
Once you find your two axes [a,b,c] and [d,e,f], you can reduce this back to the previous case (case 3), using [a,b,c] and [d,e,f] as your x and y axes (or whatever axes you need them to be, for your specific problem).
Normalization
Note that, as you continually do dot products and cross products, your vectors will begin to grow larger and larger. Depending on what you want, this might not be desired. For example, you might want your basis vectors (your coordinate axes) to all be the same size/length.
To turn any vector (except for [0,0,0]) into a unit vector (a vector with a length of 1, in the same direction as the original vector):
r = [a,b,c]
v = Sqrt(a^2 + b^2 + c^2) <-- this is the length of the original vector
r' = [ a/v , b/v , c/v ]
Where r' represents the unit vector of r -- a vector with length of 1 that points in the same direction as r does. An example:
r = [1,2,3]
v = Sqrt(1^2 + 2^2 + 3^2) = Sqrt(13) = 3.60555 <-- this is the length of the original vector
r' = [0.27735, 0.55470, 0.83205]
Now, if I wanted, for example, a vector in the same direction of r with a length of 5, I'd simply multiply out r' * 5, which is [a' * 5, b' * 5, c' * 5].
Having only one axis isn't enough, since there are still an infinite number of axes that can be in the perpendicular plane.
If you manage to get another axis though, you can use the cross product to find the third.
If you have one vector (x,y,z) you can get one perpendicular vector to it as (y,-x,0) (dot-product is xy-yx+0*z = 0)
Then you take the cross-product of both to get the remaining perpendicular vector:
(x,y,z) × (y,-x,0) = (0y+zx, yz-0x, -x²-y²) = (zx, yz, -x²-y²)
Are you talking about a typical 3coordinate system like the one used in a 3D engine?
With just a vector you can't find the other two, the only information you will have it the plane on which they lay.. but they can be at any angle also if they're perpendicular with the only one vector you have.

Resources