segment_tree.cpp
Go to the documentation of this file.
1 /*
2  * (c) 2021-2022 Nokia
3  *
4  * Licensed under the BSD 3-Clause "New" or "Revised" License
5  * SPDX-License-Identifier: BSD-3-Clause
6  */
7 
9 
10 namespace scan_tools
11 {
12 
13 double min_dist_to_segment(const Point &p, const Segment &seg)
14 {
15  const auto diff = seg.diff();
16  const auto len2 = diff.squaredNorm();
17 
18  // t represents location along seg where p projects, clamped to the endpoints
19  const auto t = std::max(0.0, std::min(1.0, (p - seg.first).dot(diff)/len2));
20  const Point projection = seg.first + t*diff;
21 
22  return (p - projection).norm();
23 }
24 
25 SegmentTree::SegmentTree(std::vector<Segment> segs):
26  root_(std::move(segs)) {}
27 
28 template<int Axis>
29 SegmentTree::Node<Axis>::Node(std::vector<Segment> segs)
30 {
31  const auto n = segs.size();
32 
33  if (n <= leaf_capacity)
34  {
35  segments_ = std::move(segs);
36  return;
37  }
38 
39  pivot_ = 0;
40  // Center of segments
41  for (const auto &seg : segs)
42  {
43  pivot_ += (seg.first[Axis] + seg.second[Axis]);
44  }
45  pivot_ /= 2*n;
46 
47  // Partition segs as follows: [split, left, right]
48  auto first_left_seg = std::partition(segs.begin(), segs.end(),
49  [this](const Segment &seg)
50  {
51  return (seg.first[Axis] < pivot_) != (seg.second[Axis] < pivot_);
52  });
53 
54  auto first_right_seg = std::partition(first_left_seg, segs.end(),
55  [this](const Segment &seg)
56  {
57  return seg.first[Axis] < pivot_;
58  });
59 
60  std::vector<Segment> right_segs(first_right_seg, segs.end());
61  segs.erase(first_right_seg, segs.end());
62 
63  for (auto i = segs.begin(); i != first_left_seg; ++i)
64  {
65  // Split the segments split by the pivot into 2 smaller segments
66  // Order along Axis must be first, pivot_, second, either plus or minus.
67  const auto diff = i->diff();
68  const double factor = (pivot_ - i->first[Axis])/diff[Axis];
69 
70  Segment left{i->first, i->first + diff*factor};
71  Segment right{i->first + diff*factor, i->second};
72 
73  // This segment goes backwards
74  if (diff[Axis] < 0) std::swap(left, right);
75 
76  // segs is the new left_segs vector.
77  *i = left;
78  right_segs.push_back(right);
79  }
80 
81  if (segs.size()) left_.reset(new ChildNode(std::move(segs)));
82  if (right_segs.size()) right_.reset(new ChildNode(std::move(right_segs)));
83 }
84 
85 template<int Axis>
86 template<class Callback>
88  Point p, double radius, const Callback &cb) const
89 {
90  for (const auto& seg : segments_)
91  if (min_dist_to_segment(p, seg) <= radius)
92  cb(seg);
93 
94  if (left_ && p[Axis] - radius <= pivot_)
95  left_->segments_within(p, radius, cb);
96 
97  if (right_ && p[Axis] + radius >= pivot_)
98  right_->segments_within(p, radius, cb);
99 }
100 
101 std::vector<Segment> SegmentTree::segments_within(Point p, double radius) const
102 {
103  std::vector<Segment> ret;
104  root_.segments_within(p, radius, [&ret](const Segment& seg)
105  {
106  ret.push_back(seg);
107  });
108 
109  return ret;
110 }
111 
112 template<int Axis>
113 template<class Callback>
114 void SegmentTree::Node<Axis>::traverse(const Callback &cb, int depth) const
115 {
116  if (left_) left_->traverse(cb, depth+1);
117  cb(segments_, pivot_, Axis, depth);
118  if (right_) right_->traverse(cb, depth+1);
119 }
120 
121 void SegmentTree::dump(std::ostream &os) const
122 {
123  root_.traverse([&os](const std::vector<Segment>& segs,
124  const double pivot, int axis, int depth)
125  {
126  os << std::string(10+depth*2, ' ');
127  if (segs.size())
128  os << segs.size() << " segments";
129  else
130  os << axis << ":" << pivot;
131 
132  os << std::endl;
133  });
134 }
135 
136 }
scan_tools::SegmentTree::Node::segments_within
void segments_within(Point p, double radius, const Callback &cb) const
Definition: segment_tree.cpp:87
scan_tools::Point
Eigen::Vector2d Point
Definition: segment_tree.h:23
scan_tools::Segment
Definition: segment_tree.h:24
scan_tools::min_dist_to_segment
double min_dist_to_segment(const Point &p, const Segment &seg)
Definition: segment_tree.cpp:13
segment_tree.h
scan_tools
Definition: laser_scan_matcher.h:72
p
struct @4 p
scan_tools::SegmentTree::Node::traverse
void traverse(const Callback &cb, int depth=0) const
Definition: segment_tree.cpp:114
scan_tools::SegmentTree::Node
Definition: segment_tree.h:43
scan_tools::SegmentTree::segments_within
std::vector< Segment > segments_within(Point p, double radius) const
Definition: segment_tree.cpp:101
std
scan_tools::SegmentTree::root_
Node< 0 > root_
Definition: segment_tree.h:88
scan_tools::SegmentTree::Node::Node
Node()=default
scan_tools::SegmentTree::SegmentTree
SegmentTree()=default
scan_tools::Segment::diff
Eigen::Vector2d diff() const
Definition: segment_tree.h:30
scan_tools::SegmentTree::dump
void dump(std::ostream &os) const
Definition: segment_tree.cpp:121


lsm_localization
Author(s): Ivan Dryanovski , Ilija Hadzic
autogenerated on Fri Dec 23 2022 03:09:11