Skip to content

Commit

Permalink
Add function that returns the compass points.
Browse files Browse the repository at this point in the history
We support 16-wind compass rose.
  • Loading branch information
vahancho committed Feb 16, 2024
1 parent d7916dc commit 0e7ac11
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 0 deletions.
20 changes: 20 additions & 0 deletions include/coordinate.h
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,13 @@ class ERKIR_EXPORT Coordinate
DD ///< Decimal Degrees (D.D°)
};

enum class CompassPrecision
{
Cardinal,
Intercardinal,
SecondaryIntercardinal
};

//! Constructs a coordinate by the given decimal degrees.
Coordinate(double degrees);

Expand All @@ -67,6 +74,19 @@ class ERKIR_EXPORT Coordinate
/// Constrain degrees to range 0..360.0 (e.g. for bearings); -1 => 359, 361 => 1.
static double wrap360(double degrees);

/// Returns compass point (to given precision) for supplied bearing.
/*!
@param bearing Bearing in degrees from north.
@param precision Precision (Cardinal, Intercardinal, SecondaryIntercardinal).
@returns Compass point for supplied bearing.
@example
const point = Coordinate::compassPoint(24); // point = 'NNE'
const point = Coordinate::compassPoint(24, 1); // point = 'N'
*/
static std::string compassPoint(double bearing,
CompassPrecision precision = CompassPrecision::SecondaryIntercardinal);

protected:
std::string toBaseString(Format format, int precision) const;

Expand Down
17 changes: 17 additions & 0 deletions src/coordinate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,23 @@ std::string Coordinate::toBaseString(Format format, int precision) const
return ss.str();
}

std::string Coordinate::compassPoint(double bearing, CompassPrecision precision)
{
const auto wrappedBearing = wrap360(bearing); // normalize to range 0..360°

static constexpr const char *cardinals[] = {
"N", "NNE", "NE", "ENE",
"E", "ESE", "SE", "SSE",
"S", "SSW", "SW", "WSW",
"W", "WNW", "NW", "NNW"
};
static constexpr const int ns[] = { 4, 8, 16 };

const auto p = static_cast<int>(precision);
const auto n = ns[p];
return cardinals[(int)(std::round(wrappedBearing * n / 360.0)) % n * 16 / n];
}

////////////////////////////////////////////////////////////////////////////////

Latitude::Latitude(double degree)
Expand Down
22 changes: 22 additions & 0 deletions test/test.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -491,6 +491,28 @@ int main()
}
}

// Compass Points
{
verifyString( "N", Coordinate::compassPoint(1));
verifyString( "N", Coordinate::compassPoint(720));
verifyString( "N", Coordinate::compassPoint(0));
verifyString( "N", Coordinate::compassPoint(-1));
verifyString( "N", Coordinate::compassPoint(359));
verifyString( "S", Coordinate::compassPoint(180));
verifyString("NNE", Coordinate::compassPoint(24));
verifyString( "N", Coordinate::compassPoint(24, Coordinate::CompassPrecision::Cardinal));
verifyString( "NE", Coordinate::compassPoint(24, Coordinate::CompassPrecision::Intercardinal));
verifyString("NNE", Coordinate::compassPoint(24, Coordinate::CompassPrecision::SecondaryIntercardinal));
verifyString( "SW", Coordinate::compassPoint(226));
verifyString( "W", Coordinate::compassPoint(226, Coordinate::CompassPrecision::Cardinal));
verifyString( "SW", Coordinate::compassPoint(226, Coordinate::CompassPrecision::Intercardinal));
verifyString( "SW", Coordinate::compassPoint(226, Coordinate::CompassPrecision::SecondaryIntercardinal));
verifyString("WSW", Coordinate::compassPoint(237));
verifyString( "W", Coordinate::compassPoint(237, Coordinate::CompassPrecision::Cardinal));
verifyString( "SW", Coordinate::compassPoint(237, Coordinate::CompassPrecision::Intercardinal));
verifyString("WSW", Coordinate::compassPoint(237, Coordinate::CompassPrecision::SecondaryIntercardinal));
}

//////////////////////////////////////////////////////////////////////////////

// Ellipsoidal points
Expand Down

0 comments on commit 0e7ac11

Please sign in to comment.