C++: Box the Compass

Bjarne-stroustrup
 

Avast me hearties!

There be many a land lubber that knows naught of the pirate ways and gives direction by degree! They know not how to box the compass!

Task description

  1. Create a function that takes a heading in degrees and returns the correct 32-point compass heading.
  2. Use the function to print and display a table of Index, Compass point, and Degree; rather like the corresponding columns from, the first table of the wikipedia article, but use only the following 33 headings as input:
[0.0, 16.87, 16.88, 33.75, 50.62, 50.63, 67.5, 84.37, 84.38, 101.25, 118.12, 118.13, 135.0, 151.87, 151.88, 168.75, 185.62, 185.63, 202.5, 219.37, 219.38, 236.25, 253.12, 253.13, 270.0, 286.87, 286.88, 303.75, 320.62, 320.63, 337.5, 354.37, 354.38]. (They should give the same order of points but are spread throughout the ranges of acceptance).
Notes;
  • The headings and indices can be calculated from this pseudocode:
for i in 0..32 inclusive:
    heading = i * 11.25
    case i %3:
      if 1: heading += 5.62; break
      if 2: heading -= 5.62; break
    end
    index = ( i mod 32) + 1
  • The column of indices can be thought of as an enumeration of the thirty two cardinal points (see talk page).

#include <string>
#include <boost/array.hpp>
#include <boost/assign/list_of.hpp>
#include <boost/format.hpp>
#include <boost/foreach.hpp>
#include <iostream>
#include <math.h>
using std::string;
using namespace boost::assign;

int get_Index(float angle)
{
	return static_cast<int>(floor(angle / 11.25 +0.5 )) % 32 + 1;
}

string get_Abbr_From_Index(int i)
{
	static boost::array<std::string, 32> points(list_of
	("N")("NbE")("NNE")("NEbN")("NE")("NEbE")("ENE")("EbN")
	("E")("EbS")("ESE")("SEbE")("SE")("SEbS")("SSE")("SbE")
	("S")("SbW")("SSW")("SWbS")("SW")("SWbW")("WSW")("WbS")
	("W")("WbN")("WNW")("NWbW")("NW")("NWbN")("NNW")("NbW"));
	return points[i-1];
}

string Build_Name_From_Abbreviation(string a)
{
	string retval;
	for (int i = 0; i < a.size(); ++i){
		if ((1 == i) && (a[i] != 'b') && (a.size() == 3)) retval += "-";
		switch (a[i]){
		case 'N' : retval += "north"; break; 
		case 'S' : retval += "south"; break; 
		case 'E' : retval += "east";  break; 
		case 'W' : retval += "west";  break; 
		case 'b' : retval += " by ";  break;
		}
	}
	retval[0] = toupper(retval[0]);
	return retval;
}

int main()
{
	boost::array<float,33> headings(list_of
	(0.0)(16.87)(16.88)(33.75)(50.62)(50.63)(67.5)(84.37)(84.38)(101.25)
	(118.12)(118.13)(135.0)(151.87)(151.88)(168.75)(185.62)(185.63)(202.5)
	(219.37)(219.38)(236.25)(253.12)(253.13)(270.0)(286.87)(286.88)(303.75)
	(320.62)(320.63)(337.5)(354.37)(354.38));
	int i;
	boost::format f("%1$4d %2$-20s %3$_7.2f");

	BOOST_FOREACH(float a, headings)
	{
		i = get_Index(a);
		std::cout << f % i %  Build_Name_From_Abbreviation(get_Abbr_From_Index(i)) % a << std::endl;
	}
	return 0;
}

Output:

   1 North                   0.00
   2 North by east          16.87
   3 North-northeast        16.88
   4 Northeast by north     33.75
   5 Northeast              50.62
   6 Northeast by east      50.63
   7 East-northeast         67.50
   8 East by north          84.37
   9 East                   84.38
  10 East by south         101.25
  11 East-southeast        118.12
  12 Southeast by east     118.13
  13 Southeast             135.00
  14 Southeast by south    151.87
  15 South-southeast       151.88
  16 South by east         168.75
  17 South                 185.62
  18 South by west         185.63
  19 South-southwest       202.50
  20 Southwest by south    219.37
  21 Southwest             219.38
  22 Southwest by west     236.25
  23 West-southwest        253.12
  24 West by south         253.13
  25 West                  270.00
  26 West by north         286.87
  27 West-northwest        286.88
  28 Northwest by west     303.75
  29 Northwest             320.62
  30 Northwest by north    320.63
  31 North-northwest       337.50
  32 North by west         354.37
   1 North                 354.38

SOURCE

Content is available under GNU Free Documentation License 1.2.