2018-01-27 14:59:17 +01:00
|
|
|
/**
|
|
|
|
* 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
|
2018-01-27 18:33:50 +01:00
|
|
|
#include <vector>
|
|
|
|
#include <cassert>
|
2018-02-12 13:18:50 +01:00
|
|
|
#include <cmath>
|
2018-01-27 16:28:36 +01:00
|
|
|
|
2018-01-27 14:59:17 +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) {}
|
2018-01-27 14:59:17 +01:00
|
|
|
double x, y, z;
|
2018-01-27 18:33:50 +01:00
|
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-01-27 18:33:50 +01:00
|
|
|
double operator[](unsigned i) const {
|
2018-02-06 19:09:02 +01:00
|
|
|
assert(i < 3);
|
2018-01-27 18:33:50 +01:00
|
|
|
switch(i) {
|
|
|
|
case 0: return x;
|
|
|
|
case 1: return y;
|
|
|
|
case 2: return z;
|
|
|
|
default: return 0;
|
|
|
|
}
|
|
|
|
}
|
2018-02-06 20:45:23 +01:00
|
|
|
|
2018-02-12 13:18:50 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
|
2018-02-06 20:45:23 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
|
2018-02-06 20:45:23 +01:00
|
|
|
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;
|
|
|
|
}
|
2018-01-27 14:59:17 +01:00
|
|
|
};
|
|
|
|
|
2018-02-12 13:18:50 +01:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
2018-01-27 14:59:17 +01:00
|
|
|
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;
|
|
|
|
}
|
2018-01-27 14:59:17 +01:00
|
|
|
int vert[3];
|
2018-01-27 16:28:36 +01:00
|
|
|
int operator[](unsigned i) const {
|
2018-01-27 14:59:17 +01:00
|
|
|
return vert[i % 3]; // dodge errors
|
|
|
|
}
|
2018-01-27 18:33:50 +01:00
|
|
|
const Point& pt(int id, const std::vector<Point>& pts) const {
|
|
|
|
assert(0 <= id && id < 3);
|
|
|
|
return pts[vert[id]];
|
|
|
|
}
|
2018-01-27 14:59:17 +01:00
|
|
|
};
|
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
|
2018-02-12 13:18:50 +01:00
|
|
|
double length(unsigned dim) const;
|
2018-02-07 17:59:41 +01:00
|
|
|
|
2018-02-13 18:43:02 +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;
|
|
|
|
};
|
|
|
|
|
2018-02-14 01:37:53 +01:00
|
|
|
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;
|
|
|
|
}
|
|
|
|
};
|
|
|
|
}
|