All pastes #744247 Raw Edit

Find bearing

public text v1 · immutable
·published 2007-10-21 07:24 UTC
rendered paste body
// Filename: 	bearing.cpp
// Author:		Joshua Boyce (aka Chazwazza)
// Purpose:		Program used to find the bearing between two arbitrary points (from 0 degrees, rotating clockwise)
// Important:	Program assumes that positive 'x' on our plane is 0 deg (+x = 0, -y = 90, -x = 180, +y = 270)

// Include declarations
#include <iostream>
#include <iomanip>
#include <ios>
#include <string>
#include <vector>
#include <sstream>
#include <cmath>
#include <stdexcept>

// Definitions
#define PI 3.14159265358979323846

// Using declarations
using std::cin;				using std::cout;
using std::vector;			using std::endl;
using std::string;			using std::istringstream;
using std::setprecision;	using std::fixed;
using std::runtime_error;	using std::range_error;
using std::domain_error;

// Function declarations
void split_string(string& str, string& delim, vector<double>& results);
double string_to_double(const string& s);
double calculate_bearing(vector<double>& point_one, vector<double>& point_two, unsigned int& deg_rad);

int main(){
	// Variables
	vector<double> point_one;
	vector<double> point_two;
	string temp_one;
	string temp_two;
	string delimiter = ",";
	double result = 0;
	unsigned int deg_rad;
	
	// Greet the user and get the points to be used
	cout << endl << "Welcome to Chazwazza's bearing calculator." << endl;
	cout << "Important: Program assumes that positive 'x' on our plane is 0 deg (+x = 0, -y = 90, -x = 180, +y = 270)" << endl;
	cout << "Please enter the coordinates of your first point, delimited by a comma: ";
	cin >> temp_one;
	cout << "Please enter the coordinates of your second point, delimited by a comma: ";
	cin >> temp_two;
	cout << "Would you like the answer to be displayed in degrees or radians? (0 for degrees, 1 for radians): ";
	cin >> deg_rad;
	
	// Split the strings and push back each coordinate into the associated vector
	try{
		split_string(temp_one,delimiter,point_one);
		split_string(temp_two,delimiter,point_two);
	} catch (runtime_error e){
		cout << e.what() << "Software will now abort.";
		return 1;
	}
	
	// Calculate the bearing between the two points
	try{
		result = calculate_bearing(point_one,point_two,deg_rad);
	} catch (range_error e) {
		cout << e.what();
		return 1;
	} catch (domain_error e) {
		cout << e.what();
		return 1;
	}
	
	// Get and set the precision from the user and display the answer
	int d;
	cout << "Please choose how many decimal places you would like the answer to be given to: ";
	if (!(cin >> d)){
		cout << "Invalid amount of decimal places! Software will now abort.";
		return 1;
	}
	cout << fixed << "The bearing between the given points is " << setprecision(d) << result << endl;
	
	return 0;
}

// Function used to split a string based on a delimiter and push it into a vector
void split_string(string& str, string& delim, vector<double>& results){
	try{
		int i;
		while ((i = str.find_first_of(delim)) != str.npos){
			if (i > 0)
				results.push_back(string_to_double(str.substr(0,i)));
			str = str.substr(i+1);
		}
		if (str.length() > 0)
			results.push_back(string_to_double(str));
	} catch (runtime_error e){
		throw e;
	}
}

// Function used to convert a string to a double
double string_to_double(const string& s){
	istringstream i(s);
	double x;
	if (!(i >> x))
		throw runtime_error("Conversion of \"" + s + "\" from string to double failed. ");
	return x;
}

// Function to calculate the bearing between the two points
double calculate_bearing(vector<double>& point_one, vector<double>& point_two, unsigned int& deg_rad){
	double result = 0;
	if (point_one.size() != 2 || point_two.size() != 2) {
		throw range_error("Null or invalid dimension amount, you must be using exactly two dimensions!");
	} else {
		try {
			if (deg_rad == 0) {
				if (point_one[1] > point_two[1]){
					result = acos((pow((point_one[0] - point_two[0]),2) + sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2)) - pow((point_one[1] - point_two[1]),2)) / (2 * fabs(point_one[0] - point_two[0]) * sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2)))) * 180 / PI;
				} else if (point_one[1] < point_two[1]){
					result = (acos((pow((point_one[0] - point_two[0]),2) + sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2)) - pow((point_one[1] - point_two[1]),2)) / (2 * fabs(point_one[0] - point_two[0]) * sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2))))  * 180 / PI) + 180;
				} else if (point_one[1] == point_two[1]){
					result = 180;
				}
			} else if (deg_rad == 1) {
				if (point_one[1] > point_two[1]){
					result = acos((pow((point_one[0] - point_two[0]),2) + sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2)) - pow((point_one[1] - point_two[1]),2)) / (2 * fabs(point_one[0] - point_two[0]) * sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2))));
				} else if (point_one[1] < point_two[1]){
					result = acos((pow((point_one[0] - point_two[0]),2) + sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2)) - pow((point_one[1] - point_two[1]),2)) / (2 * fabs(point_one[0] - point_two[0]) * sqrt(pow((point_one[1] - point_two[1]),2) + pow((point_one[0] - point_two[0]),2))));
				} else if (point_one[1] == point_two[1]){
					result = PI;
				}
			} else {
				throw range_error("Invalid selection of degrees or radians, value must be zero or one.");
			}
		} catch (domain_error e) {
			throw e;
		}
	}
	return result;
}