NavMap
Loading...
Searching...
No Matches
NavMap.hpp
Go to the documentation of this file.
1// Copyright 2025 Intelligent Robotics Lab
2//
3// This file is part of the project Easy Navigation (EasyNav in short)
4// licensed under the GNU General Public License v3.0.
5// See <http://www.gnu.org/licenses/> for details.
6//
7// Easy Navigation program is free software: you can redistribute it and/or modify
8// it under the terms of the GNU General Public License as published by
9// the Free Software Foundation, either version 3.0, or
10// (at your option) any later version.
11//
12// This program is distributed in the hope that it will be useful,
13// but WITHOUT ANY WARRANTY; without even the implied warranty of
14// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15// GNU General Public License for more details.
16//
17// You should have received a copy of the GNU General Public License
18// along with this program. If not, see <http://www.gnu.org/licenses/>.
19
20
21#ifndef NAVMAP_CORE__NAVMAP_HPP
22#define NAVMAP_CORE__NAVMAP_HPP
23
40
41#include <vector>
42#include <memory>
43#include <unordered_map>
44#include <optional>
45#include <string>
46#include <array>
47#include <limits>
48#include <cmath>
49#include <cstdint>
50#include <type_traits>
51#include <deque>
52#include <algorithm>
53
54#include <Eigen/Core>
56
57namespace navmap
58{
59
61using PointId = uint32_t;
63using NavCelId = uint32_t;
64
65// -----------------------------------------------------------------------------
66// Core data arrays
67// -----------------------------------------------------------------------------
68
79{
80 std::vector<float> x;
81 std::vector<float> y;
82 std::vector<float> z;
83
85 inline size_t size() const {return x.size();}
86
93 inline Eigen::Vector3f at(PointId id) const
94 {
95 return {x[id], y[id], z[id]};
96 }
97};
98
104struct Colors
105{
106 std::vector<uint8_t> r;
107 std::vector<uint8_t> g;
108 std::vector<uint8_t> b;
109 std::vector<uint8_t> a;
110};
111
112// -----------------------------------------------------------------------------
113// Layers (dynamic per-NavCel attributes)
114// -----------------------------------------------------------------------------
115
121enum class LayerType : uint8_t { U8 = 0, F32 = 1, F64 = 2 };
122
129{
130 virtual ~LayerViewBase() = default;
131
133 virtual LayerType type() const = 0;
134
136 virtual const std::string & name() const = 0;
137
139 virtual size_t size() const = 0;
140
142 virtual std::uint64_t content_hash() const = 0;
143
145 void mark_dirty() const noexcept {hash_dirty_ = true;}
146
147protected:
148 mutable bool hash_dirty_{true};
149 mutable std::uint64_t hash_cache_{0};
150};
151
158template<typename T>
159struct LayerView : LayerViewBase
160{
161 std::string name_;
162 std::vector<T> data_;
164
171 LayerView(std::string name, size_t nitems, LayerType t)
172 : name_(std::move(name)), data_(nitems), type_(t) {}
173
174 LayerType type() const override {return type_;}
175 const std::string & name() const override {return name_;}
176 size_t size() const override {return data_.size();}
177
180 T & operator[](NavCelId cid) {return data_[cid];}
181 const T & operator[](NavCelId cid) const {return data_[cid];}
183
185 std::vector<T> & data() {return data_;}
187 const std::vector<T> & data() const {return data_;}
188
191 std::vector<T> & mutable_data() const
192 {
193 hash_dirty_ = true; return const_cast<std::vector<T> &>(data_);
194 }
195 void set_data(const std::vector<T> & v) {data_ = v; hash_dirty_ = true;}
196 std::uint64_t content_hash() const override;
198};
199
201namespace detail
202{
203inline std::uint64_t fnv1a64_bytes(
204 const void * data, std::size_t n,
205 std::uint64_t seed = 1469598103934665603ULL)
206{
207 const auto * p = static_cast<const std::uint8_t *>(data);
208 std::uint64_t h = seed;
209 for (std::size_t i = 0; i < n; ++i) {
210 h ^= p[i]; h *= 1099511628211ULL;
211 }
212 return h;
213}
214} // namespace detail
216
217template<typename T>
218std::uint64_t LayerView<T>::content_hash() const
219{
220 if (!hash_dirty_) {return hash_cache_;}
221 const std::size_t n = data_.size();
222 std::uint64_t h = navmap::detail::fnv1a64_bytes(&n, sizeof(n));
223 if (n) {
224 static_assert(std::is_trivially_copyable<T>::value,
225 "LayerView<T> requires trivially copyable T.");
226 h = navmap::detail::fnv1a64_bytes(data_.data(), n * sizeof(T), h);
227 }
228 hash_cache_ = h;
229 hash_dirty_ = false;
230 return hash_cache_;
231}
232
241public:
254 template<typename T>
255 std::shared_ptr<LayerView<T>> add_or_get(
256 const std::string & name,
257 size_t nitems,
258 LayerType type)
259 {
260 auto it = layers_.find(name);
261 if (it != layers_.end()) {
262 return std::dynamic_pointer_cast<LayerView<T>>(it->second);
263 }
264 auto view = std::make_shared<LayerView<T>>(name, nitems, type);
265 layers_[name] = view;
266 return view;
267 }
268
274 std::shared_ptr<LayerViewBase> get(const std::string & name) const
275 {
276 auto it = layers_.find(name);
277 return it == layers_.end() ? nullptr : it->second;
278 }
279
284 std::vector<std::string> list() const
285 {
286 std::vector<std::string> out;
287 out.reserve(layers_.size());
288 for (const auto & kv : layers_) {
289 out.push_back(kv.first);
290 }
291 return out;
292 }
293
298 bool remove(const std::string & name)
299 {
300 return layers_.erase(name) > 0;
301 }
302
310 void resize_all(size_t nitems)
311 {
312 for (auto & kv : layers_) {
313 if (auto v = std::dynamic_pointer_cast<LayerView<uint8_t>>(kv.second)) {
314 v->data_.resize(nitems);
315 kv.second->mark_dirty();
316 continue;
317 }
318 if (auto v = std::dynamic_pointer_cast<LayerView<float>>(kv.second)) {
319 v->data_.resize(nitems);
320 kv.second->mark_dirty();
321 continue;
322 }
323 if (auto v = std::dynamic_pointer_cast<LayerView<double>>(kv.second)) {
324 v->data_.resize(nitems);
325 kv.second->mark_dirty();
326 continue;
327 }
328 }
329 }
330
331private:
332 std::unordered_map<std::string, std::shared_ptr<LayerViewBase>> layers_;
333};
334
341{
342 std::string description;
343 std::string unit;
344 bool per_cell{true};
345};
346
347// -----------------------------------------------------------------------------
348// Mesh cells and acceleration
349// -----------------------------------------------------------------------------
350
360struct NavCel
361{
362 PointId v[3]{0, 0, 0};
363 Eigen::Vector3f normal{0.0f, 0.0f, 1.0f};
364 float area{0.0f};
366 std::numeric_limits<uint32_t>::max(),
367 std::numeric_limits<uint32_t>::max(),
368 std::numeric_limits<uint32_t>::max()
369 };
370 uint32_t layer_dirty_mask{0};
371};
372
379{
381 int left{-1};
382 int right{-1};
383 int start{0};
384 int count{0};
385 bool is_leaf() const {return count > 0;}
386};
387
395{
396 std::string frame_id;
397 std::vector<NavCelId> navcels;
399 std::vector<int> prim_indices;
400 std::vector<BVHNode> bvh;
401};
402
403// -----------------------------------------------------------------------------
404// Rays
405// -----------------------------------------------------------------------------
406
412struct Ray
413{
414 Eigen::Vector3f o;
415 Eigen::Vector3f d;
416};
417
423struct RayHit
424{
425 bool hit{false};
426 size_t surface{0};
428 float t{0.0f};
429 Eigen::Vector3f p;
430};
431
432// -----------------------------------------------------------------------------
433// Helpers (type → LayerType mapping)
434// -----------------------------------------------------------------------------
435
437template<typename T> inline constexpr LayerType layer_type_tag();
438template<> inline constexpr LayerType layer_type_tag<uint8_t>() {return LayerType::U8;}
439template<> inline constexpr LayerType layer_type_tag<float>() {return LayerType::F32;}
440template<> inline constexpr LayerType layer_type_tag<double>() {return LayerType::F64;}
441
446
447// -----------------------------------------------------------------------------
448// NavMap: public API
449// -----------------------------------------------------------------------------
450
465class NavMap {
466public:
468 std::optional<Colors> colors;
469 std::vector<NavCel> navcels;
470 std::vector<Surface> surfaces;
472 std::unordered_map<std::string, LayerMeta> layer_meta;
473
475 NavMap();
476
478 NavMap(const NavMap & other);
479
488
496 NavMap & operator=(const NavMap & other);
497
502 NavMap & operator=(NavMap && other) noexcept;
503
505 bool has_same_geometry(const NavMap & other) const;
506
513 void build_adjacency();
514
520
526 std::array<NavCelId, 3> get_neighbors(NavCelId cid) const
527 {
528 return {navcels[cid].neighbor[0],
529 navcels[cid].neighbor[1],
530 navcels[cid].neighbor[2]};
531 }
532
542 bool raycast(
543 const Eigen::Vector3f & o,
544 const Eigen::Vector3f & d,
545 NavCelId & hit_cid,
546 float & t,
547 Eigen::Vector3f & hit_pt) const;
548
555 void raycast_many(
556 const std::vector<Ray> & rays,
557 std::vector<RayHit> & out,
558 bool first_hit_only = true) const;
559
560 // --- Per-NavCel layer value access ---
561
569 template<typename T>
570 T navcel_value(NavCelId cid, const LayerView<T> & layer) const
571 {
572 return layer[cid];
573 }
574
585 {
586 std::optional<NavCelId> hint_cid;
587 std::optional<size_t> hint_surface;
588 float planar_eps = 1e-4f;
589 float height_eps = 0.50f;
590 bool use_downward_ray = true;
591 };
592
605 bool locate_navcel(
606 const Eigen::Vector3f & p_world,
607 size_t & surface_idx,
608 NavCelId & cid,
609 Eigen::Vector3f & bary,
610 Eigen::Vector3f * hit_pt) const;
611
629 const Eigen::Vector3f & p_world,
630 size_t & surface_idx,
631 NavCelId & cid,
632 Eigen::Vector3f & bary,
633 Eigen::Vector3f * hit_pt,
634 const LocateOpts & opts) const;
635
650 bool closest_navcel(
651 const Eigen::Vector3f & p_world,
652 size_t & surface_idx,
653 NavCelId & cid,
654 Eigen::Vector3f & closest_point,
655 float & sqdist,
656 int restrict_surface = -1) const;
657
658 // ---- Convenience: construction & editing (additive, backward-compatible) ----
659
663 std::size_t create_surface(std::string frame_id);
664
668 Surface create_surface_obj(const std::string & frame_id) const;
669
671 std::size_t add_surface(const Surface & s);
672
674 std::size_t add_surface(Surface && s);
675
679 bool remove_surface(std::size_t surface_index);
680
682 uint32_t add_vertex(const Eigen::Vector3f & p);
683
688 NavCelId add_navcel(uint32_t v0, uint32_t v1, uint32_t v2);
689
691 void add_navcel_to_surface(std::size_t surface_index, NavCelId cid);
692
694 Eigen::Vector3f navcel_centroid(NavCelId cid) const;
695
697 std::vector<NavCelId> navcel_neighbors(NavCelId cid) const;
698
699 // ---- Layers (per-NavCel) convenience ----
700
715 template<typename T>
716 std::shared_ptr<LayerView<T>> add_layer(
717 const std::string & name,
718 const std::string & description = {},
719 const std::string & unit = {},
720 T default_value = T{})
721 {
722 auto v = layers.add_or_get<T>(name, navcels.size(), layer_type_tag<T>());
723 if (v->data().size() != navcels.size()) {
724 v->data().assign(navcels.size(), default_value);
725 }
726 layer_meta[name] = LayerMeta{description, unit, true};
727 return v;
728 }
729
731 bool has_layer(const std::string & name) const;
732
734 std::size_t layer_size(const std::string & name) const;
735
737 std::string layer_type_name(const std::string & name) const;
738
746 template<typename T>
747 void layer_set(const std::string & name, NavCelId cid, T value)
748 {
749 auto view = layers.add_or_get<T>(name, navcels.size(), layer_type_tag<T>());
750 if (static_cast<size_t>(cid) < view->data().size()) {
751 view->data()[cid] = value;
752 view->mark_dirty();
753 }
754 }
755
771 template<typename T>
772 T layer_get(const std::string & name, NavCelId cid, T def = T{}) const
773 {
774 if (auto base = layers.get(name)) {
775 if (auto view = std::dynamic_pointer_cast<LayerView<T>>(base)) {
776 const auto & buf = view->data();
777 if (static_cast<size_t>(cid) < buf.size()) {
778 return buf[cid];
779 }
780 return def;
781 }
782 }
783 // Fallback: try to fetch as double from any stored type and convert
784 double v;
785 if (auto base = layers.get(name)) {
786 if (auto v8 = std::dynamic_pointer_cast<LayerView<uint8_t>>(base)) {
787 const auto & buf = v8->data();
788 if (static_cast<size_t>(cid) >= buf.size()) {return def;}
789 v = static_cast<double>(buf[cid]);
790 } else if (auto vf = std::dynamic_pointer_cast<LayerView<float>>(base)) {
791 const auto & buf = vf->data();
792 if (static_cast<size_t>(cid) >= buf.size()) {return def;}
793 v = static_cast<double>(buf[cid]);
794 } else if (auto vd = std::dynamic_pointer_cast<LayerView<double>>(base)) {
795 const auto & buf = vd->data();
796 if (static_cast<size_t>(cid) >= buf.size()) {return def;}
797 v = buf[cid];
798 } else {
799 return def;
800 }
801 } else {
802 return def;
803 }
804
805 if constexpr (std::is_floating_point_v<T>) {
806 return static_cast<T>(v);
807 } else if constexpr (std::is_integral_v<T>) {
808 double lo = 0.0;
809 double hi = static_cast<double>(std::numeric_limits<T>::max());
810 double vv = v < lo ? lo : (v > hi ? hi : v);
811 return static_cast<T>(std::llround(vv));
812 } else {
813 static_assert(sizeof(T) == 0, "Unsupported layer type");
814 }
815 }
816
822 std::optional<LayerMeta> get_layer_meta(const std::string & name) const;
823
828 std::vector<std::string> list_layers() const;
829
839 double sample_layer_at(
840 const std::string & name,
841 const Eigen::Vector3f & p_world,
842 double def = std::numeric_limits<double>::quiet_NaN()) const;
843
851 template<typename T>
852 void layer_clear(const std::string & name, T value = T{})
853 {
854 auto view = layers.add_or_get<T>(name, navcels.size(), layer_type_tag<T>());
855 std::fill(view->data().begin(), view->data().end(), value);
856 view->mark_dirty();
857 }
858
869 template<typename T>
870 bool layer_copy(const std::string & src, const std::string & dst)
871 {
872 // No-op if names are equal
873 if (src == dst) {
874 return true;
875 }
876
877 // Get source
878 auto src_base = layers.get(src);
879 auto src_view = std::dynamic_pointer_cast<LayerView<T>>(src_base);
880 if (!src_view) {
881 return false; // source layer missing or wrong type
882 }
883
884 // Ensure destination exists with correct length (navcels.size())
885 auto dst_view = layers.add_or_get<T>(dst, navcels.size(), layer_type_tag<T>());
886 if (!dst_view) {
887 return false;
888 }
889
890 // If sizes mismatch, something is wrong with geometry/layer size.
891 // You can choose to resize here if your semantics allow it. For safety, fail:
892 if (src_view->data().size() != dst_view->data().size()) {
893 return false;
894 }
895
896 // If both views already refer to the same underlying buffer, no work to do
897 if (!src_view->data().empty() &&
898 src_view->data().data() == dst_view->data().data())
899 {
900 return true;
901 }
902
903 // Hash-based skip: O(1) if cached, O(n) only on first compute (then cached)
904 const bool same_hash = (src_view->content_hash() == dst_view->content_hash());
905 if (same_hash) {
906 return true; // identical content → avoid copy
907 }
908
909 // Copy only when different. set_data() marks hash as dirty for dst.
910 dst_view->set_data(src_view->data());
911 return true;
912 }
913
930 template<typename T>
931 std::shared_ptr<LayerView<T>> add_layer(
932 const std::string & name,
933 const std::string & description,
934 const std::string & unit,
935 const std::string & src_layer)
936 {
937 auto dst = layers.add_or_get<T>(name, navcels.size(), layer_type_tag<T>());
938 if (dst->data().size() != navcels.size()) {
939 dst->data().assign(navcels.size(), T{});
940 }
941 layer_meta[name] = LayerMeta{description, unit, true};
942
943 if (!has_layer(src_layer)) {
944 return dst;
945 }
946
947 if (layer_copy<T>(src_layer, name)) {
948 return dst;
949 }
950
951 const std::size_t n = dst->size();
952 for (NavCelId cid = 0; cid < n; ++cid) {
953 double v = layer_get<double>(src_layer, cid, std::numeric_limits<double>::quiet_NaN());
954 if (std::isnan(v)) {v = 0.0;}
955
956 if constexpr (std::is_floating_point_v<T>) {
957 dst->data()[cid] = static_cast<T>(v);
958 } else if constexpr (std::is_integral_v<T>) {
959 double lo = 0.0;
960 double hi = static_cast<double>(std::numeric_limits<T>::max());
961 if (v < lo) {v = lo;}
962 if (v > hi) {v = hi;}
963 dst->data()[cid] = static_cast<T>(std::llround(v));
964 } else {
965 static_assert(sizeof(T) == 0, "Unsupported layer type");
966 }
967 }
968
969 return dst;
970 }
971
979 const Eigen::Vector3f & p_world,
980 std::size_t & surface_idx,
981 NavCelId & cid,
982 Eigen::Vector3f & bary,
983 Eigen::Vector3f * hit_pt,
984 const LocateOpts & opts) const;
985
1003 template<typename T>
1005 const Eigen::Vector3f & p_world,
1006 T value,
1007 const std::string & layer_name,
1008 AreaShape shape,
1009 float size)
1010 {
1011 if (navcels.empty() || surfaces.empty() || size <= 0.0f) {
1012 return false;
1013 }
1014
1015 std::size_t surface_idx = 0;
1016 NavCelId start_cid{};
1017 Eigen::Vector3f bary{};
1018 Eigen::Vector3f hit_pt{};
1019 if (!locate_navcel(p_world, surface_idx, start_cid, bary, &hit_pt)) {
1020 return false;
1021 }
1022
1023 const float cx = hit_pt.x();
1024 const float cy = hit_pt.y();
1025
1026 {
1027 auto existing = layers.get(layer_name);
1028 if (existing && existing->type() != layer_type_tag<T>()) {
1029 return false; // type mismatch
1030 }
1031 }
1032 auto layer = layers.add_or_get<T>(layer_name, navcels.size(), layer_type_tag<T>());
1033 if (!layer) {
1034 return false;
1035 }
1036 if (layer->data().size() != navcels.size()) {
1037 const_cast<std::vector<T> &>(layer->data()).resize(navcels.size(), T{});
1038 }
1039
1040 const float half = (shape == AreaShape::CIRCULAR) ? size : (0.5f * size);
1041 const float minx = cx - half, maxx = cx + half;
1042 const float miny = cy - half, maxy = cy + half;
1043 const float r2 = (shape == AreaShape::CIRCULAR) ? (size * size) : 0.0f;
1044
1045 auto tri_aabb_intersects_box = [&](NavCelId cid) -> bool {
1046 const auto & tri = navcels[static_cast<std::size_t>(cid)];
1047 const Eigen::Vector3f p0{positions.x[tri.v[0]], positions.y[tri.v[0]],
1048 positions.z[tri.v[0]]};
1049 const Eigen::Vector3f p1{positions.x[tri.v[1]], positions.y[tri.v[1]],
1050 positions.z[tri.v[1]]};
1051 const Eigen::Vector3f p2{positions.x[tri.v[2]], positions.y[tri.v[2]],
1052 positions.z[tri.v[2]]};
1053 const float tminx = std::min({p0.x(), p1.x(), p2.x()});
1054 const float tmaxx = std::max({p0.x(), p1.x(), p2.x()});
1055 const float tminy = std::min({p0.y(), p1.y(), p2.y()});
1056 const float tmaxy = std::max({p0.y(), p1.y(), p2.y()});
1057 if (tmaxx < minx || tminx > maxx || tmaxy < miny || tminy > maxy) {
1058 return false;
1059 }
1060 return true;
1061 };
1062
1063 auto inside_area = [&](const Eigen::Vector3f & c) -> bool {
1064 const float dx = c.x() - cx;
1065 const float dy = c.y() - cy;
1066 if (shape == AreaShape::CIRCULAR) {
1067 return (dx * dx + dy * dy) <= r2;
1068 } else {
1069 return (std::abs(dx) <= half) && (std::abs(dy) <= half);
1070 }
1071 };
1072
1073 std::vector<char> visited(navcels.size(), 0);
1074 std::deque<NavCelId> q;
1075 q.push_back(start_cid);
1076 visited[static_cast<std::size_t>(start_cid)] = 1;
1077
1078 auto & data = layer->mutable_data();
1079
1080 while (!q.empty()) {
1081 const NavCelId cid = q.front(); q.pop_front();
1082
1083 if (!tri_aabb_intersects_box(cid)) {
1084 continue;
1085 }
1086
1087 const Eigen::Vector3f c = navcel_centroid(cid);
1088 if (inside_area(c)) {
1089 data[static_cast<std::size_t>(cid)] = value;
1090 }
1091
1092 for (const auto ncid : navcel_neighbors(cid)) {
1093 const std::size_t nidx = static_cast<std::size_t>(ncid);
1094 if (nidx < navcels.size() && !visited[nidx] && tri_aabb_intersects_box(ncid)) {
1095 visited[nidx] = 1;
1096 q.push_back(ncid);
1097 }
1098 }
1099 }
1100
1101 return true;
1102 }
1103
1104private:
1105 // Geometry fingerprint cache (lazy recompute)
1106 void ensure_geometry_fingerprint_() const;
1107 static std::uint64_t hash_geometry_bytes_(
1108 const float *x, std::size_t nx,
1109 const float *y, std::size_t ny,
1110 const float *z, std::size_t nz,
1111 const std::uint32_t *v0, std::size_t nv0,
1112 const std::uint32_t *v1, std::size_t nv1,
1113 const std::uint32_t *v2, std::size_t nv2);
1114
1115 mutable bool geometry_dirty_{true};
1116 mutable std::uint64_t geometry_fp_{0};
1117
1118 // Builders and traversal helpers.
1119
1124 void build_surface_bvh(Surface & s);
1125
1136 bool surface_raycast(
1137 const Surface & s,
1138 const Eigen::Vector3f & o,
1139 const Eigen::Vector3f & d,
1140 NavCelId & hit_cid,
1141 float & t_out,
1142 Eigen::Vector3f & hit_pt) const;
1143
1154 bool locate_by_walking(
1155 NavCelId start_cid,
1156 const Eigen::Vector3f & p,
1157 NavCelId & cid_out,
1158 Eigen::Vector3f & bary,
1159 Eigen::Vector3f * hit_pt,
1160 float planar_eps) const;
1161
1172 bool surface_closest_navcel(
1173 const Surface & s,
1174 const Eigen::Vector3f & p,
1175 NavCelId & cid,
1176 Eigen::Vector3f & q,
1177 float & best_sq) const;
1178};
1179
1180// Inline convenience overload.
1182 const Eigen::Vector3f & p_world,
1183 size_t & surface_idx,
1184 NavCelId & cid,
1185 Eigen::Vector3f & bary,
1186 Eigen::Vector3f * hit_pt) const
1187{
1188 return locate_navcel(p_world, surface_idx, cid, bary, hit_pt, LocateOpts{});
1189}
1190
1191} // namespace navmap
1192
1193#endif // NAVMAP_CORE__NAVMAP_HPP
Low-level geometry utilities for NavMap cells (triangles), AABB and basic queries such as ray-triangl...
NavMap()
Copy constructor: deep copy of geometry, surfaces, layers and metadata.
Definition NavMap.cpp:47
Registry of named layers (per-NavCel).
Definition NavMap.hpp:240
bool remove(const std::string &name)
Remove a layer by name.
Definition NavMap.hpp:298
void resize_all(size_t nitems)
Resize all known typed layers to nitems.
Definition NavMap.hpp:310
std::shared_ptr< LayerViewBase > get(const std::string &name) const
Get an existing layer by name (untyped view).
Definition NavMap.hpp:274
std::vector< std::string > list() const
List layer names currently in the registry.
Definition NavMap.hpp:284
std::shared_ptr< LayerView< T > > add_or_get(const std::string &name, size_t nitems, LayerType type)
Add a new typed layer or return an existing one with the same name.
Definition NavMap.hpp:255
std::array< NavCelId, 3 > get_neighbors(NavCelId cid) const
Return the three neighbor NavCel ids of triangle cid.
Definition NavMap.hpp:526
Surface create_surface_obj(const std::string &frame_id) const
Create a standalone Surface object (not yet added to the map).
Definition NavMap.cpp:843
void raycast_many(const std::vector< Ray > &rays, std::vector< RayHit > &out, bool first_hit_only=true) const
Batched raycast.
Definition NavMap.cpp:468
void add_navcel_to_surface(std::size_t surface_index, NavCelId cid)
Add an existing nav cell id to a surface.
Definition NavMap.cpp:884
Eigen::Vector3f navcel_centroid(NavCelId cid) const
Triangle centroid (computed on the fly).
Definition NavMap.cpp:891
bool layer_copy(const std::string &src, const std::string &dst)
Copy values from one layer into another.
Definition NavMap.hpp:870
LayerRegistry layers
Per-NavCel layers (runtime registry)
Definition NavMap.hpp:471
std::vector< NavCel > navcels
All triangles (global indexing)
Definition NavMap.hpp:469
NavCelId add_navcel(uint32_t v0, uint32_t v1, uint32_t v2)
Append a triangle (NavCel) and return its id.
Definition NavMap.cpp:877
bool remove_surface(std::size_t surface_index)
Remove a Surface by index.
Definition NavMap.cpp:862
bool locate_navcel_core(const Eigen::Vector3f &p_world, std::size_t &surface_idx, NavCelId &cid, Eigen::Vector3f &bary, Eigen::Vector3f *hit_pt, const LocateOpts &opts) const
Forward to the existing low-level locator (implemented in .cpp).
Definition NavMap.cpp:595
std::optional< Colors > colors
Optional per-vertex colors.
Definition NavMap.hpp:468
std::shared_ptr< LayerView< T > > add_layer(const std::string &name, const std::string &description, const std::string &unit, const std::string &src_layer)
Create (or get) a typed per-NavCel layer, initialized from another layer.
Definition NavMap.hpp:931
bool locate_navcel(const Eigen::Vector3f &p_world, size_t &surface_idx, NavCelId &cid, Eigen::Vector3f &bary, Eigen::Vector3f *hit_pt) const
Locate the triangle under / near a world point (convenience).
Definition NavMap.hpp:1181
std::string layer_type_name(const std::string &name) const
Human-readable type name for a layer ("float", "double", "uint8", ...).
Definition NavMap.cpp:1024
std::size_t add_surface(const Surface &s)
Append an existing Surface (by value).
Definition NavMap.cpp:850
bool has_same_geometry(const NavMap &other) const
Fast check for identical geometry (vertices and NavCel indices).
Definition NavMap.cpp:105
double sample_layer_at(const std::string &name, const Eigen::Vector3f &p_world, double def=std::numeric_limits< double >::quiet_NaN()) const
Sample a per-NavCel layer at a world position.
Definition NavMap.cpp:1049
void layer_clear(const std::string &name, T value=T{})
Reset all values in a layer to a given value.
Definition NavMap.hpp:852
std::vector< NavCelId > navcel_neighbors(NavCelId cid) const
Return up to 3 neighbor cell ids (skips invalid entries).
Definition NavMap.cpp:900
bool set_area(const Eigen::Vector3f &p_world, T value, const std::string &layer_name, AreaShape shape, float size)
Set a per-NavCel layer to a constant value over a 2D area.
Definition NavMap.hpp:1004
uint32_t add_vertex(const Eigen::Vector3f &p)
Append a vertex and return its index.
Definition NavMap.cpp:869
std::vector< Surface > surfaces
Surfaces (partitions of navcels)
Definition NavMap.hpp:470
std::shared_ptr< LayerView< T > > add_layer(const std::string &name, const std::string &description={}, const std::string &unit={}, T default_value=T{})
Create (or get) a typed per-NavCel layer with a default value.
Definition NavMap.hpp:716
bool closest_navcel(const Eigen::Vector3f &p_world, size_t &surface_idx, NavCelId &cid, Eigen::Vector3f &closest_point, float &sqdist, int restrict_surface=-1) const
Find the closest triangle to a point.
Definition NavMap.cpp:777
void mark_vertex_updated(PointId)
Mark a vertex as updated (reserved for future cache invalidation).
Definition NavMap.hpp:519
T navcel_value(NavCelId cid, const LayerView< T > &layer) const
Read the value of a typed per-NavCel layer at triangle cid.
Definition NavMap.hpp:570
std::vector< std::string > list_layers() const
List all layer names currently stored.
Definition NavMap.cpp:1044
std::optional< LayerMeta > get_layer_meta(const std::string &name) const
Return metadata for a layer if present (implementation-defined).
Definition NavMap.cpp:1037
NavMap & operator=(const NavMap &other)
Copy assignment optimized to avoid geometry duplication.
Definition NavMap.cpp:121
bool locate_navcel(const Eigen::Vector3f &p_world, size_t &surface_idx, NavCelId &cid, Eigen::Vector3f &bary, Eigen::Vector3f *hit_pt, const LocateOpts &opts) const
Locate the triangle under / near a world point.
Positions positions
Vertex positions (SoA)
Definition NavMap.hpp:467
void layer_set(const std::string &name, NavCelId cid, T value)
Set a per-cell value (creates/retypes the layer if needed).
Definition NavMap.hpp:747
std::size_t create_surface(std::string frame_id)
Create a new empty Surface and append it to the map.
Definition NavMap.cpp:836
void build_adjacency()
Build topological adjacency between neighboring NavCels.
Definition NavMap.cpp:227
bool has_layer(const std::string &name) const
Check whether a layer named name exists.
Definition NavMap.cpp:1013
NavMap()
Copy constructor: deep copy of geometry, surfaces, layers and metadata.
Definition NavMap.cpp:47
std::size_t layer_size(const std::string &name) const
Number of entries in a layer (should equal navcels.size()).
Definition NavMap.cpp:1018
bool raycast(const Eigen::Vector3f &o, const Eigen::Vector3f &d, NavCelId &hit_cid, float &t, Eigen::Vector3f &hit_pt) const
Raycast against all surfaces to find the closest hit.
Definition NavMap.cpp:434
void rebuild_geometry_accels()
Recompute derived geometry and acceleration structures.
Definition NavMap.cpp:354
T layer_get(const std::string &name, NavCelId cid, T def=T{}) const
Get a per-cell value as the requested type.
Definition NavMap.hpp:772
std::unordered_map< std::string, LayerMeta > layer_meta
Optional metadata per layer.
Definition NavMap.hpp:472
Definition Geometry.hpp:39
constexpr LayerType layer_type_tag< double >()
Definition NavMap.hpp:440
constexpr LayerType layer_type_tag< uint8_t >()
Definition NavMap.hpp:438
LayerType
Runtime type tag for a layer's scalar storage.
Definition NavMap.hpp:121
@ F64
Definition NavMap.hpp:121
@ F32
Definition NavMap.hpp:121
@ U8
Definition NavMap.hpp:121
AreaShape
Shape selector for area-writing APIs.
Definition NavMap.hpp:445
@ RECTANGULAR
Definition NavMap.hpp:445
@ CIRCULAR
Definition NavMap.hpp:445
constexpr LayerType layer_type_tag()
Helper to map C++ scalar type to navmap::LayerType tag.
uint32_t NavCelId
Index of a triangle (NavCel) within the global mesh.
Definition NavMap.hpp:63
uint32_t PointId
Index into the per-vertex position arrays (SoA).
Definition NavMap.hpp:61
constexpr LayerType layer_type_tag< float >()
Definition NavMap.hpp:439
LayerView(std::string name, size_t nitems, LayerType t)
Construct a typed view.
Definition NavMap.hpp:171
Options for the locate functions.
Definition NavMap.hpp:585
Axis-aligned bounding box.
Definition Geometry.hpp:151
Node in a per-surface bounding volume hierarchy (BVH).
Definition NavMap.hpp:379
int right
Right child index (or -1 for leaf)
Definition NavMap.hpp:382
int start
Start index in primitive array (leaf only)
Definition NavMap.hpp:383
bool is_leaf() const
Definition NavMap.hpp:385
int count
Number of primitives in leaf (0 for inner nodes)
Definition NavMap.hpp:384
int left
Left child index (or -1 for leaf)
Definition NavMap.hpp:381
AABB box
Bounding box of this node (world coordinates)
Definition NavMap.hpp:380
Optional per-vertex colors (RGBA, 8-bit per channel).
Definition NavMap.hpp:105
std::vector< uint8_t > r
Red channel.
Definition NavMap.hpp:106
std::vector< uint8_t > a
Alpha channel.
Definition NavMap.hpp:109
std::vector< uint8_t > g
Green channel.
Definition NavMap.hpp:107
std::vector< uint8_t > b
Blue channel.
Definition NavMap.hpp:108
Metadata associated to a layer (optional).
Definition NavMap.hpp:341
std::string unit
Physical unit (e.g., "m", "deg", "%")
Definition NavMap.hpp:343
std::string description
Human-readable description.
Definition NavMap.hpp:342
bool per_cell
true for per-NavCel layers (current behavior)
Definition NavMap.hpp:344
Non-templated base for runtime layer handling.
Definition NavMap.hpp:129
virtual LayerType type() const =0
virtual const std::string & name() const =0
virtual std::uint64_t content_hash() const =0
Return 64-bit content hash (cached; recomputed lazily).
std::uint64_t hash_cache_
Definition NavMap.hpp:149
void mark_dirty() const noexcept
Mark content dirty (forces hash recompute on next query).
Definition NavMap.hpp:145
virtual size_t size() const =0
virtual ~LayerViewBase()=default
bool hash_dirty_
Definition NavMap.hpp:148
Typed layer view storing one T value per NavCel.
Definition NavMap.hpp:160
std::uint64_t content_hash() const override
Return 64-bit content hash (cached; recomputed lazily).
Definition NavMap.hpp:218
const std::vector< T > & data() const
Definition NavMap.hpp:187
void set_data(const std::vector< T > &v)
Definition NavMap.hpp:195
std::string name_
Layer name (key in the registry)
Definition NavMap.hpp:161
std::vector< T > data_
Values, one per NavCel.
Definition NavMap.hpp:162
LayerType type_
Runtime type tag (must match T)
Definition NavMap.hpp:163
LayerType type() const override
Definition NavMap.hpp:174
const std::string & name() const override
Definition NavMap.hpp:175
const T & operator[](NavCelId cid) const
Definition NavMap.hpp:181
std::vector< T > & mutable_data() const
Definition NavMap.hpp:191
T & operator[](NavCelId cid)
Definition NavMap.hpp:180
size_t size() const override
Definition NavMap.hpp:176
LayerView(std::string name, size_t nitems, LayerType t)
Construct a typed view.
Definition NavMap.hpp:171
std::vector< T > & data()
Definition NavMap.hpp:185
Navigation cell (triangle) with geometry and adjacency.
Definition NavMap.hpp:361
uint32_t layer_dirty_mask
Reserved for future per-layer flags.
Definition NavMap.hpp:370
Eigen::Vector3f normal
Unit normal of the triangle.
Definition NavMap.hpp:363
NavCelId neighbor[3]
Neighbor cids across edges 0,1,2.
Definition NavMap.hpp:365
float area
Triangle area (m²)
Definition NavMap.hpp:364
PointId v[3]
Indices into navmap::Positions.
Definition NavMap.hpp:362
Options for the locate functions.
Definition NavMap.hpp:585
std::optional< NavCelId > hint_cid
Optional triangle hint for walking.
Definition NavMap.hpp:586
std::optional< size_t > hint_surface
Optional surface hint.
Definition NavMap.hpp:587
bool use_downward_ray
Downward ray on fallback (else upward)
Definition NavMap.hpp:590
float height_eps
Z tolerance for vertical fallback (meters)
Definition NavMap.hpp:589
float planar_eps
In-plane barycentric tolerance.
Definition NavMap.hpp:588
Structure-of-arrays for storing 3D vertex positions.
Definition NavMap.hpp:79
Eigen::Vector3f at(PointId id) const
Returns vertex id as a 3D vector.
Definition NavMap.hpp:93
size_t size() const
Definition NavMap.hpp:85
std::vector< float > x
X coordinates (meters)
Definition NavMap.hpp:80
std::vector< float > z
Z coordinates (meters)
Definition NavMap.hpp:82
std::vector< float > y
Y coordinates (meters)
Definition NavMap.hpp:81
Result of a raycast against the NavMap.
Definition NavMap.hpp:424
Eigen::Vector3f p
World coordinates of intersection.
Definition NavMap.hpp:429
bool hit
True if the ray hit any triangle.
Definition NavMap.hpp:425
size_t surface
Index of surface hit.
Definition NavMap.hpp:426
NavCelId cid
Id of the NavCel hit.
Definition NavMap.hpp:427
float t
Distance along the ray (units of d)
Definition NavMap.hpp:428
Simple ray (origin + direction).
Definition NavMap.hpp:413
Eigen::Vector3f o
Origin of the ray (world)
Definition NavMap.hpp:414
Eigen::Vector3f d
Direction of the ray (unit length recommended)
Definition NavMap.hpp:415
A connected set of NavCels in a common reference frame.
Definition NavMap.hpp:395
std::vector< BVHNode > bvh
BVH nodes for this surface.
Definition NavMap.hpp:400
AABB aabb
Bounds of the surface geometry.
Definition NavMap.hpp:398
std::vector< NavCelId > navcels
NavCels belonging to this surface (global ids)
Definition NavMap.hpp:397
std::string frame_id
Frame id of this surface.
Definition NavMap.hpp:396
std::vector< int > prim_indices
Compact list of cids used by BVH leaves.
Definition NavMap.hpp:399