Finding negative numbers in Python CSV file - python-2.7

I have a CSV file I'm reading with Northing and Easting values I'm trying to calculate the direction angle they are facing in... have things mostly sorted out(I think) at this point, but the final values are all coming up between 0 and 90 it seems even though I have the following code in there...
if (u_eastward >= 0) and (v_northward >= 0):
azimouth = azimouth
elif (u_eastward >= 0 and v_northward <= 0):
azimouth = 180 - azimouth
elif (u_eastward <= 0 and v_northward <= 0):
azimouth = azimouth + 180
elif (u_eastward <= 0 and v_northward >= 0):
azimouth = 360 - azimouth
Azimouth is being calculated in Excel as '=ATAN(D2/C2)' to find radians and then being recalculated to the angle by '=DEGREES(E2)' on the arc tangent value which I think is correct.
Would appreciate any help.

Wasn't properly converting my string to a float so everything was being seen as a positive value.

Related

Why is my character spawning at a 45 degree angle when I've coded it to be set to 0 degrees?

The title describes my problem, as you can see here my character is spawning at a 45 degree angle. The character always spawns at (0, 0)
I have created some code for animations that uses the character's position and desired position to calculate at what angle the character should be at. This angle is determined by using the percentage of distance the character has travelled to its destination (these destinations are only Y values. X is increased by 1 every tick). I have made an equation to determine the angle based on the percentage travelled. The equation: -(9/500)X^2 + (9/5)X. This is a parabola that intersects point (0, 0), (50, 45) ← 45 degree angle and (100, 0).
The code I made to use this equation is as follows:
float GetRotationDegrees(int Current, int Target, int LaneWidth) {
int numerator = Current - LaneWidth;
int denominator = Target - LaneWidth;
float X;
if (denominator == 0) X = 0;
else X = abs(numerator / denominator * 100);
return -(9/500)*pow(X,2)+(9/5)*X; // function: -(9/500)X^2 + (9/5)X.
}
The LaneWidth is always 400, Current is the character's current Y coordinate and Target is the target Y coordinate. At Y = 0 the equation should be -400 / -400 * 100 = 100. And when you put 100 in the equation you get 0, this value of 0 is then used like this:
SetActorLocation(FVector(1, sin(angle * PI / 180), 0).Rotation());
I am really confused right now because whenever I manually try this it won't work.
It is probably something stupid I did, I tend to look over things a lot of the time and am not that good at maths (I am also new to C++, so the mistake might be there too). If someone could help me I would really appreciate it!
(By the way, I know that the way that GetRotationDegrees decides X the angle will only return positive angles, I want to get this to work first)
Fixed it with this:
float GetRotationDegrees(int Current, int Target, int LaneWidth) {
if (Current == Target) return 0;
int MovingFrom;
if (Target != 0) MovingFrom = 0;
else if (Target > Current) MovingFrom = -LaneWidth;
else MovingFrom = LaneWidth;
float Percentage = float(Current - MovingFrom) / float(Target - MovingFrom) * 100;
if (Target < Current) Percentage = -Percentage;
bool isNegative = Percentage < 0;
if (isNegative) return -(-9 * pow(abs(Percentage), 2) / 500 + 9 * abs(Percentage) / 5);
return -9 * pow(Percentage, 2) / 500 + 9 * Percentage / 5;
}

Triangle function on angles

