Program Listing for File linesegment2d_detector.cpp

Return to documentation for file (src/tuw_geometry/linesegment2d_detector.cpp)

#include "tuw_geometry/linesegment2d_detector.hpp"

using namespace tuw;

LineSegment2DDetector::LineSegment2DDetector() {}
void LineSegment2DDetector::LineSegment::updatePoints(const std::vector<Point2D> & points)
{
  if ((idx0_ < idx1_) && (idx1_ < points.size())) {
    points_.clear();
    points_.reserve(idx1_ - idx0_ + 1);
    for (unsigned int i = idx0_; i <= idx1_; i++) {
      points_.push_back(points[i]);
    }
  }
}
bool LineSegment2DDetector::LineSegment::isSupportPoint(int idx)
{
  if ((static_cast<unsigned int>(idx) < idx0_) || (static_cast<unsigned int>(idx) > idx1_)) {
    return false;
  } else {
    return true;
  }
}
unsigned int LineSegment2DDetector::LineSegment::nrSupportPoint() {return idx1_ - idx0_ + 2;}
void LineSegment2DDetector::LineSegment::set(
  unsigned int idx0, unsigned int idx1, const std::vector<Point2D> & points)
{
  idx0_ = idx0, idx1_ = idx1;
  LineSegment2D::set(points[idx0], points[idx1]);
}

void LineSegment2DDetector::start(const std::vector<Point2D> & points)
{
  connected_measurments_.clear();
  segments_.clear();

  if (points.size() > 0) {
    std::pair<unsigned int, unsigned int> idx;
    idx.first = 0;

    while (idx.first < points.size()) {
      idx.second = idx.first + 1;
      float threshold = 4 * points[idx.second].distanceTo(points[idx.second + 1]);
      while (idx.second < points.size()) {
        if (config_.threshold_split_neighbor) {
          float d = points[idx.second].distanceTo(points[idx.second + 1]);
          if (d > threshold) {
            break;
          }
          threshold = 4 * d;
        }
        idx.second++;
      }
      if ((idx.second - idx.first) > 2) {
        connected_measurments_.push_back(idx);
      }
      idx.first = idx.second + 1;
    }

    for (unsigned int i = 0; i < connected_measurments_.size(); i++) {
      unsigned int idx0 = connected_measurments_[i].first;
      unsigned int idx1 = connected_measurments_[i].second;
      if (idx1 > idx0) {
        LineSegment line;
        line.set(idx0, idx1, points);
        split(line, points);
      }
    }
  }
}
std::vector<LineSegment2D> & LineSegment2DDetector::start(
  const std::vector<Point2D> & points, std::vector<LineSegment2D> & detected_segments)
{
  start(points);
  detected_segments.reserve(detected_segments.size() + segments_.size());
  for (const LineSegment & l : segments_) {
    detected_segments.push_back(l);
  }
  return detected_segments;
}
void LineSegment2DDetector::split(LineSegment & line, const std::vector<Point2D> & points)
{
  unsigned int idxMax = line.idx0_;
  float d;
  float dMax = 0;
  for (unsigned int i = line.idx0_; i < line.idx1_; i++) {
    d = fabs(line.distanceTo(points[i]));
    if (d > dMax) {
      dMax = d, idxMax = i;
    }
  }
  if (dMax > config_.threshold_split) {
    LineSegment l0, l1;
    if (line.idx0_ + config_.min_points_per_line < idxMax) {
      l0.set(line.idx0_, idxMax, points);
      split(l0, points);
    }
    if (idxMax + config_.min_points_per_line < line.idx1_) {
      l1.set(idxMax, line.idx1_, points);
      split(l1, points);
    }
  } else {
    if (line.length() < config_.min_length) {
      return;
    }
    if (((float)line.nrSupportPoint()) / line.length() < config_.min_points_per_unit) {
      return;
    }
    line.id_ = segments_.size();
    line.updatePoints(points);
    segments_.push_back(line);
  }
}

const std::vector<LineSegment2DDetector::LineSegment> & LineSegment2DDetector::result()
{
  return segments_;
}