Example #1
0
    gcc_pure
    ClosingPair FindRange(const ClosingPair &p) const {
      for (const auto &i : closing_pairs) {
        if (i.first > p.first)
          break;

        if (i.second >= p.second)
          return i;
      }

      return ClosingPair(0, 0);
    }
Example #2
0
bool
OLCTriangle::FindClosingPairs(unsigned old_size)
{
  if (predict) {
    return closing_pairs.Insert(ClosingPair(0, n_points-1));
  }

  struct TracePointNode {
    const TracePoint *point;
    unsigned index;
  };

  struct TracePointNodeAccessor {
    gcc_pure
    int GetX(const TracePointNode &node) const {
      return node.point->GetFlatLocation().x;
    }

    gcc_pure
    int GetY(const TracePointNode &node) const {
      return node.point->GetFlatLocation().y;
    }
  };

  QuadTree<TracePointNode, TracePointNodeAccessor> search_point_tree;

  for (unsigned i = old_size; i < n_points; ++i) {
    TracePointNode node;
    node.point = &GetPoint(i);
    node.index = i;

    search_point_tree.insert(node);
  }

  search_point_tree.Optimise();

  bool new_pair = false;

  for (unsigned i = old_size; i < n_points; ++i) {
    TracePointNode point;
    point.point = &GetPoint(i);
    point.index = i;

    const SearchPoint start = *point.point;
    const unsigned max_range = trace_master.ProjectRange(start.GetLocation(), max_distance);
    const unsigned half_max_range_sq = max_range * max_range / 2;

    const int min_altitude = GetMinimumFinishAltitude(*point.point);
    const int max_altitude = GetMaximumStartAltitude(*point.point);

    unsigned last = 0, first = i;

    const auto visitor = [this, i, start,
                          half_max_range_sq,
                          min_altitude, max_altitude,
                          &first, &last]
      (const TracePointNode &node) {
      const auto &dest = *node.point;

      if (node.index + 2 < i &&
          dest.GetIntegerAltitude() <= max_altitude &&
          IsInRange(start, dest, half_max_range_sq, max_distance)) {
        // point i is last point
        first = std::min(node.index, first);
        last = i;
      } else if (node.index > i + 2 &&
                 dest.GetIntegerAltitude() >= min_altitude &&
                 IsInRange(start, dest, half_max_range_sq, max_distance)) {
        // point i is first point
        first = i;
        last = std::max(node.index, last);
      }
    };

    search_point_tree.VisitWithinRange(point, max_range, visitor);

    if (last != 0 && closing_pairs.Insert(ClosingPair(first, last)))
      new_pair = true;
  }

  return new_pair;
}
Example #3
0
void
OLCTriangle::SolveTriangle(bool exhaustive)
{
  unsigned tp1 = 0,
           tp2 = 0,
           tp3 = 0,
           start = 0,
           finish = 0;

  if (exhaustive || !predict) {
    ClosingPairs relaxed_pairs;

    unsigned relax = n_points * 0.03;

    // for all closed trace loops
    for (auto closing_pair = closing_pairs.closing_pairs.begin();
         closing_pair != closing_pairs.closing_pairs.end();
         ++closing_pair) {

      auto already_relaxed = relaxed_pairs.FindRange(*closing_pair);
      if (already_relaxed.first != 0 || already_relaxed.second != 0)
        // this pair is already relaxed... continue with next
        continue;

      unsigned relax_first = closing_pair->first;
      unsigned relax_last = closing_pair->second;

      const unsigned max_first = closing_pair->first + relax;
      const unsigned max_last = closing_pair->second + relax;

      for (auto relaxed = std::next(closing_pair);
           relaxed != closing_pairs.closing_pairs.end() &&
           relaxed->first <= max_first && relaxed->second <= max_last;
           ++relaxed)
        relax_last = std::max(relax_last, relaxed->second);

      relaxed_pairs.Insert(ClosingPair(relax_first, relax_last));
    }

    // TODO: reverse sort relaxed pairs according to number of contained points

    ClosingPairs close_look;

    for (const auto relaxed_pair : relaxed_pairs.closing_pairs) {

      std::tuple<unsigned, unsigned, unsigned, unsigned> triangle;

      triangle = RunBranchAndBound(relaxed_pair.first, relaxed_pair.second, best_d, exhaustive);

      if (std::get<3>(triangle) > best_d) {
        // solution is better than best_d
        // only if triangle is inside a unrelaxed pair...

        auto unrelaxed = closing_pairs.FindRange(ClosingPair(std::get<0>(triangle), std::get<2>(triangle)));
        if (unrelaxed.first != 0 || unrelaxed.second != 0) {
          // fortunately it is inside a unrelaxed closing pair :-)
          start = unrelaxed.first;
          tp1 = std::get<0>(triangle);
          tp2 = std::get<1>(triangle);
          tp3 = std::get<2>(triangle);
          finish = unrelaxed.second;

          best_d = std::get<3>(triangle);
        } else {
          // otherwise we should solve the triangle again for every unrelaxed pair
          // contained inside the current relaxed pair. *damn!*
          for (const auto closing_pair : closing_pairs.closing_pairs) {
            if (closing_pair.first >= relaxed_pair.first &&
                closing_pair.second <= relaxed_pair.second)
              close_look.Insert(closing_pair);
         }
       }
      }
    }

    for (const auto &close_look_pair : close_look.closing_pairs) {
      std::tuple<unsigned, unsigned, unsigned, unsigned> triangle;

      triangle = RunBranchAndBound(close_look_pair.first,
                                   close_look_pair.second,
                                   best_d, exhaustive);

      if (std::get<3>(triangle) > best_d) {
        // solution is better than best_d

        start = close_look_pair.first;
        tp1 = std::get<0>(triangle);
        tp2 = std::get<1>(triangle);
        tp3 = std::get<2>(triangle);
        finish = close_look_pair.second;

        best_d = std::get<3>(triangle);
      }
    }

  } else {
    /**
     * We're currently running in predictive, non-exhaustive mode, so we use
     * one closing pair only (0 -> n_points-1) which allows us to suspend the
     * solver...
     */
    std::tuple<unsigned, unsigned, unsigned, unsigned> triangle;

    triangle = RunBranchAndBound(0, n_points - 1, best_d, false);

    if (std::get<3>(triangle) > best_d) {
      // solution is better than best_d

      start = 0;
      tp1 = std::get<0>(triangle);
      tp2 = std::get<1>(triangle);
      tp3 = std::get<2>(triangle);
      finish = n_points - 1;

      best_d = std::get<3>(triangle);
    }
  }

  if (best_d > 0) {
    solution.resize(5);

    solution[0] = TraceManager::GetPoint(start);
    solution[1] = TraceManager::GetPoint(tp1);
    solution[2] = TraceManager::GetPoint(tp2);
    solution[3] = TraceManager::GetPoint(tp3);
    solution[4] = TraceManager::GetPoint(finish);

    is_complete = true;
  }
}