I have a problem using sin. I did:
include Math
puts sin(5) # => -0.9589242746631385
But when I type sin(5) into my calculator, it outputs 0.087155742. Likewise, I tried to calculate the value of PI using the equation pi = x * sin(180 / x) and got a problem although I got the value of PI with it on my calculator.
include Math
puts "Enter the value of x"
x = gets.to_f
num = 180 / x
pie = x * sin(num)
puts pie
Thanks if anyone can help.
Your equation is for a calculation of the sin of an angle in degrees.
Most, maybe all, computer language sin() functions expect the angle to be in radians.
Unfortunately, you need to have a value for pi to convert from one to another, so unless you can find a sin-in-degrees implementation you’re somewhat stuck.
This is because your formula comes from the 2×π/360 or π/180 conversion between radians and degrees.
Related
I am making a program to enter the radius and output the area and the perimeter:
# Calculates the area and the perimeter of a circle given the radius
puts "Enter a radius"
radius = gets
area = radius * 3.14 * radius
perimeter = 2 * 3.14 * radius
puts area
puts perimeter
When I tried to execute the code, it returned:
area.rb:4:in `*': no implicit conversion of String into Integer (TypeError)
The compiler says that the error is on the fourth line, but far I don't see any problems.
The problem is that radius is a string, because gets always returns a string. Maybe it contains an integer, but it's a string representation of an integer, like '10.3'.
radius = gets.to_i
or if you need decimal values
radius = gets.to_f
It's a bit more complex than this because to_i and to_f give you 0 and 0.0 respectively if you called them on 'foo'. In that case you could use the Integer and Float methods, and they will give you an ArgumentError exception if they are not able to convert to an integer or float value.
(Using Ruby with Gosu)
I have a single-point object representing a man which looks in a certain direction.
I have three variables, x, y (the 2d co-ordinates of the man) and #angle (the direction he's facing, in degrees). If i want to find x and y of the point which is exactly a distance of d (let's make it 20) in front of the man (in otheenter code herer words in the direction he's facing), how do I compute this?
def move
# Move
#x += #vel_x
#y += #vel_y
# HELP
#point_in_front_of_me_x = # some_function_for_x(#x, #y, #angle)
#point_in_front_of_me_y = # some_function_for_y(#x, #y, #angle)
# Prevent window exit
#x %= #window.width
#y %= #window.height
# Simulate air resistance
#vel_x *= 0.95
#vel_y *= 0.95
end
If you know a Gosu library or a manual way, either will do. If you know both and can point out the benefits, that's even better!
I don't know the Gosu library (or the coordinate system it uses), but a manual solution would be to use trigonometry. You know the angle and the hypotenuse (h, the distance to move) of the triangle and you are trying to calculate the the x coordinate (length of the adjacent side, b) and y coordinate (length of the opposite side, a).
We can calculate x_after_moving (using a coordinate system centered on the man's current position - you should be able to easily adapt this to another coordinate system if you need) using the relation sin(angle)=opposite/hypotenuse and rearranging (we only have one unknown here, the opposite side (b)):
def x_after_moving(distance, angle)
distance * Math.sin(angle * Math::PI / 180)
end
We're multiplying by pi/180 to convert from radians (what Ruby expects) to degrees. Similarly, knowing the relation cos(angle)=adjacent/hypotenuse, we can use a similar method to calculate the new y coord:
def y_after_moving(distance, angle)
distance * Math.cos(angle * Math::PI / 180)
end
Verify that it works with the following:
p 'Angle 0 (straight up)'
p 'x:' + x_after_moving(20, 0).to_s + ', y:' + y_after_moving(20, 0).to_s
p 'Angle 90 (right)'
p 'x:' + x_after_moving(20, 90).to_s + ', y:' + y_after_moving(20, 90).to_s
Gives us:
"Angle 0 (straight up)"
"x:0.0, y:20.0"
"Angle 90 (right)"
"x:20.0, y:1.2246467991473533e-15"
You may get very small values instead of zero in some cases - rounding should solve this problem y_after_moving(20, 90).round.
I am currently doing a small turn based cannon game with XNA 4.0. The game is very simple: the player chooses the speed and angle at which he desires to shoot his rocket in order to hit another player. There is also a randomly generated wind vector that affects the X trajectory of the rocket. I would like to add an AI so that the player could play against the computer in a single player mode.
The way I would like to implement the AI is very simple: find the velocity and angle that would make the rocket hit the player directly, and add a random modifier to those fields so that the AI doesn't hit another player each time.
This is the code I use in order to update the position and speed of the rocket:
Vector2 gravity = new Vector2(0, (float)400); // 400 is the sweet spot value that i have found works best for the gravity
Vector2 totalAcceleration = gravity + _terrain.WindDirection;
float deltaT = (float)gameTime.ElapsedGameTime.TotalSeconds; // Elapsed time since last update() call
foreach (Rocket rocket in _instantiatedRocketList)
{
rocket.RocketSpeed += Vector2.Multiply(gravity, deltaT); // Only changes the Y component
rocket.RocketSpeed += Vector2.Multiply(_terrain.WindDirection, deltaT); // Only changes the X component
rocket.RocketPosition += Vector2.Multiply(rocket.RocketSpeed, deltaT) + Vector2.Multiply(totalAcceleration, (float)0.5) * deltaT * deltaT;
// We update the angle of the rocket accordingly
rocket.RocketAngle = (float)Math.Atan2(rocket.RocketSpeed.X, -rocket.RocketSpeed.Y);
rocket.CreateSmokeParticles(3);
}
I know that the basic equations to find the final X and Y coordinates are:
X = V0 * cos(theta) * totalFlightTime
Y = V0 * sin(theta) * totalFlightTime - 0.5 * g * totalFlightTime^2
where X and Y are the coordinates of the player I want to hit, V0 the initial speed, theta the angle at witch the rocket is shot, totalFlightTime is, like the name says, the total flight time of the rocket until it reaches (X, Y) and g is the gravity (400 in my game).
Questions:
What I am having problems with, is knowing where to add the wind in those formulas (is it just adding "+ windDirection * totalFlightTime" in the X = equation?), and also what to do with those equations in order to do what I want to do (finding the initial speed and theta angle) since there are 3 variables (V0, theta and totalFlightTime) and only 2 equations?
Thanks for your time.
You can do this as follows:
Assuming there is no specific limit to V0 (i.e. the robot can fire the rocket at any desired speed) and using the substitutions
T=totalFlightTime
Vx=V0cos(theta)
Vy=V0sin(theta)
Choose an arbitrary value for Vx. Now your first equation simplifies to
X=VxT so T=X/Vx
to solve for T. Now substitute the value of T into the second equation and solve for Vy
Y=VyT + gT^2/2 so Vy = (Y - gT^2/2)/T
Finally you can now solve for V0 and theta
V0 = Sqrt(Vx^2 + Vy^2) and Theta = aTan(Vy/Vx)
Note that your initial choice of Vx will determine the trajectory the missile will take - if Vx is large then T will be small and the trajectory will be almost a straight line (like a bullet fired at a nearby target) - if Vx is small then T will be large and the trajectory will be an arc (like a mortar round's path). You dis start with three variables (V0, totalFlightTime, and theta) but they are dependent variables so choosing any one (or in this case Vx) plus the two equations solves for the other two. You could also pre-determine flight time and solve for Vx, Vy, theta and V0, or predetermine theta (although this would be tricky as some theta wouldn't provide a real solution.
For a simple particle system I'm making, I need to, given an ellipse with width and height, calculate a random point X, Y which lies in that ellipse.
Now I'm not the best at maths, so I wanted to ask here if anybody could point me in the right direction.
Maybe the right way is to choose a random float in the range of the width, take it for X and from it calculate the Y value?
Generate a random point inside a circle of radius 1. This can be done by taking a random angle phi in the interval [0, 2*pi) and a random value rho in the interval [0, 1) and compute
x = sqrt(rho) * cos(phi)
y = sqrt(rho) * sin(phi)
The square root in the formula ensures a uniform distribution inside the circle.
Scale x and y to the dimensions of the ellipse
x = x * width/2.0
y = y * height/2.0
Use rejection sampling: choose a random point in the rectangle around the ellipse. Test whether the point is inside the ellipse by checking the sign of (x-x0)^2/a^2+(y-y0)^2/b^2-1. Repeat if the point is not inside. (This assumes that the ellipse is aligned with the coordinate axes. A similar solution works in the general case but is more complicated, of course.)
It is possible to generate points within an ellipse without using rejection sampling too by carefully considering its definition in polar form. From wikipedia the polar form of an ellipse is given by
Intuitively speaking, we should sample polar angle θ more often where the radius is larger. Put more mathematically, our PDF for the random variable θ should be p(θ) dθ = dA / A, where dA is the area of a single segment at angle θ with width dθ. Using the equation for polar angle area dA = 1/2 r2 dθ and the area of an ellipse being π a b, then the PDF becomes
To randomly sample from this PDF, one direct method is the inverse CDF technique. This requires calculating the cumulative density function (CDF) and then inverting this function. Using Wolfram Alpha to get the indefinite integral, then inverting it gives inverse CDF of
where u runs between 0 and 1. So to sample a random angle θ, you just generate a uniform random number u between 0 and 1, and substitute it into this equation for the inverse CDF.
To get the random radius, the same technique that works for a circle can be used (see for example Generate a random point within a circle (uniformly)).
Here is some sample Python code which implements this algorithm:
import numpy
import matplotlib.pyplot as plt
import random
# Returns theta in [-pi/2, 3pi/2]
def generate_theta(a, b):
u = random.random() / 4.0
theta = numpy.arctan(b/a * numpy.tan(2*numpy.pi*u))
v = random.random()
if v < 0.25:
return theta
elif v < 0.5:
return numpy.pi - theta
elif v < 0.75:
return numpy.pi + theta
else:
return -theta
def radius(a, b, theta):
return a * b / numpy.sqrt((b*numpy.cos(theta))**2 + (a*numpy.sin(theta))**2)
def random_point(a, b):
random_theta = generate_theta(a, b)
max_radius = radius(a, b, random_theta)
random_radius = max_radius * numpy.sqrt(random.random())
return numpy.array([
random_radius * numpy.cos(random_theta),
random_radius * numpy.sin(random_theta)
])
a = 2
b = 1
points = numpy.array([random_point(a, b) for _ in range(2000)])
plt.scatter(points[:,0], points[:,1])
plt.show()
I know this is an old question, but I think none of the existing answers are good enough.
I was looking for a solution for exactly the same problem and got directed here by Google, found all the existing answers are not what I wanted, so I implemented my own solution entirely by myself, using information found here: https://en.wikipedia.org/wiki/Ellipse
So any point on the ellipse must satisfy that equation, how to make a point inside the ellipse?
Just scale a and b with two random numbers between 0 and 1.
I will post my code here, I just want to help.
import math
import matplotlib.pyplot as plt
import random
from matplotlib.patches import Ellipse
a = 4
b = a*math.tan(math.radians((random.random()+0.5)/2*45))
def random_point(a, b):
d = math.radians(random.random()*360)
return (a * math.cos(d) * random.random(), b * math.sin(d) * random.random())
points = [random_point(a, b) for i in range(360)]
x, y = zip(*points)
fig = plt.figure(frameon=False)
ax = fig.add_subplot(111)
ax.set_axis_off()
ax.add_patch(Ellipse((0, 0), 2*a, 2*b, edgecolor='k', fc='None', lw=2))
ax.scatter(x, y)
fig.subplots_adjust(left=0, bottom=0, right=1, top=1, wspace=0, hspace=0)
plt.axis('scaled')
plt.box(False)
ax = plt.gca()
ax.set_xlim([-a, a])
ax.set_ylim([-b, b])
plt.set_cmap('rainbow')
plt.show()
I'm trying to add a fade effect to my form by manually changing the opacity of the form but I'm having some trouble calculating the correct value to increment by the Opacity value of the form.
I know I could use the AnimateWindow API but it's showing some unexpected behavior and I'd rather do it manually anyways as to avoid any p/invoke so I could use it in Mono later on.
My application supports speeds ranging from 1 to 10. And I've manually calculated that for a speed of 1 (slowest) I should increment the opacity by 0.005 and for a speed of 10 (fastest) I should increment by 0.1. As for the speeds between 1 and 10, I used the following expression to calculate the correct value:
double opSpeed = (((0.1 - 0.005) * (10 - X)) / (1 - 10)) + 0.1; // X = [1, 10]
I though this could give me a linear value and that that would be OK. However, for X equal 4 and above, it's already too fast. More than it should be. I mean, speeds between 7, and 10, I barely see a difference and the animation speed with these values should be a little more spaced
Note that I still want the fastest increment to be 0.1 and the slowest 0.005. But I need all the others to be linear between them.
What I'm doing wrong?
It actually makes sense why it works like this, for instance, for a fixed interval between increments, say a few milliseconds, and with the equation above, if X = 10, then opSpeed = 0.1 and if X = 5, then opSpeed = 0.47. If we think about this, a value of 0.1 will loop 10 times and a value of 0.47 will loop just the double. For such a small interval of just a few milliseconds, the difference between these values is not that much as to differentiate speeds from 5 to 10.
I think what you want is:
0.005 + ((0.1-0.005)/9)*(X-1)
for X ranging from 1-10
This gives a linear scale corresponding to 0.005 when X = 1 and 0.1 when X = 10
After the comments below, I'm also including my answer fit for a geometric series instead of a linear scale.
0.005 * (20^((X-1)/9)))
Results in a geometric variation corresponding to 0.005 when X = 1 and 0.1 when X = 10
After much more discussion, as seen in the comments below, the updates are as follows.
#Nazgulled found the following relation between my geometric series and the manual values he actually needed to ensure smooth fade animation.
The relationship was as follows:
Which means a geometric/exponential series is the way to go.
After my hours of trying to come up with the appropriate curve fitting to the right hand side graph and derive a proper equation, #Nazgulled informed me that Wolfram|Alpha does that. Seriously amazing. :)
Wolfram Alpha link
He should have what he wants now, barring very high error from the equation above.
Your problem stems from the fact that the human eye is not linear in its response; to be precise, the eye does not register the difference between a luminosity of 0.05 to 0.10 to be the same as the luminosity difference between 0.80 and 0.85. The whole topic is complicated; you may want to search for the phrase "gamma correction" for some additional information. In general, you'll probably want to find an equation which effectively "gamma corrects" for human ocular response, and use that as your fading function.
It's not really an answer, but I'll just point out that everyone who's posted so far, including the original question, are all posting the same equation. So with four independent derivations, maybe we should assume that the equation was probably correct.
I did the algebra, but here's the code to verify (in Python, btw, with offsets added to separate the curves:
from pylab import *
X = arange(1, 10, .1)
opSpeed0 = (((0.1 - 0.005) * (10 - X)) / (1 - 10)) + 0.1 # original
opSpeed1 = 0.005 + ((0.1-0.005)/9)*(X-1) # Suvesh
opSpeed2 = 0.005*((10-X)/9.) + 0.1*(X-1)/9. # duffymo
a = (0.1 - 0.005) / 9 #= 0.010555555555... # Roger
b = 0.005 - a #= -0.00555555555...
opSpeed3 = a*X+b
nonlinear01 = 0.005*2**((2*(-1 + X))/9.)*5**((-1 + X)/9.)
plot(X, opSpeed0)
plot(X, opSpeed1+.001)
plot(X, opSpeed2+.002)
plot(X, opSpeed3+.003)
plot(X, nonlinear01)
show()
Also, at Nazgulled's request, I've included the non-linear curve suggested by Suvesh (which also, btw, looks quite alot like a gamma correction curve, as suggested by McWafflestix). The Suvesh's nonlinear equation is in the code as nonlinear01.
Here's how I'd program that linear relationship. But first I'd like to make clear what I think you're doing.
You want the rate of change in opacity to be a linear function of speed:
o(v) = o1*N1(v) + o2*N2(v) so that 0 <= v <=1 and o(v1) = o1 and o(v2) = o2.
If we choose N1(v) to equal 1-v and N2(v) = v we end up with what you want:
o(v) = o1*(1-v) + o2*v
So, plugging in your values:
v = (u-1)/(10-1) = (u-1)/9
o1 = 0.005 and o2 = 0.1
So the function should look like this:
o(u) = 0.005*{1-(u-1)/9} + 0.1*(u-1)/9
o(u) = 0.005*{(9-u+1)/9} + 0.1*(u-1)/9
o(u) = 0.005*{(10-u)/9} + 0.1(u-1)/9
You can simplify this until you get a simple formula for o(u) where 1 <= u <= 10. Should work fine.
If I understand what you're after, you want the equation of a line which passes through these two points in the plane: (1, 0.005) and (10, 0.1). The general equation for such a line (as long as it is not vertical) is y = ax+b. Plug the two points into this equation and solve the resulting set of two linear equations to get
a = (0.1 - 0.005) / 9 = 0.010555555555...
b = 0.005 - a = -0.00555555555...
Then, for each integer x = 1, 2, 3, ..., 10, plug x into y = ax+b to compute y, the value you want.