segment_expander.cpp
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2017, <copyright holder> <email>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the <organization> nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY <copyright holder> <email> ''AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL <copyright holder> <email> BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  *
27  */
28 
30 #include <ros/ros.h> //DEBUG
31 
32 namespace tuw_graph
33 {
35  {
36  }
37 
38  void Segment_Expander::Initialize(cv::Mat &_map, cv::Mat &_distField, cv::Mat &_voronoiPath)
39  {
40  nx_ = _map.cols;
41  ny_ = _map.rows;
42  ns_ = nx_ * ny_;
43 
44  distance_field_.reset(new float[nx_ * ny_]);
45  voronoi_graph_.reset(new int8_t[nx_ * ny_]);
46  global_map_.reset(new int8_t[nx_ * ny_]);
47 
48  float *distance_field = distance_field_.get();
49  int8_t *voronoi_graph = voronoi_graph_.get();
50  int8_t *global_map = global_map_.get();
51 
52  for(int i = 0; i < ns_; i++)
53  {
54  distance_field[i] = ((float*)_distField.data)[i];
55  voronoi_graph[i] = ((int8_t*)_voronoiPath.data)[i];
56  global_map[i] = ((int8_t*)_map.data)[i];
57  }
58 
59  }
60 
61  void Segment_Expander:: optimizeSegments(std::vector<Segment> &_segments, float _maxPixelsCrossing, float _maxPixelsEndSegment)
62  {
63  //Move all segments with distance less than _maxPixelCrossing into the crossing
64  for(uint32_t i = 0; i < _segments.size(); i++)
65  {
66  if(!_segments[i].getOptStart())
67  {
68  optimizeSegmentsAroundPoint(_segments, _segments[i].getStart(), _maxPixelsCrossing, i);
69  }
70 
71  if(!_segments[i].getOptEnd())
72  {
73  optimizeSegmentsAroundPoint(_segments, _segments[i].getEnd(), _maxPixelsCrossing, i);
74  }
75  }
76 
77  //Remove segments with zero length...
78  for(uint32_t i = 0; i < _segments.size(); i++)
79  {
80  if((_segments[i].getStart() - _segments[i].getEnd()).norm() == 0)
81  {
82  removeSegmentFromList(i,_segments);
83  //if we erase one segment we have to check the same spot again...
84  i--;
85  }
86  }
87 
88 
89  //Important do this only in the end of the optimization
90  for(uint32_t i = 0; i < _segments.size(); i++)
91  {
92  //Its important to have a sorted segment list by id... Therefore we need to update all segments when we remove one of them
93  //As well we need to remove all existing neighbors before erasing...
94  if((_segments[i].getStart() - _segments[i].getEnd()).norm() < _maxPixelsEndSegment && (_segments[i].getPredecessors().size() == 0 || _segments[i].getSuccessors().size() == 0))
95  {
96  removeSegmentFromList(i, _segments);
97  i--;
98  }
99  }
100  }
101 
102  void Segment_Expander::removeSegmentFromList(const uint32_t _id, std::vector<Segment> &_segments)
103  {
104  //Remove neighbors
105  for(uint32_t pd : _segments[_id].getPredecessors())
106  {
107  _segments[pd].cleanNeighbors(_id);
108  }
109  for(uint32_t sc : _segments[_id].getSuccessors())
110  {
111  _segments[sc].cleanNeighbors(_id);
112  }
113  _segments.erase(_segments.begin() + _id);
114  //Reorder graph
115  for(uint32_t j = 0; j < _segments.size(); j++)
116  {
117  _segments[j].decreaseNeighborIdAbove(_id);
118  }
119  }
120 
121  void Segment_Expander::optimizeSegmentsAroundPoint(std::vector<Segment> &_segments, const Eigen::Vector2d &pt, float maxPixels, int startIndex)
122  {
123  //References to segments of a crossing
124  std::vector<Segment *> connectedSegmnetsStart;
125  std::vector<Segment *> connectedSegmnetsEnd;
126 
127 
128  //find all segments to optimize
129  for(uint32_t i = startIndex; i < _segments.size(); i++)
130  {
131  if(!_segments[i].getOptStart())
132  {
133  if((_segments[i].getStart() - pt).norm() < maxPixels)
134  {
135  connectedSegmnetsStart.push_back(&_segments[i]);
136  _segments[i].setStart(pt);
137  _segments[i].getOptStart() = true;
138  }
139  }
140 
141  if(!_segments[i].getOptEnd())
142  {
143  if((_segments[i].getEnd() - pt).norm() < maxPixels)
144  {
145  connectedSegmnetsEnd.push_back(&_segments[i]);
146  _segments[i].setEnd(pt);
147  _segments[i].getOptEnd() = true;
148  }
149  }
150  }
151 
152  //Connect all optimized segments
153  for(uint32_t i = 0; i < connectedSegmnetsStart.size(); i++)
154  {
155  for(uint32_t j = 0; j < connectedSegmnetsStart.size(); j++)
156  {
157  if(i != j)
158  {
159  if(!(*connectedSegmnetsStart[i]).containsPredecessor((*connectedSegmnetsStart[j]).getId()))
160  {
161  (*connectedSegmnetsStart[i]).addPredecessor((*connectedSegmnetsStart[j]).getId());
162  }
163  }
164  }
165 
166  for(uint32_t j = 0; j < connectedSegmnetsEnd.size(); j++)
167  {
168  if(!(*connectedSegmnetsStart[i]).containsPredecessor((*connectedSegmnetsEnd[j]).getId()))
169  {
170  (*connectedSegmnetsStart[i]).addPredecessor((*connectedSegmnetsEnd[j]).getId());
171  }
172  }
173  }
174 
175  for(uint32_t i = 0; i < connectedSegmnetsEnd.size(); i++)
176  {
177  for(uint32_t j = 0; j < connectedSegmnetsStart.size(); j++)
178  {
179  if(!(*connectedSegmnetsEnd[i]).containsSuccessor((*connectedSegmnetsStart[j]).getId()))
180  {
181  (*connectedSegmnetsEnd[i]).addSuccessor((*connectedSegmnetsStart[j]).getId());
182  }
183  }
184 
185  for(uint32_t j = 0; j < connectedSegmnetsEnd.size(); j++)
186  {
187  if(i != j)
188  {
189  if(!(*connectedSegmnetsEnd[i]).containsSuccessor((*connectedSegmnetsEnd[j]).getId()))
190  {
191  (*connectedSegmnetsEnd[i]).addSuccessor((*connectedSegmnetsEnd[j]).getId());
192  }
193  }
194  }
195  }
196 
197  }
198 
199  const std::vector<tuw_graph::Segment> Segment_Expander::splitPath(const std::vector<Eigen::Vector2d> &_path, const float _minimum_length)
200  {
201  std::vector<tuw_graph::Segment> segments;
202 
203  if(_path.size() > 1 && _path.size() <= _minimum_length)
204  {
205  float min_seg_width = getMinSegmentWidth(_path);
206  Segment seg(_path, 2 * min_seg_width);
207  segments.push_back(seg);
208  }
209  else if(_path.size() > 1 && _path.size() > _minimum_length)
210  {
211  uint32_t nr_segments = _path.size() / _minimum_length;
212  float real_length = std::ceil((float)_path.size() / (float)nr_segments);
213 
214  for(uint32_t i = 0; i < nr_segments; i++)
215  {
216  //Segment
217  std::vector<Eigen::Vector2d> map_path_segment;
218  for(uint32_t j = std::max<int>(0, i * real_length); j <= (i + 1) * real_length && j < _path.size(); j++)
219  {
220  map_path_segment.push_back( {_path[j][0], _path[j][1]});
221  }
222 
223  float min_seg_width = getMinSegmentWidth(map_path_segment);
224  Segment newSegment(std::vector<Eigen::Vector2d>(map_path_segment), 2 * min_seg_width);
225 
226  //Push back and add neighbors
227  segments.push_back(newSegment);
228  if(i > 0)
229  {
230  segments[segments.size() - 2].addSuccessor(segments[segments.size() - 1].getId());
231  segments[segments.size() - 1].addPredecessor(segments[segments.size() - 2].getId());
232  }
233  }
234  }
235 
236  return segments;
237  }
238 
239 
240 
241  std::vector< Segment > Segment_Expander::getGraph(const std::vector<std::vector<Eigen::Vector2d>> &_endPoints, float *_potential, const float _min_length, float _optimizePixelsCrossing, const float _optimizePixelsEndSegments)
242  {
244 
245  //We need at least a 10th of max length for seg optimization to find unconnected edges from skeletonizing
246  _optimizePixelsCrossing = std::max<float>(_min_length/10, _optimizePixelsCrossing);
247 
248  //To be able to change the segments in the crossing class it has to be somehow accessable over the heap -> shared_ptr
249  std::shared_ptr<std::vector< Segment >> segments = std::make_shared<std::vector<Segment>>();
250  std::vector< std::vector< Eigen::Vector2d > > endPoints = _endPoints;
251 
252  //Convert endpoints to crossings
253  std::vector<Crossing> crossings_;
254  for(uint32_t i = 0; i < endPoints.size(); i++)
255  {
256  Crossing c(std::vector< Eigen::Vector2d > (endPoints[i]));
257  c.setSegmentReference(segments);
258  crossings_.push_back(c);
259  }
260 
261  //Find all paths connecting the crossings
262  while(endPoints.size() > 0)
263  {
264  std::vector<Eigen::Vector2d> startCrossing = endPoints.back();
265  if(startCrossing.size() > 0)
266  {
267  Eigen::Vector2d startPoint = startCrossing.back();
268 
269  //Reset the potential of each crossing endpoint to prepare for the expansion
270  for(const Eigen::Vector2d &cVec : startCrossing)
271  {
272  Index idx(cVec[0], cVec[1], nx_, 0, 0, 0);
273  _potential[idx.i] = 0;
274  }
275 
276  Index start(startPoint[0], startPoint[1], nx_, 0, 0, 0);
277 
278  std::vector<Eigen::Vector2d> path = getPath(start, _potential, endPoints);
279 
280  std::vector< Segment > pathSegments = splitPath(path, _min_length);
281  segments->insert(segments->end(), pathSegments.begin(), pathSegments.end());
282  removeEndpoint(start, endPoints);
283  }
284  else
285  {
286  endPoints.pop_back();
287  }
288  }
289 
290  //Find the correct crossing for each segment
291  for(Segment &s : (*segments))
292  {
293  for(Crossing &c : crossings_)
294  {
295  c.tryAddSegment(s);
296  }
297  }
298 
299  //Optimize Crossings by moving the center and removing unecessary "double crossings"
300  optimizeSegments((*segments), _optimizePixelsCrossing, _optimizePixelsEndSegments);
301 
302  return (*segments);
303  }
304 
305  float Segment_Expander::getMinSegmentWidth(const std::vector< Eigen::Vector2d > &_path)
306  {
307  if(_path.size() == 0)
308  return 0;
309 
310  Index p1(_path[0][0], _path[0][1], nx_, 0, 0, 0);
311  float minimum_path_space = distance_field_[p1.i];
312 
313  for(const Eigen::Vector2d &point : _path)//auto it = _path.begin(); it != _path.end(); ++it)
314  {
315  Index p(point[0], point[1], nx_, 0, 0, 0);
316  minimum_path_space = std::min<float>(distance_field_[p.i], minimum_path_space);
317  }
318 
319  return minimum_path_space;
320  }
321 
322 
323  std::vector<std::vector< Eigen::Vector2d > > Segment_Expander::calcEndpoints(float* _potential)
324  {
325  std::vector<std::vector< Eigen::Vector2d > > endpoints;
326 
327  std::fill(_potential, _potential + ns_, -1);
328 
329  for(int i = 0; i < ns_; i++)
330  {
331  //dont examine allready found potentials
332  if(_potential[i] >= 0)
333  continue;
334 
335  //only look for voronoi points
336  if(voronoi_graph_[i] >= 0)
337  continue;
338 
339  if(nrOfNeighbours(i) > 2)
340  {
341  std::vector< Eigen::Vector2d > crossing = expandCrossing(Index(i, 0, 0, 0), _potential);
342  endpoints.push_back(crossing);
343  }
344 
345  }
346 
347  return std::vector<std::vector< Eigen::Vector2d > >(endpoints);
348  }
349 
350 
351 
352 
354  {
355  //Check Boundries
356  if(_point.i < 0 || _point.i > ns_)
357  return false;
358 
359 
360  if(global_map_[_point.i] > 0)
361  return false;
362 
363 
364  if(voronoi_graph_[_point.i] >= 0)
365  return false;
366 
367  if(nrOfNeighbours(_point.i) != 2)
368  return false;
369 
370  return true;
371  }
372 
373 
374 
375  std::vector< Eigen::Vector2d> Segment_Expander::getPath(const Segment_Expander::Index &_start, float* _potential,
376  const std::vector<std::vector<Eigen::Vector2d>> &_endpoints)
377  {
378  std::vector< Eigen::Vector2d > points;
379 
380  int cycle = 0;
381  int cycles = ns_;
382  _potential[_start.i] = _start.potential;
383 
384  Index current(_start.i, _potential[_start.i], 0, _potential[_start.i]);
385  //min_d = distance_field_[_start.i];
386  //clear the queue
387  clearpq(queue_);
388  queue_.push(current);
389 
390 
391  while(!(queue_.empty()) && (cycle < cycles))
392  {
393  if(queue_.empty())
394  break;
395 
396  current = queue_.top();
397  queue_.pop();
398 
399  //min_d = std::min<float>(min_d, distance_field_[current.i]);
400  points.push_back( {current.getX(nx_), current.getY(nx_)});
401 
402  if(current.i != _start.i && isEndpoint(current, _endpoints))
403  {
404 
405  Eigen::Vector2d point;
406  point[0] = current.getX(nx_);
407  point[1] = current.getY(nx_);
408  return points;
409  }
410  else
411  {
412  addExpansionCandidate(current, current.offsetDist(1, 0, nx_, ny_), _potential);
413  addExpansionCandidate(current, current.offsetDist(0, 1, nx_, ny_), _potential);
414  addExpansionCandidate(current, current.offsetDist(-1, 0, nx_, ny_), _potential);
415  addExpansionCandidate(current, current.offsetDist(0, -1, nx_, ny_), _potential);
416 
417  addExpansionCandidate(current, current.offsetDist(1, 1, nx_, ny_), _potential);
418  addExpansionCandidate(current, current.offsetDist(-1, 1, nx_, ny_), _potential);
419  addExpansionCandidate(current, current.offsetDist(-1, -1, nx_, ny_), _potential);
420  addExpansionCandidate(current, current.offsetDist(1, -1, nx_, ny_), _potential);
421  }
422 
423  cycle++;
424  }
425 
426  float dx = points.front()[0] - points.back()[0];
427  float dy = points.front()[1] - points.back()[1];
428 
429 
430  if(!findEdgeSegments_ || points.size() <= 3 || std::sqrt(dx * dx + dy * dy) <= 3)
431  {
432  points.clear();
433  }
434 
435  return points;
436  }
437 
438 
439  Eigen::Vector2d Segment_Expander::expandSegment(Segment_Expander::Index _start, float* _potential, const std::vector<std::vector<Eigen::Vector2d>> &_endpoints)
440  {
441  std::vector<Eigen::Vector2d> points;
442 
443  int cycle = 0;
444  int cycles = ns_;
445  _potential[_start.i] = _start.potential;
446 
447  Index current(_start.i, _potential[_start.i], 0, _potential[_start.i]);
448 
449  //clear the queue
450  clearpq(queue_);
451  queue_.push(current);
452 
453 
454  while(!(queue_.empty()) && (cycle < cycles))
455  {
456  if(queue_.empty())
457  break;
458 
459  current = queue_.top();
460  queue_.pop();
461 
462 
463 
464  if(current.i != _start.i && isEndpoint(current, _endpoints))
465  {
466 
467  Eigen::Vector2d point;
468  point[0] = current.getX(nx_);
469  point[1] = current.getY(nx_);
470  return point;
471  }
472  else
473  {
474  addExpansionCandidate(current, current.offsetDist(1, 0, nx_, ny_), _potential);
475  addExpansionCandidate(current, current.offsetDist(0, 1, nx_, ny_), _potential);
476  addExpansionCandidate(current, current.offsetDist(-1, 0, nx_, ny_), _potential);
477  addExpansionCandidate(current, current.offsetDist(0, -1, nx_, ny_), _potential);
478 
479  addExpansionCandidate(current, current.offsetDist(1, 1, nx_, ny_), _potential);
480  addExpansionCandidate(current, current.offsetDist(-1, 1, nx_, ny_), _potential);
481  addExpansionCandidate(current, current.offsetDist(-1, -1, nx_, ny_), _potential);
482  addExpansionCandidate(current, current.offsetDist(1, -1, nx_, ny_), _potential);
483  }
484 
485  cycle++;
486  }
487 
488 
490  return Eigen::Vector2d(current.getX(nx_), current.getY(nx_));
491  else
492  return Eigen::Vector2d(_start.getX(nx_), _start.getY(nx_));
493 
494  }
495 
496 
497 
498  std::vector< Eigen::Vector2d > Segment_Expander::expandCrossing(const Index &_start, float* _potential)
499  {
500  std::vector< Eigen::Vector2d > points;
501 
502  int cycle = 0;
503  int cycles = ns_;
504  _potential[_start.i] = _start.potential;
505 
506  Index current(_start.i, _potential[_start.i], 0, _potential[_start.i]);
507 
508  //clear the queue
509  clearpq(queue_);
510  queue_.push(current);
511 
512 
513  while(!(queue_.empty()) && (cycle < cycles))
514  {
515  if(queue_.empty())
516  break;
517 
518  current = queue_.top();
519  queue_.pop();
520 
521  if(nrOfNeighbours(current.i) <= 2)
522  {
523  Eigen::Vector2d point;
524  point[0] = current.getX(nx_);
525  point[1] = current.getY(nx_);
526  points.push_back(point);
527  _potential[current.i] = -2; //Reset potential to find point
528  }
529  else
530  {
531  addExpansionCandidate(current, current.offsetDist(1, 0, nx_, ny_), _potential);
532  addExpansionCandidate(current, current.offsetDist(0, 1, nx_, ny_), _potential);
533  addExpansionCandidate(current, current.offsetDist(-1, 0, nx_, ny_), _potential);
534  addExpansionCandidate(current, current.offsetDist(0, -1, nx_, ny_), _potential);
535 
536  addExpansionCandidate(current, current.offsetDist(1, 1, nx_, ny_), _potential);
537  addExpansionCandidate(current, current.offsetDist(-1, 1, nx_, ny_), _potential);
538  addExpansionCandidate(current, current.offsetDist(-1, -1, nx_, ny_), _potential);
539  addExpansionCandidate(current, current.offsetDist(1, -1, nx_, ny_), _potential);
540  }
541 
542  cycle++;
543  }
544 
545  return points;
546  }
547 
548  void Segment_Expander::addExpansionCandidate(const Index &current, const Index &next, float* potential)
549  {
550  float potentialPrev = potential[current.i];
551 
552  //Check Boundries
553  if(next.i < 0 || next.i > ns_)
554  return;
555 
556  //Dont update allready found potentials
557  if(potential[next.i] >= 0)
558  return;
559 
560  if(global_map_[next.i] > 0)
561  return;
562 
563 
564  if(voronoi_graph_[next.i] >= 0)
565  return;
566 
567 
568  float pot = potentialPrev + 1;
569  float dist = 0;
570  float weight = pot;
571 
572  potential[next.i] = pot;
573 
574  queue_.push(Index(next.i, weight, dist, pot));
575  }
576 
577 
578  uint32_t Segment_Expander::nrOfNeighbours(uint32_t i) const
579  {
580  //0 1 2
581  //7 3
582  //6 5 4
583  uint32_t neighbours[8] =
584  {
585  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(-1, 1, nx_, ny_)).i] < 0),
586  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(0, 1, nx_, ny_)).i] < 0),
587  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(1, 1, nx_, ny_)).i] < 0),
588  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(1, 0, nx_, ny_)).i] < 0),
589  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(1, -1, nx_, ny_)).i] < 0),
590  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(0, -1, nx_, ny_)).i] < 0),
591  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(-1, -1, nx_, ny_)).i] < 0),
592  (voronoi_graph_[(Index(i, 0, 0, 0).offsetDist(-1, 0, nx_, ny_)).i] < 0)
593  };
594 
595 
596 
597  //Remove double neighbours e.g.:
598  // x x 0
599  // 0 x 0
600  // 0 x x
601  //should result in 2
602 
603  uint32_t num_neighbours = neighbours[0] + neighbours[1] + neighbours[2] + neighbours[3] + neighbours[4] + neighbours[5] + neighbours[6] + neighbours[7];
604 
605  if(neighbours[0] && neighbours[1] && !neighbours[2])
606  num_neighbours--;
607 
608  if(!neighbours[0] && neighbours[1] && neighbours[2])
609  num_neighbours--;
610 
611  if(neighbours[2] && neighbours[3] && !neighbours[4])
612  num_neighbours--;
613 
614  if(!neighbours[2] && neighbours[3] && neighbours[4])
615  num_neighbours--;
616 
617 
618  if(neighbours[4] && neighbours[5] && !neighbours[6])
619  num_neighbours--;
620 
621  if(!neighbours[4] && neighbours[5] && neighbours[6])
622  num_neighbours--;
623 
624 
625  if(neighbours[6] && neighbours[7] && !neighbours[0])
626  num_neighbours--;
627 
628  if(!neighbours[6] && neighbours[7] && neighbours[0])
629  num_neighbours--;
630 
631  return num_neighbours;
632  }
633 
634 
635  void Segment_Expander::removeEndpoint(const Segment_Expander::Index &_current, std::vector< std::vector< Eigen::Vector2d > > &_endpoints)
636  {
637  for(uint32_t j = 0; j < _endpoints.size(); j++)
638  {
639  if(_endpoints[j].size() > 0)
640  {
641  for(uint32_t i = 0; i < _endpoints[j].size(); i++)
642  {
643  if((int)(_endpoints[j][i][0]) == _current.getX(nx_) && (int)(_endpoints[j][i][1]) == _current.getY(nx_))
644  {
645  _endpoints[j].erase(_endpoints[j].begin() + i);
646 
647  if(_endpoints[j].size() == 0)
648  {
649  _endpoints.erase(_endpoints.begin() + j);
650  }
651  }
652  }
653  }
654  else
655  {
656  _endpoints.erase(_endpoints.begin() + j);
657  }
658  }
659  }
660 
661 
662  bool Segment_Expander::isEndpoint(Segment_Expander::Index &_current, const std::vector<std::vector<Eigen::Vector2d>> &_endpoints)
663  {
664  for(auto it_crossing = _endpoints.begin(); it_crossing != _endpoints.end(); it_crossing++)
665  {
666  for(auto it = it_crossing->begin(); it != it_crossing->end(); it++)
667  {
668 
669  if((*it)[0] == _current.getX(nx_) && (*it)[1] == _current.getY(nx_))
670  {
671  return true;
672  }
673  }
674  }
675 
676  return false;
677  }
678 }
void addExpansionCandidate(const Index &current, const Index &next, float *potential)
void optimizeSegments(std::vector< Segment > &_segments, float _maxPixelsCrossing, float _maxPixelsEndSeg)
static void resetId()
resets the id counter (which is used to generate uinique ids)
Definition: segment.cpp:182
XmlRpcServer s
std::unique_ptr< float[]> distance_field_
std::priority_queue< Index, std::vector< Index >, greater1 > queue_
std::unique_ptr< int8_t[]> voronoi_graph_
std::vector< Eigen::Vector2d > getPath(const Index &start, float *_potential, const std::vector< std::vector< Eigen::Vector2d >> &_endpoints)
std::vector< Eigen::Vector2d > expandCrossing(const Index &i, float *_potential)
void Initialize(cv::Mat &_map, cv::Mat &_distField, cv::Mat &_voronoiPath)
initializes the expander by setting the voronoi path map and distancefield
Index offsetDist(int dist_x, int dist_y, int nx, int ny) const
std::vector< std::vector< Eigen::Vector2d > > calcEndpoints(float *_potential)
looks for crossings and saves all segment endpoints of it
Eigen::Vector2d expandSegment(Index start, float *_potential, const std::vector< std::vector< Eigen::Vector2d >> &_endpoints)
void optimizeSegmentsAroundPoint(std::vector< Segment > &_segments, const Eigen::Vector2d &pt, float maxPixels, int startIndex)
float getMinSegmentWidth(const std::vector< Eigen::Vector2d > &_path)
void removeSegmentFromList(const uint32_t _id, std::vector< Segment > &_segments)
void removeEndpoint(const Index &_current, std::vector< std::vector< Eigen::Vector2d >> &_endpoints)
bool checkSegmentPoint(const Index &_point)
void setSegmentReference(const std::shared_ptr< std::vector< Segment >> &segs)
saves the reference to the vector containing all segments to have access to them to alter other segme...
Definition: crossing.cpp:119
std::vector< Segment > getGraph(const std::vector< std::vector< Eigen::Vector2d >> &_endPoints, float *_potential, const float _min_length, float _optimizePixelsCrossing, const float _optimizePixelsEndSegments)
returns a list of segments, which represent the found search graph
const std::vector< tuw_graph::Segment > splitPath(const std::vector< Eigen::Vector2d > &_path, const float _minimum_length)
void clearpq(std::priority_queue< T, S, C > &q)
uint32_t nrOfNeighbours(uint32_t i) const
bool isEndpoint(Index &_current, const std::vector< std::vector< Eigen::Vector2d >> &_endpoints)
std::unique_ptr< int8_t[]> global_map_


tuw_voronoi_graph
Author(s): Benjamin Binder
autogenerated on Mon Jun 10 2019 15:42:44