#pragma once #include #include #include #include #include #include template float dot(int n, const V &a, const V &b) { float sum = 0; for (int i = 0; i < n; ++i) { sum += a[i] * b[i]; } return sum; } template std::vector> mirror(const tc::Group &group) { std::vector> mirrors; for (int p = 0; p < group.ngens; ++p) { std::vector vp; for (int m = 0; m < p; ++m) { auto &vq = mirrors[m]; vp.push_back((cos(M_PI / group.get(p, m)) - dot(m, vp, vq)) / vq[m]); } vp.push_back(std::sqrt(1 - dot(p, vp, vp))); for (const auto &v : mirrors) { if (dot(p, vp, vp) > 0) { for (auto &e : vp) { e *= -1; } break; } } mirrors.push_back(vp); } std::vector> res; for (const auto &v : mirrors) { vec rv = vec::Zero(); // ortho proj for (int i = 0; i < std::min(v.size(), (size_t) N); ++i) { rv[i] = v[i]; } res.push_back(rv); } return res; } template vec stereo(const vec &v) { vec r; for (int i = 0; i < N; ++i) { r[i] = v[i] / (1 - v[N]); } return r; } template vec ortho(const vec &v) { vec r; for (int i = 0; i < N; ++i) { r[i] = v[i]; } return r; } template V project(const V &vec, const V &target) { return vec.dot(target) / target.dot(target) * target; } template V reflect(const V &a, const V &axis) { return a - 2.f * project(a, axis); } template V gram_schmidt_last(std::vector vecs) { for (int i = 0; i < vecs.size(); ++i) { for (int j = 0; j < i; ++j) { vecs[i] -= project(vecs[i], vecs[j]); } } return vecs[vecs.size() - 1].normalized(); } template V barycentric(const std::vector &basis, const C &coords) { V res = V::Zero(); int N = std::min((int) basis.size(), (int) coords.rows()); for (int i = 0; i < N; ++i) { res += basis[i] * coords[i]; } return res; } template std::vector plane_intersections(std::vector normals) { std::vector results(normals.size()); for (int i = 0; i < normals.size(); ++i) { std::rotate(normals.begin(), normals.begin() + 1, normals.end()); results[i] = gram_schmidt_last(normals); } return results; } template mat rot(int u, int v, float theta) { mat res = mat::Identity(); res(u, u) = std::cos(theta); res(u, v) = std::sin(theta); res(v, u) = -std::sin(theta); res(v, v) = std::cos(theta); return res; }