Trigonometric functions in Swift [duplicate] - ios

This question already has answers here:
Value of sine 180 is coming out as 1.22465e-16
(4 answers)
Closed 7 years ago.
I'm beginner developer for iOS. I use some online tutorials to learn Swift and now I'm trying to develop my own calculator. There is task to down "sin" and "cos" buttons by my own, which would return sine or cosine function for entered value.
Of course, there is sin() and cos() functions in the Swift, but I've found, that it returns values in radians, not degrees. I did search and found code, smth like that
func sind(degrees: Double) -> Double {
return sin(degrees * M_PI / 180.0)
}
which I implemented in my code. Now everything looks fine, buttons returns correct values. But there is sine of 180 degrees is 0 and when I enter 180 in my calculator and press "sin" button it returns another value. Same for cosine of 90 degrees, should be 0 but returns another value.
Could you please explain how possible to fix it? Full code at github: https://github.com/senator14/firstcalculator.git

The problem with sine and cosine functions is that M_PI is an irrational number is approximately defined as 3.14159265358979323846264338327950288 which means that it has some error.
One possible solutions to your problem is having the ranges of input form -PI/2 to PI/2. This reduces the error of approximation. The following changes your range to -90 to 90 degrees.
sin(((fmod($0, 360) > 270 ? fmod($0, 360) - 270 : ((fmod($0, 360) > 90) ? 180 - fmod($0, 360) : fmod($0, 360))) * M_PI / 180.00)) }
Reference from here

Related

Calculate a position based on an angle a speed and a starting position

