121 lines
3.4 KiB
C++
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
|