Files
CSCI-1200/labs/exceptions_inheritance/cp2/utilities.h
2025-01-07 17:20:18 -05:00

121 lines
3.4 KiB
C++

// =========================================
//
// IMPORTANT NOTE: DO NOT EDIT THIS FILE
//
// =========================================
#ifndef _UTILITIES_H_
#define _UTILITIES_H_
#include <iostream>
#include <cmath>
#include <cassert>
// epsilon values used in comparing the edge lengths & angles between
// edges note that these values are dependent on the precision of
// the coordinates and the overall scale of the objects
#define DISTANCE_EPSILON 0.0001
#define ANGLE_EPSILON 0.1
// -----------------------------------------------------------------
// Stores a 2D coordinate
class Point {
public:
Point(double _x, double _y) : x(_x),y(_y) {}
double x;
double y;
};
// Stores a 2D vector, constructed from 2 Points
class Vector {
public:
Vector(const Point &a, const Point &b) { dx = b.x-a.x; dy = b.y-a.y; }
double Length() const { return sqrt(dx*dx+dy*dy); }
void Normalize() {
// make this a unit vector (length = 1)
double length = Length();
if (length < DISTANCE_EPSILON) throw std::string("LENGTH = 0");
assert (length > DISTANCE_EPSILON);
dx /= length;
dy /= length;
}
// representation
double dx;
double dy;
};
inline std::ostream& operator<< (std::ostream &ostr, const Vector &v) {
ostr << "<" << v.dx << "," << v.dy << ">";
return ostr;
}
// -----------------------------------------------------------------
// calculate the length of an edge, the distance between 2 points
inline double DistanceBetween(const Point &a, const Point &b) {
Vector v(a,b);
return v.Length();
}
// Calculate the angle at vertex b in degrees, that is, the angle
// between edges ab and bc. This will return a positive number
// measured as the clockwise rotation in the xy plane from point c to
// point a (rotating around point b).
inline double Angle(const Point &a, const Point &b, const Point &c) {
// make unit vector along each of the edges
Vector ba(b,a); ba.Normalize();
Vector bc(b,c); bc.Normalize();
// calculate the angle in radians
double dot_product = ba.dx * bc.dx + ba.dy * bc.dy;
if (dot_product < -1 || dot_product > 1) throw std::string("DOT PRODUCT RANGE");
assert (dot_product >= -1 && dot_product <= 1);
float perpDot = ba.dx * bc.dy - ba.dy * bc.dx;
// using atan2 to ensure than we get a signed answer.
double angle_in_radians = atan2(perpDot, dot_product);
// convert to degrees
double answer = angle_in_radians * 180.0 / M_PI;
if (answer < 0) {
answer += 360;
}
assert (answer >= 0 && answer <= 360);
return answer;
}
// returns true if these two vectors are parallel
inline bool Parallel(const Vector &a, const Vector &b) {
Vector a2 = a; a2.Normalize();
Vector b2 = b; b2.Normalize();
double dot_product = a2.dx * b2.dx + a2.dy * b2.dy;
// parallel vectors have dot product == 1
if (fabs(dot_product) > 1-DISTANCE_EPSILON) return true;
return false;
}
// -----------------------------------------------------------------
// simple functions for angles & sides
inline bool EqualSides(double a, double b) {
return (fabs(a-b) < DISTANCE_EPSILON);
}
inline bool EqualAngles(double a, double b) {
assert (a >= 0.0 && a < 360.0);
assert (b >= 0.0 && b < 360.0);
return (fabs(a-b) < ANGLE_EPSILON);
}
inline bool RightAngle(double a) {
assert (a >= 0.0 && a < 360.0);
return (fabs(a-90.0) < ANGLE_EPSILON);
}
// -----------------------------------------------------------------
#endif