I need a function that works on angles (degrees for the example, but it may be radians as well) with the following (it must be continuous, I only write down some key values to understand the behavior):
any_function(angle):
0-> 0.0
45-> 0.5
90-> 1.0
135-> 0.5
180-> 0.0
225->-0.5
270->-1.0
335->-0.5
360-> 0.0
This is a simple triangular wave.
Does anything already exist in some modules or do I need to create it on my own?
For example like this (quick and dirty):
def toTriangle(angle):
if angle < 90 and angle >= 0:
t = (angle/90.)
elif angle <= 180 and angle >= 90:
t = 2-(angle/90.)
elif angle <= 270 and angle >= 180:
t = -(3-(angle/90.))
else:
t = -(4-(angle/90.))
return t
Thanks DeepSpace for your suggestion but it doesn't work out of the box:
from scipy.signal import sawtooth
sawtooth(0)
Out[4]: array(-1.0)
Here's a less quick-n-dirty solution:
def toTriangle(angle):
import math
tr = 1-4*math.fabs(0.5-math.modf(0.25+0.5*angle%(2*math.pi)/math.pi)[0] )
return t
( http://mathworld.wolfram.com/TriangleWave.html )

How to avoid if / else if chain when classifying a heading into 8 directions?

I have the following code:
if (this->_car.getAbsoluteAngle() <= 30 || this->_car.getAbsoluteAngle() >= 330)
this->_car.edir = Car::EDirection::RIGHT;
else if (this->_car.getAbsoluteAngle() > 30 && this->_car.getAbsoluteAngle() <= 60)
this->_car.edir = Car::EDirection::UP_RIGHT;
else if (this->_car.getAbsoluteAngle() > 60 && this->_car.getAbsoluteAngle() <= 120)
this->_car.edir = Car::EDirection::UP;
else if (this->_car.getAbsoluteAngle() > 120 && this->_car.getAbsoluteAngle() <= 150)
this->_car.edir = Car::EDirection::UP_LEFT;
else if (this->_car.getAbsoluteAngle() > 150 && this->_car.getAbsoluteAngle() <= 210)
this->_car.edir = Car::EDirection::LEFT;
else if (this->_car.getAbsoluteAngle() > 210 && this->_car.getAbsoluteAngle() <= 240)
this->_car.edir = Car::EDirection::DOWN_LEFT;
else if (this->_car.getAbsoluteAngle() > 240 && this->_car.getAbsoluteAngle() <= 300)
this->_car.edir = Car::EDirection::DOWN;
else if (this->_car.getAbsoluteAngle() > 300 && this->_car.getAbsoluteAngle() <= 330)
this->_car.edir = Car::EDirection::DOWN_RIGHT;
I want to avoid the ifs chain; it's really ugly. Is there a another, possibly cleaner, way of writing this?
#include <iostream>
enum Direction { UP, UP_RIGHT, RIGHT, DOWN_RIGHT, DOWN, DOWN_LEFT, LEFT, UP_LEFT };
Direction GetDirectionForAngle(int angle)
{
const Direction slices[] = { RIGHT, UP_RIGHT, UP, UP, UP_LEFT, LEFT, LEFT, DOWN_LEFT, DOWN, DOWN, DOWN_RIGHT, RIGHT };
return slices[(((angle % 360) + 360) % 360) / 30];
}
int main()
{
// This is just a test case that covers all the possible directions
for (int i = 15; i < 360; i += 30)
std::cout << GetDirectionForAngle(i) << ' ';
return 0;
}
This is how I would do it. (As per my previous comment).
You can use map::lower_bound and store the upper-bound of each angle in a map.
Working example below:
#include <cassert>
#include <map>
enum Direction
{
RIGHT,
UP_RIGHT,
UP,
UP_LEFT,
LEFT,
DOWN_LEFT,
DOWN,
DOWN_RIGHT
};
using AngleDirMap = std::map<int, Direction>;
AngleDirMap map = {
{ 30, RIGHT },
{ 60, UP_RIGHT },
{ 120, UP },
{ 150, UP_LEFT },
{ 210, LEFT },
{ 240, DOWN_LEFT },
{ 300, DOWN },
{ 330, DOWN_RIGHT },
{ 360, RIGHT }
};
Direction direction(int angle)
{
assert(angle >= 0 && angle <= 360);
auto it = map.lower_bound(angle);
return it->second;
}
int main()
{
Direction d;
d = direction(45);
assert(d == UP_RIGHT);
d = direction(30);
assert(d == RIGHT);
d = direction(360);
assert(d == RIGHT);
return 0;
}
Create an array, each element of which is associated with a block of 30 degrees:
Car::EDirection dirlist[] = {
Car::EDirection::RIGHT,
Car::EDirection::UP_RIGHT,
Car::EDirection::UP,
Car::EDirection::UP,
Car::EDirection::UP_LEFT,
Car::EDirection::LEFT,
Car::EDirection::LEFT,
Car::EDirection::DOWN_LEFT,
Car::EDirection::DOWN,
Car::EDirection::DOWN,
Car::EDirection::DOWN_RIGHT,
Car::EDirection::RIGHT
};
Then you can index the array with the angle / 30:
this->_car.edir = dirlist[(this->_car.getAbsoluteAngle() % 360) / 30];
No comparisons or branching required.
The result however is slightly off from the original. Values on the borders, i.e. 30, 60, 120, etc. are placed in the next category. For example, in the original code the valid values for UP_RIGHT are 31 to 60. The above code assigns 30 to 59 to UP_RIGHT.
We can get around this by subtracting 1 from the angle:
this->_car.edir = dirlist[((this->_car.getAbsoluteAngle() - 1) % 360) / 30];
This now gives us RIGHT for 30, UP_RIGHT for 60, etc.
In the case of 0, the expression becomes (-1 % 360) / 30. This is valid because -1 % 360 == -1 and -1 / 30 == 0, so we still get an index of 0.
Section 5.6 of the C++ standard confirms this behavior:
4 The binary / operator yields the quotient, and the binary % operator yields the remainder from the division of the first
expression by the second. If the second operand of / or % is zero
the behavior is undefined. For integral operands the / operator
yields the algebraic quotient with any fractional part discarded. if
the quotient a/b is representable in the type of the result,
(a/b)*b + a%b is equal to a.
EDIT:
There were many questions raised regarding the readability and maintainability of a construct like this. The answer given by motoDrizzt is a good example of simplifying the original construct that is more maintainable and isn't quite as "ugly".
Expanding on his answer, here's another example making use of the ternary operator. Since each case in the original post is assigning to the same variable, using this operator can help increase readability further.
int angle = ((this->_car.getAbsoluteAngle() % 360) + 360) % 360;
this->_car.edir = (angle <= 30) ? Car::EDirection::RIGHT :
(angle <= 60) ? Car::EDirection::UP_RIGHT :
(angle <= 120) ? Car::EDirection::UP :
(angle <= 150) ? Car::EDirection::UP_LEFT :
(angle <= 210) ? Car::EDirection::LEFT :
(angle <= 240) ? Car::EDirection::DOWN_LEFT :
(angle <= 300) ? Car::EDirection::DOWN:
(angle <= 330) ? Car::EDirection::DOWN_RIGHT :
Car::EDirection::RIGHT;
That code is not ugly, it's simple, practical, readable and easy to understand. It will be isolated in it's own method, so nobody will have to deal with it in everyday life. And just in case someone has to check it -maybe because he is debugging your application for a problem somewhere else- it's so easy it will take him two seconds to understand the code and what it does.
If I was doing such a debug I'd be happy to not have to spend five minutes trying to understand what your function does. In this regards, all other functions fail completely, as they change a simple, forget-about-it, bugs free routine, in a complicated mess that people when debugging will be forced to deeply analyse and test. As a project manager myself I'd strongly get upset by a developer taking a simple task and instead of implementing it into a simple, harmless way, wastes time to implement it into an over complicate way. Just think all the time you wasted thinking about it, then coming to SO asking, and all for just the sake of worsening maintenance and readability of the thing.
That said, there is a common mistake in your code that make it quite less readable, and a couple improvements you can do quite easily:
int angle = this->_car.getAbsoluteAngle();
if (angle <= 30 || angle >= 330)
return Car::EDirection::RIGHT;
else if (angle <= 60)
return Car::EDirection::UP_RIGHT;
else if (angle <= 120)
return Car::EDirection::UP;
else if (angle <= 150)
return Car::EDirection::UP_LEFT;
else if (angle <= 210)
return Car::EDirection::LEFT;
else if (angle <= 240)
return Car::EDirection::DOWN_LEFT;
else if (angle <= 300)
return Car::EDirection::DOWN;
else if (angle <= 330)
return Car::EDirection::DOWN_RIGHT;
Put this into a method, assign the returned value to the object, collapse the method, and forget about it for the rest of eternity.
P.S. there is another bug over the 330 threshold, but I don't know how you want to treat it, so I didn't fix it at all.
Later update
As per comment, you can even get rid of the else if at all:
int angle = this->_car.getAbsoluteAngle();
if (angle <= 30 || angle >= 330)
return Car::EDirection::RIGHT;
if (angle <= 60)
return Car::EDirection::UP_RIGHT;
if (angle <= 120)
return Car::EDirection::UP;
if (angle <= 150)
return Car::EDirection::UP_LEFT;
if (angle <= 210)
return Car::EDirection::LEFT;
if (angle <= 240)
return Car::EDirection::DOWN_LEFT;
if (angle <= 300)
return Car::EDirection::DOWN;
if (angle <= 330)
return Car::EDirection::DOWN_RIGHT;
I didn't do it 'cause I feel that a certain point it becomes just a matter of own preferences, and the scope of my answer was (and is) to give a different perspective to your concern about "ugliness of code". Anyway, as I said, someone pointed it out in the comments and I think it makes sense to show it.
In pseudocode:
angle = (angle + 30) %360; // Offset by 30.
So, we have 0-60, 60-90, 90-150,... as the categories.
In each quadrant with 90 degrees, one part has 60, one part has 30. So, now:
i = angle / 90; // Figure out the quadrant. Could be 0, 1, 2, 3
j = (angle - 90 * i) >= 60? 1: 0; // In the quardrant is it perfect (eg: RIGHT) or imperfect (eg: UP_RIGHT)?
index = i * 2 + j;
Use the index in an array containing the enums in the appropriate order.
switch (this->_car.getAbsoluteAngle() / 30) // integer division
{
case 0:
case 11: this->_car.edir = Car::EDirection::RIGHT; break;
case 1: this->_car.edir = Car::EDirection::UP_RIGHT; break;
...
case 10: this->_car.edir = Car::EDirection::DOWN_RIGHT; break;
}
Ignoring your first if which is a bit of a special case, the remaining ones all follow the exact same pattern: a min, max and direction; pseudo-code:
if (angle > min && angle <= max)
_car.edir = direction;
Making this real C++ might look like:
enum class EDirection { NONE,
RIGHT, UP_RIGHT, UP, UP_LEFT, LEFT, DOWN_LEFT, DOWN, DOWN_RIGHT };
struct AngleRange
{
int min, max;
EDirection direction;
};
Now, rather than writing a bunch of ifs, just loop over your various possibilies:
EDirection direction_from_angle(int angle, const std::vector<AngleRange>& angleRanges)
{
for (auto&& angleRange : angleRanges)
{
if ((angle > angleRange.min) && (angle <= angleRange.max))
return angleRange.direction;
}
return EDirection::NONE;
}
(throwing an exception rather than returning NONE is another option).
Which you would then call:
_car.edir = direction_from_angle(_car.getAbsoluteAngle(), {
{30, 60, EDirection::UP_RIGHT},
{60, 120, EDirection::UP},
// ... etc.
});
This technique is known as data-driven programming. Besides getting rid of a bunch of ifs, it would allow you to use easily add more directions (e.g., NNW) or reduce the number (left, right, up, down) without re-working other code.
(Handling your first special case is left as "an exercise for the reader." :-) )
Although the proposed variants based on a lookup table for angle / 30 are probably preferable, here is an alternative that uses a hard coded binary search to minimize the number of comparisons.
static Car::EDirection directionFromAngle( int angle )
{
if( angle <= 210 )
{
if( angle > 120 )
return angle > 150 ? Car::EDirection::LEFT
: Car::EDirection::UP_LEFT;
if( angle > 30 )
return angle > 60 ? Car::EDirection::UP
: Car::EDirection::UP_RIGHT;
}
else // > 210
{
if( angle <= 300 )
return angle > 240 ? Car::EDirection::DOWN
: Car::EDirection::DOWN_LEFT;
if( angle <= 330 )
return Car::EDirection::DOWN_RIGHT;
}
return Car::EDirection::RIGHT; // <= 30 || > 330
}
If you really want to avoid duplication you can express this as a mathematical formula.
First of all, assume that we are using #Geek's Enum
Enum EDirection { RIGHT =0, UP_RIGHT, UP, UP_LEFT, LEFT, DOWN_LEFT,DOWN, DOWN_RIGHT}
Now we can compute the enum using integer mathematics (with out the need for arrays).
EDirection angle2dir(int angle) {
int d = ( ((angle%360)+360)%360-1)/30;
d-=d/3; //some directions cover a 60 degree arc
d%=8;
//printf ("assert(angle2dir(%3d)==%-10s);\n",angle,dir2str[d]);
return (EDirection) d;
}
As #motoDrizzt points out, concise code isn't necessarily readable code. It does have the small advantage that expressing it as maths makes it explicit that some directions cover a wider arc. If you want to go this direction you can add some asserts to help understand the code.
assert(angle2dir( 0)==RIGHT ); assert(angle2dir( 30)==RIGHT );
assert(angle2dir( 31)==UP_RIGHT ); assert(angle2dir( 60)==UP_RIGHT );
assert(angle2dir( 61)==UP ); assert(angle2dir(120)==UP );
assert(angle2dir(121)==UP_LEFT ); assert(angle2dir(150)==UP_LEFT );
assert(angle2dir(151)==LEFT ); assert(angle2dir(210)==LEFT );
assert(angle2dir(211)==DOWN_LEFT ); assert(angle2dir(240)==DOWN_LEFT );
assert(angle2dir(241)==DOWN ); assert(angle2dir(300)==DOWN );
assert(angle2dir(301)==DOWN_RIGHT); assert(angle2dir(330)==DOWN_RIGHT);
assert(angle2dir(331)==RIGHT ); assert(angle2dir(360)==RIGHT );
Having added the asserts you have added duplication, but duplication in asserts isn't so bad. If you have an inconsistent assert you will find out soon enough. Asserts can be compiled out of release version so as not to bloat the executable you distribute. Nevertheless, this approach is probably most applicable if you want to optimize the code rather than just make it less ugly.
I'm Late to the party, but We could use enum flags and range checks to do something neat.
enum EDirection {
RIGHT = 0x01,
LEFT = 0x02,
UP = 0x04,
DOWN = 0x08,
DOWN_RIGHT = DOWN | RIGHT,
DOWN_LEFT = DOWN | LEFT,
UP_RIGHT = UP | RIGHT,
UP_LEFT = UP | LEFT,
// just so we be clear, these won't have much use though
IMPOSSIBLE_H = RIGHT | LEFT,
IMPOSSIBLE_V = UP | DOWN
};
the checking(pseudo-code), assuming angle is absolue (between 0 and 360):
int up = (angle > 30 && angle < 150) * EDirection.UP;
int down = (angle > 210 && angle < 330) * EDirection.DOWN;
int right = (angle <= 60 || angle >= 330) * EDirection.Right;
int left = (angle >= 120 && angle <= 240) * EDirection.LEFT;
EDirection direction = (Direction)(up | down | right | left);
switch(direction){
case RIGHT:
// do right
break;
case UP_RIGHT:
// be honest
break;
case UP:
// whats up
break;
case UP_LEFT:
// do you even left
break;
case LEFT:
// 5 done 3 to go
break;
case DOWN_LEFT:
// your're driving me to a corner here
break;
case DOWN:
// :(
break;
case DOWN_RIGHT:
// completion
break;
// hey, we mustn't let these slide
case IMPOSSIBLE_H:
case IMPOSSIBLE_V:
// treat your impossible case here!
break;
}

