11 template <
typename value_t,
size_t DIM,
size_t SIDES>
12 template <
size_t D, std::enable_if_t<D == 2,
int>>
17 using rotation_t = Eigen::Rotation2D<value_type>;
19 static_assert(SIDES == 2,
"2D frustum can only have 2 sides");
20 assert(opening_angle <
M_PI);
24 Eigen::Rotation2D<value_type> rot(angle);
27 VertexType normal1 = rotation_t(normal_angle) * VertexType::UnitX();
28 VertexType normal2 = rotation_t(-normal_angle) * VertexType::UnitX();
30 m_normals = {rot * VertexType::UnitX(), rot * normal1, rot * normal2};
33 template <
typename value_t,
size_t DIM,
size_t SIDES>
34 template <
size_t D, std::enable_if_t<D == 3,
int>>
36 const VertexType&
dir,
37 value_type opening_angle)
39 static_assert(SIDES > 2,
"3D frustum must have 3 or more sides");
40 assert(opening_angle <
M_PI);
41 using angle_axis_t = Eigen::AngleAxis<value_type>;
47 transform = (Eigen::Quaternion<value_type>().setFromTwoVectors(ldir, dir));
53 rot = angle_axis_t(phi_sep, ldir);
55 value_type half_opening_angle = opening_angle / 2.;
56 auto calculate_normal =
58 const VertexType tilt_axis = -1 * out.cross(ldir);
59 return (-1 * (angle_axis_t(half_opening_angle, tilt_axis) * out))
64 m_normals[1] = calculate_normal(current_outward);
66 for (
size_t i = 1; i <
sides; i++) {
67 current_outward = rot * current_outward;
68 m_normals[i + 1] = calculate_normal(current_outward);
76 template <
typename value_t,
size_t DIM,
size_t SIDES>
77 template <
size_t D, std::enable_if_t<D == 3,
int>>
80 static_assert(DIM == 3,
"Drawing is only supported in 3D");
87 VertexType far_center = m_normals[0] * far_distance;
88 std::array<std::pair<VertexType, VertexType>, SIDES> planeFarIXs;
90 auto ixPlanePlane = [](
const auto&
n1,
const auto& p1,
const auto& n2,
91 const auto& p2) -> std::pair<VertexType, VertexType> {
93 const double j = (n2.dot(p2 - p1)) / (n2.dot(
n1.cross(m)));
98 auto ixLineLine = [](
const auto& p1,
const auto&
d1,
const auto& p2,
104 for (
size_t i = 1; i < n_normals; i++) {
106 ixPlanePlane(far_normal, far_center, m_normals[i], VertexType::Zero());
107 planeFarIXs.at(i - 1) = ixLine;
110 std::array<VertexType, SIDES> points;
112 for (
size_t i = 0; i < std::size(planeFarIXs); i++) {
113 size_t j = (i + 1) % std::size(planeFarIXs);
114 const auto& l1 = planeFarIXs.at(i);
115 const auto& l2 = planeFarIXs.at(j);
117 m_origin + ixLineLine(l1.second, l1.first, l2.second, l2.first);
121 for (
size_t i = 0; i < std::size(points); i++) {
122 size_t j = (i + 1) % std::size(points);
124 std::vector<VertexType>({m_origin, points.at(i), points.at(j)}));
128 template <
typename value_t,
size_t DIM,
size_t SIDES>
129 template <
size_t D, std::enable_if_t<D == 2,
int>>
135 static_assert(DIM == 2,
"SVG is only supported in 2D");
143 trf = trf * Eigen::Scaling(
VertexType(1, -1));
146 std::array<std::string, 3> colors({
"orange",
"blue",
"red"});
154 os <<
"x1=\"" << left.x() <<
"\" ";
155 os <<
"y1=\"" << left.y() <<
"\" ";
156 os <<
"x2=\"" << right.x() <<
"\" ";
157 os <<
"y2=\"" << right.y() <<
"\" ";
159 os <<
" stroke=\"" << color <<
"\" stroke-width=\"" <<
width <<
"\"/>\n";
165 os <<
"cx=\"" << p.x() <<
"\" cy=\"" << p.y() <<
"\" r=\"" <<
r <<
"\"";
166 os <<
" fill=\"" << color <<
"\"";
174 const vec3 p1(p1_2.x(), p1_2.y(), 0);
175 const vec3 p2(p2_2.x(), p2_2.y(), 0);
176 const vec3
d1(d1_2.x(), d1_2.y(), 0);
177 const vec3
d2(d2_2.x(), d2_2.y(), 0);
183 value_type dot = num.normalized().dot(den.normalized());
184 if (
std::abs(dot) - 1 < 1
e-9 && dot < 0) {
188 const vec3
p = p1 + f * (num.norm() / den.norm()) *
d1;
190 return {p.x(), p.y()};
193 const VertexType far_dir = {m_normals[0].y(), -m_normals[0].x()};
194 const VertexType far_point = m_normals[0] * far_distance;
196 std::array<VertexType, 2> points;
198 for (
size_t i = 1; i < n_normals; i++) {
199 VertexType plane_dir(m_normals[i].
y(), -m_normals[i].
x());
201 const VertexType ix = ixLineLine(far_point, far_dir, {0, 0}, plane_dir);
202 draw_point(m_origin + ix,
"black", 3);
203 draw_line(m_origin, m_origin + ix,
"black", 2);
204 points.at(i - 1) = ix;
207 draw_line(m_origin + points.at(0), m_origin + points.at(1),
"black", 2);
209 draw_line(m_origin, m_origin + m_normals[0] * 2, colors[0], 3);
211 draw_point({0, 0},
"yellow", 5);
212 draw_point(m_origin,
"green", 5);
217 template <
typename value_t,
size_t DIM,
size_t SIDES>
221 const auto& rot = trf.rotation();
223 std::array<VertexType, n_normals> new_normals;
224 for (
size_t i = 0; i < n_normals; i++) {
225 new_normals[i] = rot * m_normals[i];