mpri-graphics-project/common_structures.hpp

183 lines
4.4 KiB
C++
Raw Permalink Normal View History

/**
* Defines a few widely used, widely spread structures. Imported pervasively.
**/
2018-02-06 19:07:07 +01:00
#pragma once
2018-01-27 16:28:36 +01:00
#include <functional> // Hash
#include <vector>
#include <cassert>
#include <cmath>
2018-01-27 16:28:36 +01:00
struct Point {
2018-01-27 16:28:36 +01:00
Point(double x, double y, double z) : x(x), y(y), z(z) {}
double x, y, z;
2018-02-13 16:14:28 +01:00
double norm() const {
auto sq = [](double x) { return x * x; };
return sqrt(sq(x) + sq(y) + sq(z));
}
void normalize() {
double _norm = norm();
x /= _norm;
y /= _norm;
z /= _norm;
}
double operator[](unsigned i) const {
2018-02-06 19:09:02 +01:00
assert(i < 3);
switch(i) {
case 0: return x;
case 1: return y;
case 2: return z;
default: return 0;
}
}
bool operator==(const Point& pt) const {
return fabs(x - pt.x) < 1e-9
&& fabs(y - pt.y) < 1e-9
&& fabs(z - pt.z) < 1e-9;
}
Point operator+(const Point& pt) const {
return Point(
x + pt.x,
y + pt.y,
z + pt.z);
}
Point& operator+=(const Point& pt) {
x += pt.x;
y += pt.y;
z += pt.z;
return *this;
}
Point& operator-=(const Point& pt) {
return (*this += Point(-pt.x, -pt.y, -pt.z));
}
2018-02-13 14:01:57 +01:00
Point operator-(const Point& pt) const {
return (*this) + (-1 * pt);
}
friend Point operator*(double scalar, const Point& pt) {
return Point(
scalar * pt.x,
scalar * pt.y,
scalar * pt.z);
}
2018-02-07 17:59:41 +01:00
2018-02-13 14:01:57 +01:00
Point cross_prod(const Point& pt) const {
return Point(
(*this)[1] * pt[2] - (*this)[2] * pt[1],
(*this)[2] * pt[0] - (*this)[0] * pt[2],
(*this)[0] * pt[1] - (*this)[1] * pt[0]);
}
2018-02-07 17:59:41 +01:00
bool operator<(const Point& pt) const {
/// Lexicographic order on (x, y, z)
if(x == pt.x) {
if(y == pt.y)
return z < pt.z;
return y < pt.y;
}
return x < pt.x;
}
};
struct PointLoc {
/// Point location: a point with integer coordinates, used to index Points
PointLoc(int x, int y, int z): x(x), y(y), z(z) {}
int x, y, z;
bool operator<(const PointLoc& pt) const {
if(x == pt.x) {
if(y == pt.y)
return z < pt.z;
return y < pt.y;
}
return x < pt.x;
}
bool operator==(const PointLoc& pt) const {
return x == pt.x && y == pt.y && z == pt.z;
}
PointLoc operator+(const PointLoc& pt) const {
return PointLoc(x + pt.x, y + pt.y, z + pt.z);
}
};
struct Face {
2018-01-27 16:28:36 +01:00
Face(int v0, int v1, int v2) {
vert[0] = v0;
vert[1] = v1;
vert[2] = v2;
}
int vert[3];
2018-01-27 16:28:36 +01:00
int operator[](unsigned i) const {
return vert[i % 3]; // dodge errors
}
const Point& pt(int id, const std::vector<Point>& pts) const {
assert(0 <= id && id < 3);
return pts[vert[id]];
}
};
2018-01-27 16:28:36 +01:00
2018-02-07 17:59:41 +01:00
class Cuboid {
/// A 3D box
public:
static Cuboid empty() {
return Cuboid(Point(0, 0, 0), Point(0, 0, 0));
}
Cuboid(Point bd1, Point bd2);
Cuboid(const Cuboid& oth)
: lowBound(oth.lowBound), highBound(oth.highBound) {}
double low(unsigned dim) const; ///< Lower bound for a dimension
double high(unsigned dim) const; ///< Higher bound for a dimension
double length(unsigned dim) const;
2018-02-07 17:59:41 +01:00
Point low_pt() const;
Point high_pt() const;
2018-02-07 17:59:41 +01:00
double volume() const;
bool is_empty() const;
private:
Point lowBound, highBound;
};
struct Color {
Color() : r(0), g(0), b(0) {}
Color(double r, double g, double b) : r(r), g(g), b(b) {}
double r, g, b;
double operator[](int i) const {
switch(i % 3) {
case 0: return r;
case 1: return g;
case 2: return b;
}
return 0; // won't happen
}
};
2018-01-27 16:28:36 +01:00
namespace std {
template<> struct hash<Face>
{
typedef Face argument_type;
typedef std::size_t result_type;
result_type operator()(argument_type const& s) const noexcept
{
result_type const h1 ( std::hash<int>{}(s[0]) );
result_type const h2 ( std::hash<int>{}(s[1]) );
result_type const h3 ( std::hash<int>{}(s[2]) );
return h1 ^ h2 ^ h3;
}
};
}