Stablize a value in c++

I have a variable which is a Modulus of Congruence x=y(mod 360),which means y varies from 0 - 360 and if the value is greater than 360 it again comes to 0. For example x=5 for y = 365 .
I wrote this function to stabilize y , so if the difference between x and previousx is greater than 5 then i get x otherwise previousx .
float stabilize(float x,float previous){
if(fabs(x-previousx)<5)
{
return previousx;
}
else
{
return x;
}
}
This works fine between 0 to 360 But this fails on the boundary condition of 360 and 0 .How can i stabilize the value when y is a value near 0 such as 0.3 and previous y is near 360 such as 359. So the difference calculated here is 359 - .3 = 358.7 . but i want it to be the modulo 360 difference which is 1.3 .
What about something like if(fabs(x-previousx)<5 || fabs(x-previousx)>355)? Given that the input data is mod 360, if the difference is big enough it means that both values are close enough to the border.
You could subtract the original numbers and take modulo 360 of the fabs(result):
for example:
359 - 720.3 = -361.3
fabs(-361.3) = 361.3
361.3 % 360 = 1.3

Converting wind direction in angles to text words

I have wind direction data coming from a weather vane, and the data is represented in 0 to 359 degrees.
I want to convert this into text format (compass rose) with 16 different directions.
Basically I want to know if there is a fast slick way to scale the angle reading to a 16 string array to print out the correct wind direction without using a bunch of if statements and checking for ranges of angles
Wind direction can be found here.
thanks!
EDIT :
Since there is an angle change at every 22.5 degrees, the direction should swap hands after 11.25 degrees.
Therefore:
349-360//0-11 = N
12-33 = NNE
34-56 = NE
Using values from 327-348 (The entire NNW spectrum) failed to produce a result for eudoxos' answer.
After giving it some thought I could not find the flaw in his logic, so i rewrote my own..
def degToCompass(num):
val=int((num/22.5)+.5)
arr=["N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"]
print arr[(val % 16)]
>>> degToCompass(0)
N
>>> degToCompass(180)
S
>>> degToCompass(720)
N
>>> degToCompass(11)
N
>>> 12
12
>>> degToCompass(12)
NNE
>>> degToCompass(33)
NNE
>>> degToCompass(34)
NE
STEPS :
Divide the angle by 22.5 because 360deg/16 directions = 22.5deg/direction change.
Add .5 so that when you truncate the value you can break the 'tie' between the change threshold.
Truncate the value using integer division (so there is no rounding).
Directly index into the array and print the value (mod 16).
Here's a javascript implementation of steve-gregory's answer, which works for me.
function degToCompass(num) {
var val = Math.floor((num / 22.5) + 0.5);
var arr = ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"];
return arr[(val % 16)];
}
See his answer for an explanation of the logic.
This JavaScript will work for anyone who only needs 8 cardinal directions and would like corresponding arrows.
function getCardinalDirection(angle) {
const directions = ['↑ N', '↗ NE', '→ E', '↘ SE', '↓ S', '↙ SW', '← W', '↖ NW'];
return directions[Math.round(angle / 45) % 8];
}
Watch out for rounding, angles between 349...11 should be "N", therefore add half sector first (+(360/16)/2), then handle overflow over 360 by %360, then divide by 360/16:
["N","NNW",...,"NNE"][((d+(360/16)/2)%360)/(360/16)]
I checked this and it works very good and seems accurate.
Source: http://www.themethodology.net/2013/12/how-to-convert-degrees-to-cardinal.html by Adrian Stevens
public static string DegreesToCardinal(double degrees)
{
string[] caridnals = { "N", "NE", "E", "SE", "S", "SW", "W", "NW", "N" };
return caridnals[(int)Math.Round(((double)degrees % 360) / 45)];
}
public static string DegreesToCardinalDetailed(double degrees)
{
degrees *= 10;
string[] caridnals = { "N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE", "S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW", "N" };
return caridnals[(int)Math.Round(((double)degrees % 3600) / 225)];
}
I believe it is easier to:
Shift the direction by 11.25
Add an "N" at the end of the direction list to handle the 'over 360',
DirTable = ["N","NNE","NE","ENE","E","ESE", "SE","SSE","S","SSW","SW","WSW", "W","WNW","NW","NNW",**"N"**];
wind_direction= DirTable[Math.floor((d+11.25)/22.5)];
If you arrived here and are only interested in breaking your degrees into one of 8 directions.
function degToCompass(num){
const val = Math.floor((num / 45) + 0.5);
const arr = ["N","NE","E", "SE","S","SW","W","NW"];
return arr[(val % 8)]
Here's a one-line python function:
def deg_to_text(deg):
return ["N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"][round(deg/22.5)%16]
Obviously it can be split into multiple lines for readability/pep8
I would probably just do simple division of degrees to get a position in an array or an enum value or something that would give you the text you need. Just round down on all your division. 360/16 = 22.5, so you would want to divide by 22.5 to get the position.
String[] a = [N,NNW,NW,WNW,...,NNE]
this works fine
#!/usr/bin/env python
def wind_deg_to_str1(deg):
if deg >= 11.25 and deg < 33.75: return 'NNE'
elif deg >= 33.75 and deg < 56.25: return 'NE'
elif deg >= 56.25 and deg < 78.75: return 'ENE'
elif deg >= 78.75 and deg < 101.25: return 'E'
elif deg >= 101.25 and deg < 123.75: return 'ESE'
elif deg >= 123.75 and deg < 146.25: return 'SE'
elif deg >= 146.25 and deg < 168.75: return 'SSE'
elif deg >= 168.75 and deg < 191.25: return 'S'
elif deg >= 191.25 and deg < 213.75: return 'SSW'
elif deg >= 213.75 and deg < 236.25: return 'SW'
elif deg >= 236.25 and deg < 258.75: return 'WSW'
elif deg >= 258.75 and deg < 281.25: return 'W'
elif deg >= 281.25 and deg < 303.75: return 'WNW'
elif deg >= 303.75 and deg < 326.25: return 'NW'
elif deg >= 326.25 and deg < 348.75: return 'NNW'
else: return 'N'
def wind_deg_to_str2(deg):
arr = ['NNE', 'NE', 'ENE', 'E', 'ESE', 'SE', 'SSE', 'S', 'SSW', 'SW', 'WSW', 'W', 'WNW', 'NW', 'NNW', 'N']
return arr[int(abs((deg - 11.25) % 360)/ 22.5)]
i = 0
while i < 360:
s1 = wind_deg_to_str1(i)
s2 = wind_deg_to_str2(i)
print '%5.1f deg -> func1(%-3s), func2(%-3s), same:%s' % (i, s1, s2, ('ok' if s1 == s2 else 'different'))
i += 0.5
To do the reverse conversion (compass letter abbreviations to degrees):
function getDir($b)
{
$dirs = array('N'=>0, 'NNE'=>22.5,"NE"=>45,"ENE"=>67.5, 'E'=>90,'ESE'=>112.5, 'SE'=>135,'SSE'=>157.5, 'S'=>180,'SSW'=>202.5, 'SW'=>225,'WSW'=>247.5, 'W'=>270,'WNW'=>292.5,'NW'=>315,'NNW'=>337.5, 'N'=>0,'North'=>0,'East'=>90,'West'=>270,'South'=>180);
return $dirs[$b];
}
Javascript function 100% working
function degToCompass(num) {
while( num < 0 ) num += 360 ;
while( num >= 360 ) num -= 360 ;
val= Math.round( (num -11.25 ) / 22.5 ) ;
arr=["N","NNE","NE","ENE","E","ESE", "SE",
"SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"] ;
return arr[ Math.abs(val) ] ;
}
steps
Given a 360 degree angle
Since north is between -11.25 to 11.25 we subtract 11.25 for accuracy
Divide the angle by 22.5 because 360deg/16 directions = 22.5deg/direction change
Math.abs for as negative is still north
Select the segment from arr from answer
Hope it helps
Used this in Excel:
VLOOKUP(MROUND(N12,22.5),N14:O29,2,FALSE)
Cell N12 is direction toward in degrees for which an answer is needed.
The range N14:O29 is looking up the sector(A to R):
WIND SECTOR
0 A
22.5 B
45 C
67.5 D
90 E
112.5 F
135 G
157.5 H
180 J
202.5 K
225 L
247.5 M
270 N
292.5 P
315 Q
337.5 R
I use R heavily and needed a solution for this. This is what I came up with and works well for all possible combinations I have fed it:
degToCardinal <- function(degrees) {
val <- as.integer((degrees / 22.5) + 0.5)
arr <- c("N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW")
return(arr[((val+1) %% 16)])
}
Wanted to use #eudoxos but needed to pull all the parts together:
def deg_to_compass(d):
return ["N", "NNE", "NE", "ENE", "E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW", "W", "WNW", "NW", "NNW"] [math.floor(((d+(360/16)/2)%360)/(360/16))]
Borrrowed #Hristo markow to check the results:
for i in range(0,360):
print (i,deg_to_compass(i) == wind_deg_to_str2(i))
compass_direction =["NNE","NE","ENE","E","ESE","SE","SSE","S","SSW","SW","WSW","W","WNW","NW","NNW","N"]
for i in range (0,365):
index = (int) ((((i / 11.25) - 1) /2) % 16)
print(f"Angle: {i:3}, Index: {index}, Compass: {compass_direction[index]}")