Althougth i have read many articles on internet regarding it, i m unable to solve my issue.
There is a 2D plan where x, y is the top left point of the screen.
I have a point from which i know the position x, y, the direction (0 to 360 degrees) and a speed (in pixel per step ).
According to what i have read, if i want to calculate the next position of the point after one step i use the following code:
self.px.X := round(self.px.X + self.speed * cos(direction));
self.px.Y := round(self.px.Y + Self.speed * sin(direction));
For testing purpose i use a speed value of 10 and a direction of 90.
Normally, the point should move horizontally (or even vertically would be a progress), but it is moving in a diagonal movement, not even something like 45°.
Anyone knows what i'm doing wrong ?
As said by Andreas Rejbrand (but i don't know how to turn a comment into an answer, sorry Andreas), the solution was to use radians number by simply calling degToRad function:
self.px.X := round(self.px.X + self.speed * cos(DegToRad(direction)));
self.px.Y := round(self.px.Y + Self.speed * sin(DegToRad(direction)));

Objective-C: most efficient way to find the quadrant of an angle in Objective-C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 3 years ago.
Improve this question
What is the most efficient way to find the quadrant of an angle given in Objective-C (assuming that the boundary angles 0, 90, 270, 360 etc. all fall within a quadrant) ?
You don't need any magic functions.
Full circle contains 2*Pi radians and 4 quadrants.
So just divide angle by Pi/2 and make floor rounding to get 0..3 quadrant numbering (add 1 if 1..4 is needed)
Python example. Note that integer modulo operation % 4 provides "angle normalisation" so function works with large and negative angles
(Swift % does not work similar according to table here, so you might need to make something like return ((floor(2.0 * angle / math.pi) % 4 + 4) %4)
import math
def quadrant(angle):
return math.floor(2.0 * angle / math.pi) % 4
print(quadrant(math.pi/4))
print(quadrant(math.pi/4 + math.pi))
print(quadrant(math.pi/4 - math.pi))
0
2
2

Trig, placing items and updating their position

I have a problem I just cannot solve, and after a week it's really winding me up.
Background.
I'm placing items onto a circle using basic trig. The number of items can change dynamically, and they are spaced around the circle equally.
The items rotate around the circle, and the speed of rotation changes to be in sync with a BPM (Beats Per Minute) clock. This clock can change at any time.
The problem I'm having is that the items seem to be placed randomly on the circle, not equally spaced in order (see image 1). They'll appear out of order even though it's a basic for loop that places them. I think they may in face be in order, but the rotation values may be off making them look like they are in an odd order.
The second issue is that when the number of items reduces, the speed of rotation increases (it shouldn't) and if the number increases, the speed slows.
So I expect an issue with my trig function. I'm showing the complete code here but can simplify if it'll help.
What have I tried?
I've tried simplified versions without the graphical output, and the numbers all seem to make perfect sense. The radians between items is correct, the placement looks correct. It all looks correct, but it isn't.
The code.
--the variables
orbitalCircle.xPos = x or 0
orbitalCircle.yPos = y or 0
orbitalCircle.circleDiameter = diameter or 10
orbitalCircle.numberOfNotes = number_of_notes
orbitalCircle.spaceBetweenNotes = (360 / number_of_notes)
orbitalCircle.beatsPerSecond = (beats_per_minute / 60)
orbitalCircle.currentRotation = 0
orbitalCircle.framesPerSecond = frames_per_second or 15
orbitalCircle.framesPerFullRotation = (orbitalCircle.numberOfNotes/orbitalCircle.beatsPerSecond)+orbitalCircle.framesPerSecond
orbitalCircle.degreesPerFrame = 360 / orbitalCircle.framesPerFullRotation
orbitalCircle.newRotationValue = orbitalCircle.currentRotation + orbitalCircle.degreesPerFrame
orbitalCircle.sequenceData = sequence_data
--the function that updates the sequence data and therefore the number of items on the circle
function orbitalCircle.updateNotes(sq)
orbitalCircle.sequenceData = sq
orbitalCircle.numberOfNotes = (#sq)
orbitalCircle.spaceBetweenNotes = (360 / orbitalCircle.numberOfNotes)
end
--the function that calculates the new rotation value of the item to be placed on the circle
function orbitalCircle.tick()
orbitalCircle.spaceBetweenNotes = (360 / number_of_notes)
orbitalCircle.framesPerFullRotation = (orbitalCircle.numberOfNotes/orbitalCircle.beatsPerSecond)*orbitalCircle.framesPerSecond
orbitalCircle.degreesPerFrame = (360 / orbitalCircle.framesPerFullRotation)
orbitalCircle.newRotationValue = (orbitalCircle.currentRotation + orbitalCircle.degreesPerFrame)
if orbitalCircle.newRotationValue > 360 then
orbitalCircle.currentRotation = 0
else
orbitalCircle.currentRotation = orbitalCircle.newRotationValue
end
end
--finally the function that places the items onto the circle
function orbitalCircle.redraw()
screen.circle(orbitalCircle.xPos, orbitalCircle.yPos, orbitalCircle.circleDiameter)
screen.stroke()
for i=1, (#orbitalCircle.sequenceData) do
if orbitalCircle.sequenceData[i] > 0 then
screen.circle(
math.cos(math.rad(orbitalCircle.newRotationValue)+(orbitalCircle.spaceBetweenNotes*i))*orbitalCircle.circleDiameter + orbitalCircle.xPos,
math.sin(math.rad(orbitalCircle.newRotationValue)+(orbitalCircle.spaceBetweenNotes*i))*orbitalCircle.circleDiameter + orbitalCircle.yPos,
map(orbitalCircle.sequenceData[i], 5, 128, 0.5, 4)
)
end
end
end
end
I'd expect that the items would be:
equally spaced no matter the amount (that works)
in order (they appear not to be)
the speed of rotation should remain fixed unless the BPM changes (this doesn't happen)
I'm lost!
Let us take a closer look at the drawing.
screen.circle(
math.cos(math.rad(orbitalCircle.newRotationValue)+(orbitalCircle.spaceBetweenNotes*i))*orbitalCircle.circleDiameter + orbitalCircle.xPos,
math.sin(math.rad(orbitalCircle.newRotationValue)+(orbitalCircle.spaceBetweenNotes*i))*orbitalCircle.circleDiameter + orbitalCircle.yPos,
map(orbitalCircle.sequenceData[i], 5, 128, 0.5, 4)
)
What is the angle that is being drawn here? It is the argument to math.cos and math.sin (I will ignore the scaling and the translation that is applied afterwards):
math.rad(orbitalCircle.newRotationValue)+(orbitalCircle.spaceBetweenNotes*i)
So... it is the neRotationValue converted to radians and added to that the space between notes. This one is defined as 360 / number_of_notes, so it is in degrees. Adding a radians and degrees most likely does not produce the expected result.
So, what exactly do you mean with the following?
I've tried simplified versions without the graphical output, and the numbers all seem to make perfect sense.

Best way to place icons on a circle [duplicate]

This question already has answers here:
Calculating the position of points in a circle
(13 answers)
Closed 9 years ago.
I want to place some menu icons on a circle so that it almost looks like a clock. Depending on the amount of icons, the space between them may vary. Whats the best way to put each of these icons in the form of a circle?
Mathematics.
If you know how many items you have then you can find the angle between them because you know there are 360 degrees (2pi radians) in a circle. Choose a start point and then use
x = centerX + r * cos(angle)
y = centerY + r * sin(angle)
Using the center point of the circle, the radius and the angle (in radians), increasing the angle for each item.

CGContextAddArc initial circle angle

Anyways, I have been following this tutorial http://www.thinkandbuild.it/how-to-build-a-custom-control-in-ios/ in order to make a stop watch using this custom control. (I am not a total beginner, about 4 months in iOS, still new but I understand things.)
However, when I change the CGContextAddArc start angle from 0 to M_PI/2 to look like a clock and initialize the angle to self.angle = 0, it does not start at M_PI/2 but it creates an arc of length M_PI/2. So if you can picture that, imagine the 12 on a clock to the 3 on a clock is the arc length yet I want it to be so when I initialize it to self.angle = 0, it would only show M_PI/2 because that would be the original angle.

Resources