42#ifndef UFO_CONTAINER_TREE_RENDER_HPP
43#define UFO_CONTAINER_TREE_RENDER_HPP
46#include <ufo/container/tree/node.hpp>
47#include <ufo/container/tree/predicate.hpp>
48#include <ufo/container/tree/trace_result.hpp>
49#include <ufo/utility/type_traits.hpp>
50#include <ufo/vision/camera.hpp>
61template <
class Tree,
class Predicate,
62 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
65 Predicate
const& pred)
67 return render(tree.index(), tree, camera, pred);
70template <
class Tree,
class NodeType,
class Predicate,
71 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
72 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true>
76 Predicate
const& pred)
82 return tree.trace(node, camera.rays(), pred);
86 static_assert(dependent_false_v<Tree>,
"Does not support dimensions");
91 class ExecutionPolicy,
class Tree,
class Predicate,
92 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
93 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
94[[nodiscard]] Image<TraceResult<
Tree::dimensions()>> render(ExecutionPolicy&& policy,
97 Predicate
const& pred)
99 return render(std::forward<ExecutionPolicy>(policy), tree, tree.index(), camera, pred);
103 class ExecutionPolicy,
class Tree,
class NodeType,
class Predicate,
104 std::enable_if_t<Tree::template is_node_type_v<NodeType>,
bool> =
true,
105 std::enable_if_t<pred::is_pred_v<Predicate>,
bool> =
true,
106 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
107[[nodiscard]] Image<TraceResult<
Tree::dimensions()>> render(ExecutionPolicy&& policy,
109 NodeType
const& node,
111 Predicate
const& pred)
117 auto rays = camera.rays();
118 tree.trace(std::forward<ExecutionPolicy>(policy), node, rays.begin(), rays.end(),
119 image.begin(), pred, camera.near_clip, camera.far_clip);
124 static_assert(dependent_false_v<Tree>,
"Does not support dimensions");
128template <
class Map,
class Predicate = pred::True,
129 std::enable_if_t<pred::is_pred_v<Predicate, Map>,
bool> =
true>
130[[nodiscard]] std::pair<Image<typename Map::Node>, Image<float>> renderGPU(
131 Map const& map,
Camera const& camera, Predicate
const& pred = pred::True{},
132 bool only_exists =
true)
134 return renderGPU(map.code(), map, camera, pred, only_exists);
137template <
class NodeType,
class Map,
class Predicate = pred::True,
138 std::enable_if_t<Map::template is_node_type_v<NodeType>,
bool> =
true,
139 std::enable_if_t<pred::is_pred_v<Predicate, Map>,
bool> =
true>
140[[nodiscard]] std::pair<Image<typename Map::Node>, Image<float>> renderGPU(
141 NodeType
const& node,
Map const& map,
Camera const& camera,
142 Predicate pred = pred::True{},
bool only_exists =
true)
144 using Filter = pred::Filter<Predicate>;
146 Filter::init(pred, map);
154 std::pair<Image<typename Map::Node>, Image<float>> ret;
156 auto& nodes = ret.first;
157 auto& depths = ret.second;
159 nodes.resize(camera.cols, camera.rows);
160 depths.resize(camera.cols, camera.rows);
172template <
class InnerFun,
class HitFun,
class T>
173void render(
Camera const& camera, Image<T>& image, InnerFun inner_f, HitFun hit_f,
176 render(Base::index(), camera, image, inner_f, hit_f, miss);
179template <
class InnerFun,
class HitFun,
class T>
180[[nodiscard]] Image<T> render(
Camera const& camera, std::size_t rows, std::size_t cols,
181 InnerFun inner_f, HitFun hit_f, T
const& miss)
183 return render(Base::index(), camera, rows, cols, inner_f, hit_f, miss);
186template <
class NodeType,
class InnerFun,
class HitFun,
class T,
187 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
188void render(NodeType node,
Camera const& camera, Image<T>& image, InnerFun inner_f,
189 HitFun hit_f, T
const& miss)
191 Image<Ray3> rays = camera.rays(image.rows(), image.cols());
192 trace3D(node, rays.begin(), rays.end(), image.begin(), inner_f, hit_f, miss);
195template <
class NodeType,
class InnerFun,
class HitFun,
class T,
196 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
197[[nodiscard]] Image<T> render(NodeType node,
Camera const& camera, std::size_t rows,
198 std::size_t cols, InnerFun inner_f, HitFun hit_f,
201 Image<T> image(rows, cols);
202 render(node, camera, image, inner_f, hit_f, miss);
207 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
208 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
209void render(ExecutionPolicy&& policy,
Camera const& camera, Image<T>& image,
210 InnerFun inner_f, HitFun hit_f, T
const& miss)
212 render(std::forward<ExecutionPolicy>(policy), Base::index(), camera, image, inner_f,
217 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
218 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
219[[nodiscard]] Image<T> render(ExecutionPolicy&& policy,
Camera const& camera,
220 std::size_t rows, std::size_t cols, InnerFun inner_f,
221 HitFun hit_f, T
const& miss)
223 return render(std::forward<ExecutionPolicy>(policy), Base::index(), camera, rows, cols,
224 inner_f, hit_f, miss);
227template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
228void render(ExecutionPolicy&& policy, NodeType node,
Camera const& camera,
229 Image<T>& image, InnerFun inner_f, HitFun hit_f, T
const& miss)
231 auto rows = image.rows();
232 auto cols = image.cols();
234 Image<Ray3> rays = camera.rays(policy, rows, cols);
236 trace3D(std::forward<ExecutionPolicy>(policy), node, rays.begin(), rays.end(),
237 image.begin(), inner_f, hit_f, miss);
240template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
241[[nodiscard]] Image<T> render(ExecutionPolicy&& policy, NodeType node,
242 Camera const& camera, std::size_t rows, std::size_t cols,
243 InnerFun inner_f, HitFun hit_f, T
const& miss)
245 Image<T> image(rows, cols);
246 render(policy, node, camera, image, inner_f, hit_f, miss);
250template <
class NodeType,
class InputIt,
class OutputIt,
class InnerFun,
class HitFun,
251 class T, std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
252OutputIt trace3D(NodeType node, InputIt first, InputIt last, OutputIt d_first,
253 InnerFun inner_f, HitFun hit_f, T
const& miss)
255 if constexpr (!std::is_same_v<Index, std::decay_t<NodeType>>) {
257 if (!Base::exists(node)) {
262 Index n = Base::index(node);
264 auto center = Base::center(n);
265 auto half_length = Base::halfLength(n);
267 return std::transform(first, last, d_first, [&](
auto const& ray) {
268 return trace3D(n, center, half_length, ray, inner_f, hit_f, miss);
272template <
class ExecutionPolicy,
class NodeType,
class RandomIt1,
class RandomIt2,
273 class InnerFun,
class HitFun,
class T>
274RandomIt2 trace3D(ExecutionPolicy&& policy, NodeType node, RandomIt1 first,
275 RandomIt1 last, RandomIt2 d_first, InnerFun inner_f, HitFun hit_f,
278 if constexpr (std::is_same_v<execution::sequenced_policy,
279 std::decay_t<ExecutionPolicy>>) {
280 return trace3D(node, first, last, d_first, inner_f, hit_f, miss);
283#if !defined(UFO_TBB) && !defined(UFO_OMP)
284 return trace3D(node, first, last, d_first, inner_f, hit_f, miss);
287 if constexpr (!std::is_same_v<Index, std::decay_t<NodeType>>) {
289 if (!Base::exists(node)) {
294 Index n = Base::index(node);
296 auto center = Base::center(n);
297 auto half_length = Base::halfLength(n);
300 return std::transform(
301 std::forward<ExecutionPolicy>(policy), first, last, d_first, [&](
auto const& ray) {
302 return trace3D(n, center, half_length, ray, inner_f, hit_f, miss);
304#elif defined(UFO_OMP)
305 std::size_t size = std::distance(first, last);
307#pragma omp parallel for
308 for (std::size_t i = 0; i != size; ++i) {
309 auto const& ray = first[i];
310 d_first[i] = trace3D(n, center, half_length, ray, inner_f, hit_f, miss);
313 return std::next(d_first, size);
317template <
class InnerFun,
class HitFun,
class T>
318[[nodiscard]] T trace3D(Index node, Vec2f
const& center,
float half_length,
319 Ray3
const& ray, InnerFun inner_f, HitFun hit_f,
322 auto wrapped_inner_f = [&ray, inner_f](Index node,
float distance) {
323 return inner_f(node, ray,
distance);
326 auto wrapped_hit_f = [&ray, hit_f](Index node,
float distance) {
330 if (0.0f == ray.origin.z && 0.0f == ray.direction.z) {
332 Ray2 ray2(Vec2f(ray.origin), Vec2f(ray.direction));
333 auto params = Base::traceInit(ray2, center, half_length);
334 return Base::trace(node, params, wrapped_inner_f, wrapped_hit_f, miss);
335 }
else if (0.0f == ray.direction.z ||
sign(ray.origin.z) ==
sign(ray.direction.z)) {
341 float t = -ray.origin.z / ray.direction.z;
342 Vec2f v = Vec2f(ray.origin) + t * Vec2f(ray.direction);
343 auto code = Base::code(v);
345 if (Base::code(node) != code.toDepth(Base::depth(node))) {
350 for (
int depth = Base::depth(node); 0 < depth; --depth) {
351 if (
auto [hit, value] = wrapped_hit_f(node, t); hit) {
353 }
else if (Base::isLeaf(node) || !wrapped_inner_f(node, t)) {
357 node = Base::child(node, code.offset(depth - 1));
360 if (
auto [hit, value] = wrapped_hit_f(node, t); hit) {
371template <
class InnerFun,
class HitFun,
class T>
372void render(
Camera const& camera, Image<T>& image, InnerFun inner_f, HitFun hit_f,
375 render(Base::index(), camera, image, inner_f, hit_f, miss);
378template <
class InnerFun,
class HitFun,
class T>
379[[nodiscard]] Image<T> render(
Camera const& camera, std::size_t rows, std::size_t cols,
380 InnerFun inner_f, HitFun hit_f, T
const& miss)
382 return render(Base::index(), camera, rows, cols, inner_f, hit_f, miss);
385template <
class NodeType,
class InnerFun,
class HitFun,
class T,
386 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
387void render(NodeType node,
Camera const& camera, Image<T>& image, InnerFun inner_f,
388 HitFun hit_f, T
const& miss)
390 Image<Ray3> rays = camera.rays(image.rows(), image.cols());
391 Base::trace(node, rays.begin(), rays.end(), image.begin(), inner_f, hit_f, miss);
394template <
class NodeType,
class InnerFun,
class HitFun,
class T,
395 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
396[[nodiscard]] Image<T> render(NodeType node,
Camera const& camera, std::size_t rows,
397 std::size_t cols, InnerFun inner_f, HitFun hit_f,
400 Image<T> image(rows, cols);
401 render(node, camera, image, inner_f, hit_f, miss);
406 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
407 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
408void render(ExecutionPolicy&& policy,
Camera const& camera, Image<T>& image,
409 InnerFun inner_f, HitFun hit_f, T
const& miss)
411 render(std::forward<ExecutionPolicy>(policy), Base::index(), camera, image, inner_f,
416 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
417 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
418[[nodiscard]] Image<T> render(ExecutionPolicy&& policy,
Camera const& camera,
419 std::size_t rows, std::size_t cols, InnerFun inner_f,
420 HitFun hit_f, T
const& miss)
422 return render(std::forward<ExecutionPolicy>(policy), Base::index(), camera, rows, cols,
423 inner_f, hit_f, miss);
426template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
427void render(ExecutionPolicy&& policy, NodeType node,
Camera const& camera,
428 Image<T>& image, InnerFun inner_f, HitFun hit_f, T
const& miss)
430 auto rows = image.rows();
431 auto cols = image.cols();
433 Image<Ray3> rays = camera.rays(policy, rows, cols);
435 constexpr std::size_t
const step_size = 1;
437 if constexpr (1 == step_size) {
438 Base::trace(std::forward<ExecutionPolicy>(policy), node, rays.begin(), rays.end(),
439 image.begin(), inner_f, hit_f, miss);
444 Index n = Base::index(node);
446 auto center = Base::center(n);
447 auto half_length = Base::halfLength(n);
449 std::vector<std::size_t> row_idx(rows);
450 std::iota(row_idx.begin(), row_idx.end(), 0);
495 static std::size_t s{};
498 std::for_each(policy, row_idx.begin(), row_idx.end(), [&](std::size_t row) {
499 std::size_t offset = (row + s) % step_size;
501 for (std::size_t col = offset; cols > col; col += step_size) {
502 auto const& ray = rays(row, col);
504 auto wrapped_inner_f = [inner_f, &ray](auto node, auto distance) {
505 return inner_f(node, ray, distance);
508 auto wrapped_hit_f = [hit_f, &ray](auto node, auto distance) {
509 return hit_f(node, ray, distance);
514 auto params = Base::traceInit(ray, center, half_length);
515 image(row, col) = Base::trace(n, params, wrapped_inner_f, wrapped_hit_f, miss);
522 if constexpr (2 == step_size) {
585template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
586[[nodiscard]] Image<T> render(ExecutionPolicy&& policy, NodeType node,
587 Camera const& camera, std::size_t rows, std::size_t cols,
588 InnerFun inner_f, HitFun hit_f, T
const& miss)
590 Image<T> image(rows, cols);
591 render(policy, node, camera, image, inner_f, hit_f, miss);
599template <
class InnerFun,
class HitFun,
class T>
600void render(
float w,
Camera const& camera, Image<T>& image, InnerFun inner_f,
601 HitFun hit_f, T
const& miss)
603 render(w, Base::index(), camera, image, inner_f, hit_f, miss);
606template <
class InnerFun,
class HitFun,
class T>
607[[nodiscard]] Image<T> render(
float w,
Camera const& camera, std::size_t rows,
608 std::size_t cols, InnerFun inner_f, HitFun hit_f,
611 return render(Base::index(), w, camera, rows, cols, inner_f, hit_f, miss);
614template <
class NodeType,
class InnerFun,
class HitFun,
class T,
615 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
616void render(NodeType node,
float w,
Camera const& camera, Image<T>& image,
617 InnerFun inner_f, HitFun hit_f, T
const& miss)
619 Image<Ray3> rays = camera.rays(image.rows(), image.cols());
620 Image<Ray4> rays4d(image.rows(), image.cols());
621 for (std::size_t row{}; image.rows() > row; ++row) {
622 for (std::size_t col{}; image.cols() > col; ++col) {
624 Ray4(Vec4f(rays(row, col).origin, w), Vec4f(rays(row, col).direction, 0));
627 Base::trace(node, rays4d.begin(), rays4d.end(), image.begin(), inner_f, hit_f, miss);
630template <
class NodeType,
class InnerFun,
class HitFun,
class T,
631 std::enable_if_t<Base::template is_node_type_v<NodeType>,
bool> =
true>
632[[nodiscard]] Image<T> render(NodeType node,
float w,
Camera const& camera,
633 std::size_t rows, std::size_t cols, InnerFun inner_f,
634 HitFun hit_f, T
const& miss)
636 Image<T> image(rows, cols);
637 render(node, w, camera, image, inner_f, hit_f, miss);
642 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
643 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
644void render(ExecutionPolicy&& policy,
float w,
Camera const& camera, Image<T>& image,
645 InnerFun inner_f, HitFun hit_f, T
const& miss)
647 render(std::forward<ExecutionPolicy>(policy), Base::index(), w, camera, image, inner_f,
652 class ExecutionPolicy,
class InnerFun,
class HitFun,
class T,
653 std::enable_if_t<execution::is_execution_policy_v<ExecutionPolicy>,
bool> =
true>
654[[nodiscard]] Image<T> render(ExecutionPolicy&& policy,
float w,
Camera const& camera,
655 std::size_t rows, std::size_t cols, InnerFun inner_f,
656 HitFun hit_f, T
const& miss)
658 return render(std::forward<ExecutionPolicy>(policy), Base::index(), w, camera, rows,
659 cols, inner_f, hit_f, miss);
662template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
663void render(ExecutionPolicy&& policy, NodeType node,
float w,
Camera const& camera,
664 Image<T>& image, InnerFun inner_f, HitFun hit_f, T
const& miss)
666 auto rows = image.rows();
667 auto cols = image.cols();
669 Image<Ray3> rays = camera.rays(policy, rows, cols);
670 Image<Ray4> rays4d(image.rows(), image.cols());
671 for (std::size_t row{}; image.rows() > row; ++row) {
672 for (std::size_t col{}; image.cols() > col; ++col) {
674 Ray4(Vec4f(rays(row, col).origin, w), Vec4f(rays(row, col).direction, 0));
678 Base::trace(std::forward<ExecutionPolicy>(policy), node, rays4d.begin(), rays4d.end(),
679 image.begin(), inner_f, hit_f, miss);
682template <
class ExecutionPolicy,
class NodeType,
class InnerFun,
class HitFun,
class T>
683[[nodiscard]] Image<T> render(ExecutionPolicy&& policy, NodeType node,
float w,
684 Camera const& camera, std::size_t rows, std::size_t cols,
685 InnerFun inner_f, HitFun hit_f, T
const& miss)
687 Image<T> image(rows, cols);
688 render(policy, node, w, camera, image, inner_f, hit_f, miss);
static constexpr std::size_t dimensions() noexcept
Returns the number of dimensions of the tree (i.e., 1 = binary tree, 2 = quadtree,...
constexpr int sign(T val) noexcept
Returns the sign of a value.
All vision-related classes and functions.
constexpr auto distance(A const &a, B const &b)
Computes the minimum distance between two shapes.