/** * Defines a few widely used, widely spread structures. Imported pervasively. **/ #pragma once #include // Hash #include #include #include struct Point { Point(double x, double y, double z) : x(x), y(y), z(z) {} double x, y, z; 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 { 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)); } 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); } 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]); } 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 { Face(int v0, int v1, int v2) { vert[0] = v0; vert[1] = v1; vert[2] = v2; } int vert[3]; int operator[](unsigned i) const { return vert[i % 3]; // dodge errors } const Point& pt(int id, const std::vector& pts) const { assert(0 <= id && id < 3); return pts[vert[id]]; } }; 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; Point low_pt() const; Point high_pt() const; 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 } }; namespace std { template<> struct hash { 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{}(s[0]) ); result_type const h2 ( std::hash{}(s[1]) ); result_type const h3 ( std::hash{}(s[2]) ); return h1 ^ h2 ^ h3; } }; }