예제 #1
0
std::tuple<Segment, bool> ew::VectorTerrainWorld::getFirstColliding(const Segment &motion)
{
  Segment closest;
  bool collisions = false;
  float closestDistanceSquared = -1;

  // Find closest terrain collision
  segmentTree.query(motion, [&](Segment const& segment){
    if(segment.intersects(motion))
    {
      if(segment.delta().cross(motion.delta()) <= 0)
      {
        Vec2D collisionPoint = segment.intersectionPoint(motion);
        float distanceSquared = (collisionPoint - motion.a).lengthSquared();
        if(closestDistanceSquared < 0 || distanceSquared < closestDistanceSquared)
        {
          closestDistanceSquared = distanceSquared;
          closest = segment;
          collisions = true;
        }
      }
    }
    return false;
  });

  return std::make_tuple(closest, collisions);
}
void WindowEvaluator::obstacle_robot(vector<Window>& windows, Point origin,
                                     Segment target, Point bot_pos) {
    auto n = (bot_pos - origin).normalized();
    auto t = n.perpCCW();
    auto r = Robot_Radius + Ball_Radius;

    Segment seg{bot_pos - n * Robot_Radius + t * r,
                bot_pos - n * Robot_Radius - t * r};

    if (debug) {
        system->drawLine(seg, QColor{"Red"}, "Debug");
    }

    auto end = target.delta().magsq();

    array<double, 2> extent = {0, end};

    for (int i = 0; i < 2; i++) {
        Line edge{origin, seg.pt[i]};
        auto d = edge.delta().magsq();

        Point intersect;
        if (edge.intersects(Line(target), &intersect) &&
            (intersect - origin).dot(edge.delta()) > d) {
            auto f = (intersect - target.pt[0]).dot(target.delta());
            if (f < 0)
                extent[i] = 0;
            else if (f > end)
                extent[i] = end;
            else
                extent[i] = f;
        } else {
            return;
        }
    }
    obstacle_range(windows, extent[0], extent[1]);
}
예제 #3
0
int ew::VectorTerrainWorld::getCollideCount(const Segment &motion)
{
  int result = 0;
  segmentTree.query(motion, [&](Segment const& segment){
    if(segment.intersects(motion))
    {
      if(segment.delta().cross(motion.delta()) <= 0)
      {
        result += 1;
      }
    }
    return false;
  });

  return result;
}
예제 #4
0
SegmentTree::SegmentList ew::VectorTerrainWorld::getColliding(const Segment &motion)
{
  SegmentTree::SegmentList result;
  segmentTree.query(motion, [&](Segment const& segment){
    if(segment.intersects(motion))
    {
      if(segment.delta().cross(motion.delta()) <= 0)
      {
        result.push_back(segment);
      }
    }
    return false;
  });

  return result;
}
예제 #5
0
파일: segment.cpp 프로젝트: bzar/2dshooter
Vec2D Segment::intersectionPoint(Segment const& other) const
{
  Vec2D selfDelta = delta();
  Vec2D otherDelta = other.delta();

  if(selfDelta.cross(otherDelta) != 0)
  {
    float t = other.a.subtract(a).cross(otherDelta) / selfDelta.cross(otherDelta);
    float u = other.a.subtract(a).cross(selfDelta) / selfDelta.cross(otherDelta);
    if(t >= 0 && t <= 1 && u >= 0 && u <= 1)
    {
      return a.add(selfDelta.scale(t));
    }
  }

  return Vec2D(0, 0);
}
예제 #6
0
파일: segment.cpp 프로젝트: bzar/2dshooter
bool Segment::intersects(Segment const& other) const
{
  Vec2D selfDelta = delta();
  Vec2D otherDelta = other.delta();

  if(selfDelta.cross(otherDelta) != 0)
  {
    float t = other.a.subtract(a).cross(otherDelta) / selfDelta.cross(otherDelta);
    float u = other.a.subtract(a).cross(selfDelta) / selfDelta.cross(otherDelta);
    if(t >= 0 && t <= 1 && u >= 0 && u <= 1)
    {
      return true;
    }
  }

  return false;
}
예제 #7
0
void Polygon::init(const Segment& seg, float r, float length) {
    Point dir;
    if (length) {
        dir = seg.delta() / length;
    } else {
        // Degenerate segment, so direction doesn't matter as long as it's a
        // unit vector.
        dir = Point(1, 0);
    }

    Point v = dir * r;
    Point u = v.perpCCW();

    vertices.resize(4);
    vertices[0] = seg.pt[0] - u - v;
    vertices[1] = seg.pt[0] + u - v;
    vertices[2] = seg.pt[1] + u + v;
    vertices[3] = seg.pt[1] - u + v;
}
WindowingResult WindowEvaluator::eval_pt_to_seg(Point origin, Segment target) {
    auto end = target.delta().magsq();

    // if target is a zero-length segment, there are no windows
    if (end == 0) return make_pair(vector<Window>{}, boost::none);

    if (debug) {
        system->drawLine(target, QColor{"Blue"}, "Debug");
    }

    vector<Window> windows = {Window{0, end}};

    // apply the obstacles

    vector<Robot*> bots(system->self.size() + system->opp.size());

    auto filter_predicate = [&](const Robot* bot) -> bool {
        return bot != nullptr && bot->visible &&
               find(excluded_robots.begin(), excluded_robots.end(), bot) ==
                   excluded_robots.end();
    };

    auto end_it = copy_if(system->self.begin(), system->self.end(),
                          bots.begin(), filter_predicate);

    end_it = copy_if(system->opp.begin(), system->opp.end(), end_it,
                     filter_predicate);

    bots.resize(distance(bots.begin(), end_it));

    vector<Point> bot_locations;
    for_each(bots.begin(), bots.end(), [&bot_locations](Robot* bot) {
        bot_locations.push_back(bot->pos);
    });

    bot_locations.insert(bot_locations.end(),
                         hypothetical_robot_locations.begin(),
                         hypothetical_robot_locations.end());

    for (auto& pos : bot_locations) {
        auto d = (pos - origin).mag();
        // whether or not we can ship over this bot
        auto chip_overable = chip_enabled &&
                             (d < max_chip_range - Robot_Radius) &&
                             (d > min_chip_range + Robot_Radius);
        if (!chip_overable) {
            obstacle_robot(windows, origin, target, pos);
        }
    }

    auto p0 = target.pt[0];
    auto delta = target.delta() / end;

    for (auto& w : windows) {
        w.segment = Segment{p0 + delta * w.t0, p0 + delta * w.t1};
        w.a0 = RadiansToDegrees((w.segment.pt[0] - origin).angle());
        w.a1 = RadiansToDegrees((w.segment.pt[1] - origin).angle());
        fill_shot_success(w, origin);
    }

    boost::optional<Window> best{
        !windows.empty(), *max_element(windows.begin(), windows.end(),
                                       [](Window& a, Window& b) -> bool {
                                           return a.segment.delta().magsq() <
                                                  b.segment.delta().magsq();
                                       })};
    if (debug) {
        if (best) {
            system->drawLine(Segment{origin, best->segment.center()},
                             QColor{"Green"}, "Debug");
        }
        for (Window& window : windows) {
            system->drawLine(window.segment, QColor{"Green"}, "Debug");
            system->drawText(QString::number(window.shot_success),
                             window.segment.center() + Point(0, 0.1),
                             QColor{"Green"}, "Debug");
        }
    }

    return make_pair(windows, best);
}