initial commit, 4.5 stable
Some checks failed
🔗 GHA / 📊 Static checks (push) Has been cancelled
🔗 GHA / 🤖 Android (push) Has been cancelled
🔗 GHA / 🍏 iOS (push) Has been cancelled
🔗 GHA / 🐧 Linux (push) Has been cancelled
🔗 GHA / 🍎 macOS (push) Has been cancelled
🔗 GHA / 🏁 Windows (push) Has been cancelled
🔗 GHA / 🌐 Web (push) Has been cancelled

This commit is contained in:
2025-09-16 20:46:46 -04:00
commit 9d30169a8d
13378 changed files with 7050105 additions and 0 deletions

594
thirdparty/rvo2/rvo2_2d/Agent2d.cpp vendored Normal file
View File

@@ -0,0 +1,594 @@
/*
* Agent2d.cpp
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#include "Agent2d.h"
#include "KdTree2d.h"
#include "Obstacle2d.h"
namespace RVO2D {
Agent2D::Agent2D() : maxNeighbors_(0), maxSpeed_(0.0f), neighborDist_(0.0f), radius_(0.0f), timeHorizon_(0.0f), timeHorizonObst_(0.0f), id_(0) { }
void Agent2D::computeNeighbors(RVOSimulator2D *sim_)
{
obstacleNeighbors_.clear();
float rangeSq = sqr(timeHorizonObst_ * maxSpeed_ + radius_);
sim_->kdTree_->computeObstacleNeighbors(this, rangeSq);
agentNeighbors_.clear();
if (maxNeighbors_ > 0) {
rangeSq = sqr(neighborDist_);
sim_->kdTree_->computeAgentNeighbors(this, rangeSq);
}
}
/* Search for the best new velocity. */
void Agent2D::computeNewVelocity(RVOSimulator2D *sim_)
{
orcaLines_.clear();
const float invTimeHorizonObst = 1.0f / timeHorizonObst_;
/* Create obstacle ORCA lines. */
for (size_t i = 0; i < obstacleNeighbors_.size(); ++i) {
const Obstacle2D *obstacle1 = obstacleNeighbors_[i].second;
const Obstacle2D *obstacle2 = obstacle1->nextObstacle_;
const Vector2 relativePosition1 = obstacle1->point_ - position_;
const Vector2 relativePosition2 = obstacle2->point_ - position_;
/*
* Check if velocity obstacle of obstacle is already taken care of by
* previously constructed obstacle ORCA lines.
*/
bool alreadyCovered = false;
for (size_t j = 0; j < orcaLines_.size(); ++j) {
if (det(invTimeHorizonObst * relativePosition1 - orcaLines_[j].point, orcaLines_[j].direction) - invTimeHorizonObst * radius_ >= -RVO_EPSILON && det(invTimeHorizonObst * relativePosition2 - orcaLines_[j].point, orcaLines_[j].direction) - invTimeHorizonObst * radius_ >= -RVO_EPSILON) {
alreadyCovered = true;
break;
}
}
if (alreadyCovered) {
continue;
}
/* Not yet covered. Check for collisions. */
const float distSq1 = absSq(relativePosition1);
const float distSq2 = absSq(relativePosition2);
const float radiusSq = sqr(radius_);
const Vector2 obstacleVector = obstacle2->point_ - obstacle1->point_;
const float s = (-relativePosition1 * obstacleVector) / absSq(obstacleVector);
const float distSqLine = absSq(-relativePosition1 - s * obstacleVector);
Line line;
if (s < 0.0f && distSq1 <= radiusSq) {
/* Collision with left vertex. Ignore if non-convex. */
if (obstacle1->isConvex_) {
line.point = Vector2(0.0f, 0.0f);
line.direction = normalize(Vector2(-relativePosition1.y(), relativePosition1.x()));
orcaLines_.push_back(line);
}
continue;
}
else if (s > 1.0f && distSq2 <= radiusSq) {
/* Collision with right vertex. Ignore if non-convex
* or if it will be taken care of by neighoring obstace */
if (obstacle2->isConvex_ && det(relativePosition2, obstacle2->unitDir_) >= 0.0f) {
line.point = Vector2(0.0f, 0.0f);
line.direction = normalize(Vector2(-relativePosition2.y(), relativePosition2.x()));
orcaLines_.push_back(line);
}
continue;
}
else if (s >= 0.0f && s < 1.0f && distSqLine <= radiusSq) {
/* Collision with obstacle segment. */
line.point = Vector2(0.0f, 0.0f);
line.direction = -obstacle1->unitDir_;
orcaLines_.push_back(line);
continue;
}
/*
* No collision.
* Compute legs. When obliquely viewed, both legs can come from a single
* vertex. Legs extend cut-off line when nonconvex vertex.
*/
Vector2 leftLegDirection, rightLegDirection;
if (s < 0.0f && distSqLine <= radiusSq) {
/*
* Obstacle viewed obliquely so that left vertex
* defines velocity obstacle.
*/
if (!obstacle1->isConvex_) {
/* Ignore obstacle. */
continue;
}
obstacle2 = obstacle1;
const float leg1 = std::sqrt(distSq1 - radiusSq);
leftLegDirection = Vector2(relativePosition1.x() * leg1 - relativePosition1.y() * radius_, relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
rightLegDirection = Vector2(relativePosition1.x() * leg1 + relativePosition1.y() * radius_, -relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
}
else if (s > 1.0f && distSqLine <= radiusSq) {
/*
* Obstacle viewed obliquely so that
* right vertex defines velocity obstacle.
*/
if (!obstacle2->isConvex_) {
/* Ignore obstacle. */
continue;
}
obstacle1 = obstacle2;
const float leg2 = std::sqrt(distSq2 - radiusSq);
leftLegDirection = Vector2(relativePosition2.x() * leg2 - relativePosition2.y() * radius_, relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
rightLegDirection = Vector2(relativePosition2.x() * leg2 + relativePosition2.y() * radius_, -relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
}
else {
/* Usual situation. */
if (obstacle1->isConvex_) {
const float leg1 = std::sqrt(distSq1 - radiusSq);
leftLegDirection = Vector2(relativePosition1.x() * leg1 - relativePosition1.y() * radius_, relativePosition1.x() * radius_ + relativePosition1.y() * leg1) / distSq1;
}
else {
/* Left vertex non-convex; left leg extends cut-off line. */
leftLegDirection = -obstacle1->unitDir_;
}
if (obstacle2->isConvex_) {
const float leg2 = std::sqrt(distSq2 - radiusSq);
rightLegDirection = Vector2(relativePosition2.x() * leg2 + relativePosition2.y() * radius_, -relativePosition2.x() * radius_ + relativePosition2.y() * leg2) / distSq2;
}
else {
/* Right vertex non-convex; right leg extends cut-off line. */
rightLegDirection = obstacle1->unitDir_;
}
}
/*
* Legs can never point into neighboring edge when convex vertex,
* take cutoff-line of neighboring edge instead. If velocity projected on
* "foreign" leg, no constraint is added.
*/
const Obstacle2D *const leftNeighbor = obstacle1->prevObstacle_;
bool isLeftLegForeign = false;
bool isRightLegForeign = false;
if (obstacle1->isConvex_ && det(leftLegDirection, -leftNeighbor->unitDir_) >= 0.0f) {
/* Left leg points into obstacle. */
leftLegDirection = -leftNeighbor->unitDir_;
isLeftLegForeign = true;
}
if (obstacle2->isConvex_ && det(rightLegDirection, obstacle2->unitDir_) <= 0.0f) {
/* Right leg points into obstacle. */
rightLegDirection = obstacle2->unitDir_;
isRightLegForeign = true;
}
/* Compute cut-off centers. */
const Vector2 leftCutoff = invTimeHorizonObst * (obstacle1->point_ - position_);
const Vector2 rightCutoff = invTimeHorizonObst * (obstacle2->point_ - position_);
const Vector2 cutoffVec = rightCutoff - leftCutoff;
/* Project current velocity on velocity obstacle. */
/* Check if current velocity is projected on cutoff circles. */
const float t = (obstacle1 == obstacle2 ? 0.5f : ((velocity_ - leftCutoff) * cutoffVec) / absSq(cutoffVec));
const float tLeft = ((velocity_ - leftCutoff) * leftLegDirection);
const float tRight = ((velocity_ - rightCutoff) * rightLegDirection);
if ((t < 0.0f && tLeft < 0.0f) || (obstacle1 == obstacle2 && tLeft < 0.0f && tRight < 0.0f)) {
/* Project on left cut-off circle. */
const Vector2 unitW = normalize(velocity_ - leftCutoff);
line.direction = Vector2(unitW.y(), -unitW.x());
line.point = leftCutoff + radius_ * invTimeHorizonObst * unitW;
orcaLines_.push_back(line);
continue;
}
else if (t > 1.0f && tRight < 0.0f) {
/* Project on right cut-off circle. */
const Vector2 unitW = normalize(velocity_ - rightCutoff);
line.direction = Vector2(unitW.y(), -unitW.x());
line.point = rightCutoff + radius_ * invTimeHorizonObst * unitW;
orcaLines_.push_back(line);
continue;
}
/*
* Project on left leg, right leg, or cut-off line, whichever is closest
* to velocity.
*/
const float distSqCutoff = ((t < 0.0f || t > 1.0f || obstacle1 == obstacle2) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (leftCutoff + t * cutoffVec)));
const float distSqLeft = ((tLeft < 0.0f) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (leftCutoff + tLeft * leftLegDirection)));
const float distSqRight = ((tRight < 0.0f) ? std::numeric_limits<float>::infinity() : absSq(velocity_ - (rightCutoff + tRight * rightLegDirection)));
if (distSqCutoff <= distSqLeft && distSqCutoff <= distSqRight) {
/* Project on cut-off line. */
line.direction = -obstacle1->unitDir_;
line.point = leftCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
orcaLines_.push_back(line);
continue;
}
else if (distSqLeft <= distSqRight) {
/* Project on left leg. */
if (isLeftLegForeign) {
continue;
}
line.direction = leftLegDirection;
line.point = leftCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
orcaLines_.push_back(line);
continue;
}
else {
/* Project on right leg. */
if (isRightLegForeign) {
continue;
}
line.direction = -rightLegDirection;
line.point = rightCutoff + radius_ * invTimeHorizonObst * Vector2(-line.direction.y(), line.direction.x());
orcaLines_.push_back(line);
continue;
}
}
const size_t numObstLines = orcaLines_.size();
const float invTimeHorizon = 1.0f / timeHorizon_;
/* Create agent ORCA lines. */
for (size_t i = 0; i < agentNeighbors_.size(); ++i) {
const Agent2D *const other = agentNeighbors_[i].second;
//const float timeHorizon_mod = (avoidance_priority_ - other->avoidance_priority_ + 1.0f) * 0.5f;
//const float invTimeHorizon = (1.0f / timeHorizon_) * timeHorizon_mod;
const Vector2 relativePosition = other->position_ - position_;
const Vector2 relativeVelocity = velocity_ - other->velocity_;
const float distSq = absSq(relativePosition);
const float combinedRadius = radius_ + other->radius_;
const float combinedRadiusSq = sqr(combinedRadius);
Line line;
Vector2 u;
if (distSq > combinedRadiusSq) {
/* No collision. */
const Vector2 w = relativeVelocity - invTimeHorizon * relativePosition;
/* Vector from cutoff center to relative velocity. */
const float wLengthSq = absSq(w);
const float dotProduct1 = w * relativePosition;
if (dotProduct1 < 0.0f && sqr(dotProduct1) > combinedRadiusSq * wLengthSq) {
/* Project on cut-off circle. */
const float wLength = std::sqrt(wLengthSq);
const Vector2 unitW = w / wLength;
line.direction = Vector2(unitW.y(), -unitW.x());
u = (combinedRadius * invTimeHorizon - wLength) * unitW;
}
else {
/* Project on legs. */
const float leg = std::sqrt(distSq - combinedRadiusSq);
if (det(relativePosition, w) > 0.0f) {
/* Project on left leg. */
line.direction = Vector2(relativePosition.x() * leg - relativePosition.y() * combinedRadius, relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
}
else {
/* Project on right leg. */
line.direction = -Vector2(relativePosition.x() * leg + relativePosition.y() * combinedRadius, -relativePosition.x() * combinedRadius + relativePosition.y() * leg) / distSq;
}
const float dotProduct2 = relativeVelocity * line.direction;
u = dotProduct2 * line.direction - relativeVelocity;
}
}
else {
/* Collision. Project on cut-off circle of time timeStep. */
const float invTimeStep = 1.0f / sim_->timeStep_;
/* Vector from cutoff center to relative velocity. */
const Vector2 w = relativeVelocity - invTimeStep * relativePosition;
const float wLength = abs(w);
const Vector2 unitW = w / wLength;
line.direction = Vector2(unitW.y(), -unitW.x());
u = (combinedRadius * invTimeStep - wLength) * unitW;
}
line.point = velocity_ + 0.5f * u;
orcaLines_.push_back(line);
}
size_t lineFail = linearProgram2(orcaLines_, maxSpeed_, prefVelocity_, false, newVelocity_);
if (lineFail < orcaLines_.size()) {
linearProgram3(orcaLines_, numObstLines, lineFail, maxSpeed_, newVelocity_);
}
}
void Agent2D::insertAgentNeighbor(const Agent2D *agent, float &rangeSq)
{
// no point processing same agent
if (this == agent) {
return;
}
// ignore other agent if layers/mask bitmasks have no matching bit
if ((avoidance_mask_ & agent->avoidance_layers_) == 0) {
return;
}
// ignore other agent if this agent is below or above
if ((elevation_ > agent->elevation_ + agent->height_) || (elevation_ + height_ < agent->elevation_)) {
return;
}
if (avoidance_priority_ > agent->avoidance_priority_) {
return;
}
const float distSq = absSq(position_ - agent->position_);
if (distSq < rangeSq) {
if (agentNeighbors_.size() < maxNeighbors_) {
agentNeighbors_.push_back(std::make_pair(distSq, agent));
}
size_t i = agentNeighbors_.size() - 1;
while (i != 0 && distSq < agentNeighbors_[i - 1].first) {
agentNeighbors_[i] = agentNeighbors_[i - 1];
--i;
}
agentNeighbors_[i] = std::make_pair(distSq, agent);
if (agentNeighbors_.size() == maxNeighbors_) {
rangeSq = agentNeighbors_.back().first;
}
}
}
void Agent2D::insertObstacleNeighbor(const Obstacle2D *obstacle, float rangeSq)
{
const Obstacle2D *const nextObstacle = obstacle->nextObstacle_;
// ignore obstacle if no matching layer/mask
if ((avoidance_mask_ & nextObstacle->avoidance_layers_) == 0) {
return;
}
// ignore obstacle if below or above
if ((elevation_ > obstacle->elevation_ + obstacle->height_) || (elevation_ + height_ < obstacle->elevation_)) {
return;
}
const float distSq = distSqPointLineSegment(obstacle->point_, nextObstacle->point_, position_);
if (distSq < rangeSq) {
obstacleNeighbors_.push_back(std::make_pair(distSq, obstacle));
size_t i = obstacleNeighbors_.size() - 1;
while (i != 0 && distSq < obstacleNeighbors_[i - 1].first) {
obstacleNeighbors_[i] = obstacleNeighbors_[i - 1];
--i;
}
obstacleNeighbors_[i] = std::make_pair(distSq, obstacle);
}
//}
}
void Agent2D::update(RVOSimulator2D *sim_)
{
velocity_ = newVelocity_;
position_ += velocity_ * sim_->timeStep_;
}
bool linearProgram1(const std::vector<Line> &lines, size_t lineNo, float radius, const Vector2 &optVelocity, bool directionOpt, Vector2 &result)
{
const float dotProduct = lines[lineNo].point * lines[lineNo].direction;
const float discriminant = sqr(dotProduct) + sqr(radius) - absSq(lines[lineNo].point);
if (discriminant < 0.0f) {
/* Max speed circle fully invalidates line lineNo. */
return false;
}
const float sqrtDiscriminant = std::sqrt(discriminant);
float tLeft = -dotProduct - sqrtDiscriminant;
float tRight = -dotProduct + sqrtDiscriminant;
for (size_t i = 0; i < lineNo; ++i) {
const float denominator = det(lines[lineNo].direction, lines[i].direction);
const float numerator = det(lines[i].direction, lines[lineNo].point - lines[i].point);
if (std::fabs(denominator) <= RVO_EPSILON) {
/* Lines lineNo and i are (almost) parallel. */
if (numerator < 0.0f) {
return false;
}
else {
continue;
}
}
const float t = numerator / denominator;
if (denominator >= 0.0f) {
/* Line i bounds line lineNo on the right. */
tRight = std::min(tRight, t);
}
else {
/* Line i bounds line lineNo on the left. */
tLeft = std::max(tLeft, t);
}
if (tLeft > tRight) {
return false;
}
}
if (directionOpt) {
/* Optimize direction. */
if (optVelocity * lines[lineNo].direction > 0.0f) {
/* Take right extreme. */
result = lines[lineNo].point + tRight * lines[lineNo].direction;
}
else {
/* Take left extreme. */
result = lines[lineNo].point + tLeft * lines[lineNo].direction;
}
}
else {
/* Optimize closest point. */
const float t = lines[lineNo].direction * (optVelocity - lines[lineNo].point);
if (t < tLeft) {
result = lines[lineNo].point + tLeft * lines[lineNo].direction;
}
else if (t > tRight) {
result = lines[lineNo].point + tRight * lines[lineNo].direction;
}
else {
result = lines[lineNo].point + t * lines[lineNo].direction;
}
}
return true;
}
size_t linearProgram2(const std::vector<Line> &lines, float radius, const Vector2 &optVelocity, bool directionOpt, Vector2 &result)
{
if (directionOpt) {
/*
* Optimize direction. Note that the optimization velocity is of unit
* length in this case.
*/
result = optVelocity * radius;
}
else if (absSq(optVelocity) > sqr(radius)) {
/* Optimize closest point and outside circle. */
result = normalize(optVelocity) * radius;
}
else {
/* Optimize closest point and inside circle. */
result = optVelocity;
}
for (size_t i = 0; i < lines.size(); ++i) {
if (det(lines[i].direction, lines[i].point - result) > 0.0f) {
/* Result does not satisfy constraint i. Compute new optimal result. */
const Vector2 tempResult = result;
if (!linearProgram1(lines, i, radius, optVelocity, directionOpt, result)) {
result = tempResult;
return i;
}
}
}
return lines.size();
}
void linearProgram3(const std::vector<Line> &lines, size_t numObstLines, size_t beginLine, float radius, Vector2 &result)
{
float distance = 0.0f;
for (size_t i = beginLine; i < lines.size(); ++i) {
if (det(lines[i].direction, lines[i].point - result) > distance) {
/* Result does not satisfy constraint of line i. */
std::vector<Line> projLines(lines.begin(), lines.begin() + static_cast<ptrdiff_t>(numObstLines));
for (size_t j = numObstLines; j < i; ++j) {
Line line;
float determinant = det(lines[i].direction, lines[j].direction);
if (std::fabs(determinant) <= RVO_EPSILON) {
/* Line i and line j are parallel. */
if (lines[i].direction * lines[j].direction > 0.0f) {
/* Line i and line j point in the same direction. */
continue;
}
else {
/* Line i and line j point in opposite direction. */
line.point = 0.5f * (lines[i].point + lines[j].point);
}
}
else {
line.point = lines[i].point + (det(lines[j].direction, lines[i].point - lines[j].point) / determinant) * lines[i].direction;
}
line.direction = normalize(lines[j].direction - lines[i].direction);
projLines.push_back(line);
}
const Vector2 tempResult = result;
if (linearProgram2(projLines, radius, Vector2(-lines[i].direction.y(), lines[i].direction.x()), true, result) < projLines.size()) {
/* This should in principle not happen. The result is by definition
* already in the feasible region of this linear program. If it fails,
* it is due to small floating point error, and the current result is
* kept.
*/
result = tempResult;
}
distance = det(lines[i].direction, lines[i].point - result);
}
}
}
}

160
thirdparty/rvo2/rvo2_2d/Agent2d.h vendored Normal file
View File

@@ -0,0 +1,160 @@
/*
* Agent2d.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO2D_AGENT_H_
#define RVO2D_AGENT_H_
/**
* \file Agent2d.h
* \brief Contains the Agent class.
*/
#include "Definitions.h"
#include "RVOSimulator2d.h"
namespace RVO2D {
/**
* \brief Defines an agent in the simulation.
*/
class Agent2D {
public:
/**
* \brief Constructs an agent instance.
* \param sim The simulator instance.
*/
explicit Agent2D();
/**
* \brief Computes the neighbors of this agent.
*/
void computeNeighbors(RVOSimulator2D *sim_);
/**
* \brief Computes the new velocity of this agent.
*/
void computeNewVelocity(RVOSimulator2D *sim_);
/**
* \brief Inserts an agent neighbor into the set of neighbors of
* this agent.
* \param agent A pointer to the agent to be inserted.
* \param rangeSq The squared range around this agent.
*/
void insertAgentNeighbor(const Agent2D *agent, float &rangeSq);
/**
* \brief Inserts a static obstacle neighbor into the set of neighbors
* of this agent.
* \param obstacle The number of the static obstacle to be
* inserted.
* \param rangeSq The squared range around this agent.
*/
void insertObstacleNeighbor(const Obstacle2D *obstacle, float rangeSq);
/**
* \brief Updates the two-dimensional position and two-dimensional
* velocity of this agent.
*/
void update(RVOSimulator2D *sim_);
std::vector<std::pair<float, const Agent2D *> > agentNeighbors_;
size_t maxNeighbors_;
float maxSpeed_;
float neighborDist_;
Vector2 newVelocity_;
std::vector<std::pair<float, const Obstacle2D *> > obstacleNeighbors_;
std::vector<Line> orcaLines_;
Vector2 position_;
Vector2 prefVelocity_;
float radius_;
float timeHorizon_;
float timeHorizonObst_;
Vector2 velocity_;
float height_ = 0.0;
float elevation_ = 0.0;
uint32_t avoidance_layers_ = 1;
uint32_t avoidance_mask_ = 1;
float avoidance_priority_ = 1.0;
size_t id_;
friend class KdTree2D;
friend class RVOSimulator2D;
};
/**
* \relates Agent
* \brief Solves a one-dimensional linear program on a specified line
* subject to linear constraints defined by lines and a circular
* constraint.
* \param lines Lines defining the linear constraints.
* \param lineNo The specified line constraint.
* \param radius The radius of the circular constraint.
* \param optVelocity The optimization velocity.
* \param directionOpt True if the direction should be optimized.
* \param result A reference to the result of the linear program.
* \return True if successful.
*/
bool linearProgram1(const std::vector<Line> &lines, size_t lineNo,
float radius, const Vector2 &optVelocity,
bool directionOpt, Vector2 &result);
/**
* \relates Agent
* \brief Solves a two-dimensional linear program subject to linear
* constraints defined by lines and a circular constraint.
* \param lines Lines defining the linear constraints.
* \param radius The radius of the circular constraint.
* \param optVelocity The optimization velocity.
* \param directionOpt True if the direction should be optimized.
* \param result A reference to the result of the linear program.
* \return The number of the line it fails on, and the number of lines if successful.
*/
size_t linearProgram2(const std::vector<Line> &lines, float radius,
const Vector2 &optVelocity, bool directionOpt,
Vector2 &result);
/**
* \relates Agent
* \brief Solves a two-dimensional linear program subject to linear
* constraints defined by lines and a circular constraint.
* \param lines Lines defining the linear constraints.
* \param numObstLines Count of obstacle lines.
* \param beginLine The line on which the 2-d linear program failed.
* \param radius The radius of the circular constraint.
* \param result A reference to the result of the linear program.
*/
void linearProgram3(const std::vector<Line> &lines, size_t numObstLines, size_t beginLine,
float radius, Vector2 &result);
}
#endif /* RVO2D_AGENT_H_ */

110
thirdparty/rvo2/rvo2_2d/Definitions.h vendored Normal file
View File

@@ -0,0 +1,110 @@
/*
* Definitions.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO2D_DEFINITIONS_H_
#define RVO2D_DEFINITIONS_H_
/**
* \file Definitions.h
* \brief Contains functions and constants used in multiple classes.
*/
#include <algorithm>
#include <cmath>
#include <cstddef>
#include <cstdint>
#include <limits>
#include <vector>
#include "Vector2.h"
/**
* \brief A sufficiently small positive number.
*/
const float RVO_EPSILON = 0.00001f;
namespace RVO2D {
class Agent2D;
class Obstacle2D;
class RVOSimulator2D;
/**
* \brief Computes the squared distance from a line segment with the
* specified endpoints to a specified point.
* \param a The first endpoint of the line segment.
* \param b The second endpoint of the line segment.
* \param c The point to which the squared distance is to
* be calculated.
* \return The squared distance from the line segment to the point.
*/
inline float distSqPointLineSegment(const Vector2 &a, const Vector2 &b,
const Vector2 &c)
{
const float r = ((c - a) * (b - a)) / absSq(b - a);
if (r < 0.0f) {
return absSq(c - a);
}
else if (r > 1.0f) {
return absSq(c - b);
}
else {
return absSq(c - (a + r * (b - a)));
}
}
/**
* \brief Computes the signed distance from a line connecting the
* specified points to a specified point.
* \param a The first point on the line.
* \param b The second point on the line.
* \param c The point to which the signed distance is to
* be calculated.
* \return Positive when the point c lies to the left of the line ab.
*/
inline float leftOf(const Vector2 &a, const Vector2 &b, const Vector2 &c)
{
return det(a - c, b - a);
}
/**
* \brief Computes the square of a float.
* \param a The float to be squared.
* \return The square of the float.
*/
inline float sqr(float a)
{
return a * a;
}
}
#endif /* RVO2D_DEFINITIONS_H_ */

357
thirdparty/rvo2/rvo2_2d/KdTree2d.cpp vendored Normal file
View File

@@ -0,0 +1,357 @@
/*
* KdTree2d.cpp
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#include "KdTree2d.h"
#include "Agent2d.h"
#include "RVOSimulator2d.h"
#include "Obstacle2d.h"
namespace RVO2D {
KdTree2D::KdTree2D(RVOSimulator2D *sim) : obstacleTree_(NULL), sim_(sim) { }
KdTree2D::~KdTree2D()
{
deleteObstacleTree(obstacleTree_);
}
void KdTree2D::buildAgentTree(std::vector<Agent2D *> agents)
{
agents_.swap(agents);
if (!agents_.empty()) {
agentTree_.resize(2 * agents_.size() - 1);
buildAgentTreeRecursive(0, agents_.size(), 0);
}
}
void KdTree2D::buildAgentTreeRecursive(size_t begin, size_t end, size_t node)
{
agentTree_[node].begin = begin;
agentTree_[node].end = end;
agentTree_[node].minX = agentTree_[node].maxX = agents_[begin]->position_.x();
agentTree_[node].minY = agentTree_[node].maxY = agents_[begin]->position_.y();
for (size_t i = begin + 1; i < end; ++i) {
agentTree_[node].maxX = std::max(agentTree_[node].maxX, agents_[i]->position_.x());
agentTree_[node].minX = std::min(agentTree_[node].minX, agents_[i]->position_.x());
agentTree_[node].maxY = std::max(agentTree_[node].maxY, agents_[i]->position_.y());
agentTree_[node].minY = std::min(agentTree_[node].minY, agents_[i]->position_.y());
}
if (end - begin > MAX_LEAF_SIZE) {
/* No leaf node. */
const bool isVertical = (agentTree_[node].maxX - agentTree_[node].minX > agentTree_[node].maxY - agentTree_[node].minY);
const float splitValue = (isVertical ? 0.5f * (agentTree_[node].maxX + agentTree_[node].minX) : 0.5f * (agentTree_[node].maxY + agentTree_[node].minY));
size_t left = begin;
size_t right = end;
while (left < right) {
while (left < right && (isVertical ? agents_[left]->position_.x() : agents_[left]->position_.y()) < splitValue) {
++left;
}
while (right > left && (isVertical ? agents_[right - 1]->position_.x() : agents_[right - 1]->position_.y()) >= splitValue) {
--right;
}
if (left < right) {
std::swap(agents_[left], agents_[right - 1]);
++left;
--right;
}
}
if (left == begin) {
++left;
++right;
}
agentTree_[node].left = node + 1;
agentTree_[node].right = node + 2 * (left - begin);
buildAgentTreeRecursive(begin, left, agentTree_[node].left);
buildAgentTreeRecursive(left, end, agentTree_[node].right);
}
}
void KdTree2D::buildObstacleTree(std::vector<Obstacle2D *> obstacles)
{
deleteObstacleTree(obstacleTree_);
obstacleTree_ = buildObstacleTreeRecursive(obstacles);
}
KdTree2D::ObstacleTreeNode *KdTree2D::buildObstacleTreeRecursive(const std::vector<Obstacle2D *> &obstacles)
{
if (obstacles.empty()) {
return NULL;
}
else {
ObstacleTreeNode *const node = new ObstacleTreeNode;
size_t optimalSplit = 0;
size_t minLeft = obstacles.size();
size_t minRight = obstacles.size();
for (size_t i = 0; i < obstacles.size(); ++i) {
size_t leftSize = 0;
size_t rightSize = 0;
const Obstacle2D *const obstacleI1 = obstacles[i];
const Obstacle2D *const obstacleI2 = obstacleI1->nextObstacle_;
/* Compute optimal split node. */
for (size_t j = 0; j < obstacles.size(); ++j) {
if (i == j) {
continue;
}
const Obstacle2D *const obstacleJ1 = obstacles[j];
const Obstacle2D *const obstacleJ2 = obstacleJ1->nextObstacle_;
const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);
if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
++leftSize;
}
else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
++rightSize;
}
else {
++leftSize;
++rightSize;
}
if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) >= std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
break;
}
}
if (std::make_pair(std::max(leftSize, rightSize), std::min(leftSize, rightSize)) < std::make_pair(std::max(minLeft, minRight), std::min(minLeft, minRight))) {
minLeft = leftSize;
minRight = rightSize;
optimalSplit = i;
}
}
/* Build split node. */
std::vector<Obstacle2D *> leftObstacles(minLeft);
std::vector<Obstacle2D *> rightObstacles(minRight);
size_t leftCounter = 0;
size_t rightCounter = 0;
const size_t i = optimalSplit;
const Obstacle2D *const obstacleI1 = obstacles[i];
const Obstacle2D *const obstacleI2 = obstacleI1->nextObstacle_;
for (size_t j = 0; j < obstacles.size(); ++j) {
if (i == j) {
continue;
}
Obstacle2D *const obstacleJ1 = obstacles[j];
Obstacle2D *const obstacleJ2 = obstacleJ1->nextObstacle_;
const float j1LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ1->point_);
const float j2LeftOfI = leftOf(obstacleI1->point_, obstacleI2->point_, obstacleJ2->point_);
if (j1LeftOfI >= -RVO_EPSILON && j2LeftOfI >= -RVO_EPSILON) {
leftObstacles[leftCounter++] = obstacles[j];
}
else if (j1LeftOfI <= RVO_EPSILON && j2LeftOfI <= RVO_EPSILON) {
rightObstacles[rightCounter++] = obstacles[j];
}
else {
/* Split obstacle j. */
const float t = det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleI1->point_) / det(obstacleI2->point_ - obstacleI1->point_, obstacleJ1->point_ - obstacleJ2->point_);
const Vector2 splitpoint = obstacleJ1->point_ + t * (obstacleJ2->point_ - obstacleJ1->point_);
Obstacle2D *const newObstacle = new Obstacle2D();
newObstacle->point_ = splitpoint;
newObstacle->prevObstacle_ = obstacleJ1;
newObstacle->nextObstacle_ = obstacleJ2;
newObstacle->isConvex_ = true;
newObstacle->unitDir_ = obstacleJ1->unitDir_;
newObstacle->id_ = sim_->obstacles_.size();
sim_->obstacles_.push_back(newObstacle);
obstacleJ1->nextObstacle_ = newObstacle;
obstacleJ2->prevObstacle_ = newObstacle;
if (j1LeftOfI > 0.0f) {
leftObstacles[leftCounter++] = obstacleJ1;
rightObstacles[rightCounter++] = newObstacle;
}
else {
rightObstacles[rightCounter++] = obstacleJ1;
leftObstacles[leftCounter++] = newObstacle;
}
}
}
node->obstacle = obstacleI1;
node->left = buildObstacleTreeRecursive(leftObstacles);
node->right = buildObstacleTreeRecursive(rightObstacles);
return node;
}
}
void KdTree2D::computeAgentNeighbors(Agent2D *agent, float &rangeSq) const
{
queryAgentTreeRecursive(agent, rangeSq, 0);
}
void KdTree2D::computeObstacleNeighbors(Agent2D *agent, float rangeSq) const
{
queryObstacleTreeRecursive(agent, rangeSq, obstacleTree_);
}
void KdTree2D::deleteObstacleTree(ObstacleTreeNode *node)
{
if (node != NULL) {
deleteObstacleTree(node->left);
deleteObstacleTree(node->right);
delete node;
}
}
void KdTree2D::queryAgentTreeRecursive(Agent2D *agent, float &rangeSq, size_t node) const
{
if (agentTree_[node].end - agentTree_[node].begin <= MAX_LEAF_SIZE) {
for (size_t i = agentTree_[node].begin; i < agentTree_[node].end; ++i) {
agent->insertAgentNeighbor(agents_[i], rangeSq);
}
}
else {
const float distSqLeft = sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].left].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].left].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].left].maxY));
const float distSqRight = sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minX - agent->position_.x())) + sqr(std::max(0.0f, agent->position_.x() - agentTree_[agentTree_[node].right].maxX)) + sqr(std::max(0.0f, agentTree_[agentTree_[node].right].minY - agent->position_.y())) + sqr(std::max(0.0f, agent->position_.y() - agentTree_[agentTree_[node].right].maxY));
if (distSqLeft < distSqRight) {
if (distSqLeft < rangeSq) {
queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
if (distSqRight < rangeSq) {
queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
}
}
}
else {
if (distSqRight < rangeSq) {
queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].right);
if (distSqLeft < rangeSq) {
queryAgentTreeRecursive(agent, rangeSq, agentTree_[node].left);
}
}
}
}
}
void KdTree2D::queryObstacleTreeRecursive(Agent2D *agent, float rangeSq, const ObstacleTreeNode *node) const
{
if (node == NULL) {
return;
}
else {
const Obstacle2D *const obstacle1 = node->obstacle;
const Obstacle2D *const obstacle2 = obstacle1->nextObstacle_;
const float agentLeftOfLine = leftOf(obstacle1->point_, obstacle2->point_, agent->position_);
queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0.0f ? node->left : node->right));
const float distSqLine = sqr(agentLeftOfLine) / absSq(obstacle2->point_ - obstacle1->point_);
if (distSqLine < rangeSq) {
if (agentLeftOfLine < 0.0f) {
/*
* Try obstacle at this node only if agent is on right side of
* obstacle (and can see obstacle).
*/
agent->insertObstacleNeighbor(node->obstacle, rangeSq);
}
/* Try other side of line. */
queryObstacleTreeRecursive(agent, rangeSq, (agentLeftOfLine >= 0.0f ? node->right : node->left));
}
}
}
bool KdTree2D::queryVisibility(const Vector2 &q1, const Vector2 &q2, float radius) const
{
return queryVisibilityRecursive(q1, q2, radius, obstacleTree_);
}
bool KdTree2D::queryVisibilityRecursive(const Vector2 &q1, const Vector2 &q2, float radius, const ObstacleTreeNode *node) const
{
if (node == NULL) {
return true;
}
else {
const Obstacle2D *const obstacle1 = node->obstacle;
const Obstacle2D *const obstacle2 = obstacle1->nextObstacle_;
const float q1LeftOfI = leftOf(obstacle1->point_, obstacle2->point_, q1);
const float q2LeftOfI = leftOf(obstacle1->point_, obstacle2->point_, q2);
const float invLengthI = 1.0f / absSq(obstacle2->point_ - obstacle1->point_);
if (q1LeftOfI >= 0.0f && q2LeftOfI >= 0.0f) {
return queryVisibilityRecursive(q1, q2, radius, node->left) && ((sqr(q1LeftOfI) * invLengthI >= sqr(radius) && sqr(q2LeftOfI) * invLengthI >= sqr(radius)) || queryVisibilityRecursive(q1, q2, radius, node->right));
}
else if (q1LeftOfI <= 0.0f && q2LeftOfI <= 0.0f) {
return queryVisibilityRecursive(q1, q2, radius, node->right) && ((sqr(q1LeftOfI) * invLengthI >= sqr(radius) && sqr(q2LeftOfI) * invLengthI >= sqr(radius)) || queryVisibilityRecursive(q1, q2, radius, node->left));
}
else if (q1LeftOfI >= 0.0f && q2LeftOfI <= 0.0f) {
/* One can see through obstacle from left to right. */
return queryVisibilityRecursive(q1, q2, radius, node->left) && queryVisibilityRecursive(q1, q2, radius, node->right);
}
else {
const float point1LeftOfQ = leftOf(q1, q2, obstacle1->point_);
const float point2LeftOfQ = leftOf(q1, q2, obstacle2->point_);
const float invLengthQ = 1.0f / absSq(q2 - q1);
return (point1LeftOfQ * point2LeftOfQ >= 0.0f && sqr(point1LeftOfQ) * invLengthQ > sqr(radius) && sqr(point2LeftOfQ) * invLengthQ > sqr(radius) && queryVisibilityRecursive(q1, q2, radius, node->left) && queryVisibilityRecursive(q1, q2, radius, node->right));
}
}
}
}

203
thirdparty/rvo2/rvo2_2d/KdTree2d.h vendored Normal file
View File

@@ -0,0 +1,203 @@
/*
* KdTree2d.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO2D_KD_TREE_H_
#define RVO2D_KD_TREE_H_
/**
* \file KdTree2d.h
* \brief Contains the KdTree class.
*/
#include "Definitions.h"
namespace RVO2D {
/**
* \brief Defines <i>k</i>d-trees for agents and static obstacles in the
* simulation.
*/
class KdTree2D {
public:
/**
* \brief Defines an agent <i>k</i>d-tree node.
*/
class AgentTreeNode {
public:
/**
* \brief The beginning node number.
*/
size_t begin;
/**
* \brief The ending node number.
*/
size_t end;
/**
* \brief The left node number.
*/
size_t left;
/**
* \brief The maximum x-coordinate.
*/
float maxX;
/**
* \brief The maximum y-coordinate.
*/
float maxY;
/**
* \brief The minimum x-coordinate.
*/
float minX;
/**
* \brief The minimum y-coordinate.
*/
float minY;
/**
* \brief The right node number.
*/
size_t right;
};
/**
* \brief Defines an obstacle <i>k</i>d-tree node.
*/
class ObstacleTreeNode {
public:
/**
* \brief The left obstacle tree node.
*/
ObstacleTreeNode *left;
/**
* \brief The obstacle number.
*/
const Obstacle2D *obstacle;
/**
* \brief The right obstacle tree node.
*/
ObstacleTreeNode *right;
};
/**
* \brief Constructs a <i>k</i>d-tree instance.
* \param sim The simulator instance.
*/
explicit KdTree2D(RVOSimulator2D *sim);
/**
* \brief Destroys this kd-tree instance.
*/
~KdTree2D();
/**
* \brief Builds an agent <i>k</i>d-tree.
*/
void buildAgentTree(std::vector<Agent2D *> agents);
void buildAgentTreeRecursive(size_t begin, size_t end, size_t node);
/**
* \brief Builds an obstacle <i>k</i>d-tree.
*/
void buildObstacleTree(std::vector<Obstacle2D *> obstacles);
ObstacleTreeNode *buildObstacleTreeRecursive(const std::vector<Obstacle2D *> &
obstacles);
/**
* \brief Computes the agent neighbors of the specified agent.
* \param agent A pointer to the agent for which agent
* neighbors are to be computed.
* \param rangeSq The squared range around the agent.
*/
void computeAgentNeighbors(Agent2D *agent, float &rangeSq) const;
/**
* \brief Computes the obstacle neighbors of the specified agent.
* \param agent A pointer to the agent for which obstacle
* neighbors are to be computed.
* \param rangeSq The squared range around the agent.
*/
void computeObstacleNeighbors(Agent2D *agent, float rangeSq) const;
/**
* \brief Deletes the specified obstacle tree node.
* \param node A pointer to the obstacle tree node to be
* deleted.
*/
void deleteObstacleTree(ObstacleTreeNode *node);
void queryAgentTreeRecursive(Agent2D *agent, float &rangeSq,
size_t node) const;
void queryObstacleTreeRecursive(Agent2D *agent, float rangeSq,
const ObstacleTreeNode *node) const;
/**
* \brief Queries the visibility between two points within a
* specified radius.
* \param q1 The first point between which visibility is
* to be tested.
* \param q2 The second point between which visibility is
* to be tested.
* \param radius The radius within which visibility is to be
* tested.
* \return True if q1 and q2 are mutually visible within the radius;
* false otherwise.
*/
bool queryVisibility(const Vector2 &q1, const Vector2 &q2,
float radius) const;
bool queryVisibilityRecursive(const Vector2 &q1, const Vector2 &q2,
float radius,
const ObstacleTreeNode *node) const;
std::vector<Agent2D *> agents_;
std::vector<AgentTreeNode> agentTree_;
ObstacleTreeNode *obstacleTree_;
RVOSimulator2D *sim_;
static const size_t MAX_LEAF_SIZE = 10;
friend class Agent2D;
friend class RVOSimulator2D;
};
}
#endif /* RVO2D_KD_TREE_H_ */

38
thirdparty/rvo2/rvo2_2d/Obstacle2d.cpp vendored Normal file
View File

@@ -0,0 +1,38 @@
/*
* Obstacle2d.cpp
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#include "Obstacle2d.h"
#include "RVOSimulator2d.h"
namespace RVO2D {
Obstacle2D::Obstacle2D() : isConvex_(false), nextObstacle_(NULL), prevObstacle_(NULL), id_(0) { }
}

72
thirdparty/rvo2/rvo2_2d/Obstacle2d.h vendored Normal file
View File

@@ -0,0 +1,72 @@
/*
* Obstacle2d.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO2D_OBSTACLE_H_
#define RVO2D_OBSTACLE_H_
/**
* \file Obstacle2d.h
* \brief Contains the Obstacle class.
*/
#include "Definitions.h"
namespace RVO2D {
/**
* \brief Defines static obstacles in the simulation.
*/
class Obstacle2D {
public:
/**
* \brief Constructs a static obstacle instance.
*/
Obstacle2D();
bool isConvex_;
Obstacle2D *nextObstacle_;
Vector2 point_;
Obstacle2D *prevObstacle_;
Vector2 unitDir_;
float height_ = 1.0;
float elevation_ = 0.0;
uint32_t avoidance_layers_ = 1;
size_t id_;
friend class Agent2D;
friend class KdTree2D;
friend class RVOSimulator2D;
};
}
#endif /* RVO2D_OBSTACLE_H_ */

View File

@@ -0,0 +1,363 @@
/*
* RVOSimulator2d.cpp
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#include "RVOSimulator2d.h"
#include "Agent2d.h"
#include "KdTree2d.h"
#include "Obstacle2d.h"
#ifdef _OPENMP
#include <omp.h>
#endif
namespace RVO2D {
RVOSimulator2D::RVOSimulator2D() : defaultAgent_(NULL), globalTime_(0.0f), kdTree_(NULL), timeStep_(0.0f)
{
kdTree_ = new KdTree2D(this);
}
RVOSimulator2D::RVOSimulator2D(float timeStep, float neighborDist, size_t maxNeighbors, float timeHorizon, float timeHorizonObst, float radius, float maxSpeed, const Vector2 &velocity) : defaultAgent_(NULL), globalTime_(0.0f), kdTree_(NULL), timeStep_(timeStep)
{
kdTree_ = new KdTree2D(this);
defaultAgent_ = new Agent2D();
defaultAgent_->maxNeighbors_ = maxNeighbors;
defaultAgent_->maxSpeed_ = maxSpeed;
defaultAgent_->neighborDist_ = neighborDist;
defaultAgent_->radius_ = radius;
defaultAgent_->timeHorizon_ = timeHorizon;
defaultAgent_->timeHorizonObst_ = timeHorizonObst;
defaultAgent_->velocity_ = velocity;
}
RVOSimulator2D::~RVOSimulator2D()
{
if (defaultAgent_ != NULL) {
delete defaultAgent_;
}
for (size_t i = 0; i < agents_.size(); ++i) {
delete agents_[i];
}
for (size_t i = 0; i < obstacles_.size(); ++i) {
delete obstacles_[i];
}
delete kdTree_;
}
size_t RVOSimulator2D::addAgent(const Vector2 &position)
{
if (defaultAgent_ == NULL) {
return RVO2D_ERROR;
}
Agent2D *agent = new Agent2D();
agent->position_ = position;
agent->maxNeighbors_ = defaultAgent_->maxNeighbors_;
agent->maxSpeed_ = defaultAgent_->maxSpeed_;
agent->neighborDist_ = defaultAgent_->neighborDist_;
agent->radius_ = defaultAgent_->radius_;
agent->timeHorizon_ = defaultAgent_->timeHorizon_;
agent->timeHorizonObst_ = defaultAgent_->timeHorizonObst_;
agent->velocity_ = defaultAgent_->velocity_;
agent->id_ = agents_.size();
agents_.push_back(agent);
return agents_.size() - 1;
}
size_t RVOSimulator2D::addAgent(const Vector2 &position, float neighborDist, size_t maxNeighbors, float timeHorizon, float timeHorizonObst, float radius, float maxSpeed, const Vector2 &velocity)
{
Agent2D *agent = new Agent2D();
agent->position_ = position;
agent->maxNeighbors_ = maxNeighbors;
agent->maxSpeed_ = maxSpeed;
agent->neighborDist_ = neighborDist;
agent->radius_ = radius;
agent->timeHorizon_ = timeHorizon;
agent->timeHorizonObst_ = timeHorizonObst;
agent->velocity_ = velocity;
agent->id_ = agents_.size();
agents_.push_back(agent);
return agents_.size() - 1;
}
size_t RVOSimulator2D::addObstacle(const std::vector<Vector2> &vertices)
{
if (vertices.size() < 2) {
return RVO2D_ERROR;
}
const size_t obstacleNo = obstacles_.size();
for (size_t i = 0; i < vertices.size(); ++i) {
Obstacle2D *obstacle = new Obstacle2D();
obstacle->point_ = vertices[i];
if (i != 0) {
obstacle->prevObstacle_ = obstacles_.back();
obstacle->prevObstacle_->nextObstacle_ = obstacle;
}
if (i == vertices.size() - 1) {
obstacle->nextObstacle_ = obstacles_[obstacleNo];
obstacle->nextObstacle_->prevObstacle_ = obstacle;
}
obstacle->unitDir_ = normalize(vertices[(i == vertices.size() - 1 ? 0 : i + 1)] - vertices[i]);
if (vertices.size() == 2) {
obstacle->isConvex_ = true;
}
else {
obstacle->isConvex_ = (leftOf(vertices[(i == 0 ? vertices.size() - 1 : i - 1)], vertices[i], vertices[(i == vertices.size() - 1 ? 0 : i + 1)]) >= 0.0f);
}
obstacle->id_ = obstacles_.size();
obstacles_.push_back(obstacle);
}
return obstacleNo;
}
void RVOSimulator2D::doStep()
{
kdTree_->buildAgentTree(agents_);
for (int i = 0; i < static_cast<int>(agents_.size()); ++i) {
agents_[i]->computeNeighbors(this);
agents_[i]->computeNewVelocity(this);
}
for (int i = 0; i < static_cast<int>(agents_.size()); ++i) {
agents_[i]->update(this);
}
globalTime_ += timeStep_;
}
size_t RVOSimulator2D::getAgentAgentNeighbor(size_t agentNo, size_t neighborNo) const
{
return agents_[agentNo]->agentNeighbors_[neighborNo].second->id_;
}
size_t RVOSimulator2D::getAgentMaxNeighbors(size_t agentNo) const
{
return agents_[agentNo]->maxNeighbors_;
}
float RVOSimulator2D::getAgentMaxSpeed(size_t agentNo) const
{
return agents_[agentNo]->maxSpeed_;
}
float RVOSimulator2D::getAgentNeighborDist(size_t agentNo) const
{
return agents_[agentNo]->neighborDist_;
}
size_t RVOSimulator2D::getAgentNumAgentNeighbors(size_t agentNo) const
{
return agents_[agentNo]->agentNeighbors_.size();
}
size_t RVOSimulator2D::getAgentNumObstacleNeighbors(size_t agentNo) const
{
return agents_[agentNo]->obstacleNeighbors_.size();
}
size_t RVOSimulator2D::getAgentNumORCALines(size_t agentNo) const
{
return agents_[agentNo]->orcaLines_.size();
}
size_t RVOSimulator2D::getAgentObstacleNeighbor(size_t agentNo, size_t neighborNo) const
{
return agents_[agentNo]->obstacleNeighbors_[neighborNo].second->id_;
}
const Line &RVOSimulator2D::getAgentORCALine(size_t agentNo, size_t lineNo) const
{
return agents_[agentNo]->orcaLines_[lineNo];
}
const Vector2 &RVOSimulator2D::getAgentPosition(size_t agentNo) const
{
return agents_[agentNo]->position_;
}
const Vector2 &RVOSimulator2D::getAgentPrefVelocity(size_t agentNo) const
{
return agents_[agentNo]->prefVelocity_;
}
float RVOSimulator2D::getAgentRadius(size_t agentNo) const
{
return agents_[agentNo]->radius_;
}
float RVOSimulator2D::getAgentTimeHorizon(size_t agentNo) const
{
return agents_[agentNo]->timeHorizon_;
}
float RVOSimulator2D::getAgentTimeHorizonObst(size_t agentNo) const
{
return agents_[agentNo]->timeHorizonObst_;
}
const Vector2 &RVOSimulator2D::getAgentVelocity(size_t agentNo) const
{
return agents_[agentNo]->velocity_;
}
float RVOSimulator2D::getGlobalTime() const
{
return globalTime_;
}
size_t RVOSimulator2D::getNumAgents() const
{
return agents_.size();
}
size_t RVOSimulator2D::getNumObstacleVertices() const
{
return obstacles_.size();
}
const Vector2 &RVOSimulator2D::getObstacleVertex(size_t vertexNo) const
{
return obstacles_[vertexNo]->point_;
}
size_t RVOSimulator2D::getNextObstacleVertexNo(size_t vertexNo) const
{
return obstacles_[vertexNo]->nextObstacle_->id_;
}
size_t RVOSimulator2D::getPrevObstacleVertexNo(size_t vertexNo) const
{
return obstacles_[vertexNo]->prevObstacle_->id_;
}
float RVOSimulator2D::getTimeStep() const
{
return timeStep_;
}
void RVOSimulator2D::processObstacles()
{
kdTree_->buildObstacleTree(obstacles_);
}
bool RVOSimulator2D::queryVisibility(const Vector2 &point1, const Vector2 &point2, float radius) const
{
return kdTree_->queryVisibility(point1, point2, radius);
}
void RVOSimulator2D::setAgentDefaults(float neighborDist, size_t maxNeighbors, float timeHorizon, float timeHorizonObst, float radius, float maxSpeed, const Vector2 &velocity)
{
if (defaultAgent_ == NULL) {
defaultAgent_ = new Agent2D();
}
defaultAgent_->maxNeighbors_ = maxNeighbors;
defaultAgent_->maxSpeed_ = maxSpeed;
defaultAgent_->neighborDist_ = neighborDist;
defaultAgent_->radius_ = radius;
defaultAgent_->timeHorizon_ = timeHorizon;
defaultAgent_->timeHorizonObst_ = timeHorizonObst;
defaultAgent_->velocity_ = velocity;
}
void RVOSimulator2D::setAgentMaxNeighbors(size_t agentNo, size_t maxNeighbors)
{
agents_[agentNo]->maxNeighbors_ = maxNeighbors;
}
void RVOSimulator2D::setAgentMaxSpeed(size_t agentNo, float maxSpeed)
{
agents_[agentNo]->maxSpeed_ = maxSpeed;
}
void RVOSimulator2D::setAgentNeighborDist(size_t agentNo, float neighborDist)
{
agents_[agentNo]->neighborDist_ = neighborDist;
}
void RVOSimulator2D::setAgentPosition(size_t agentNo, const Vector2 &position)
{
agents_[agentNo]->position_ = position;
}
void RVOSimulator2D::setAgentPrefVelocity(size_t agentNo, const Vector2 &prefVelocity)
{
agents_[agentNo]->prefVelocity_ = prefVelocity;
}
void RVOSimulator2D::setAgentRadius(size_t agentNo, float radius)
{
agents_[agentNo]->radius_ = radius;
}
void RVOSimulator2D::setAgentTimeHorizon(size_t agentNo, float timeHorizon)
{
agents_[agentNo]->timeHorizon_ = timeHorizon;
}
void RVOSimulator2D::setAgentTimeHorizonObst(size_t agentNo, float timeHorizonObst)
{
agents_[agentNo]->timeHorizonObst_ = timeHorizonObst;
}
void RVOSimulator2D::setAgentVelocity(size_t agentNo, const Vector2 &velocity)
{
agents_[agentNo]->velocity_ = velocity;
}
void RVOSimulator2D::setTimeStep(float timeStep)
{
timeStep_ = timeStep;
}
}

592
thirdparty/rvo2/rvo2_2d/RVOSimulator2d.h vendored Normal file
View File

@@ -0,0 +1,592 @@
/*
* RVOSimulator2d.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO2D_RVO_SIMULATOR_H_
#define RVO2D_RVO_SIMULATOR_H_
/**
* \file RVOSimulator2d.h
* \brief Contains the RVOSimulator2D class.
*/
#include <cstddef>
#include <limits>
#include <vector>
#include "Vector2.h"
namespace RVO2D {
/**
* \brief Error value.
*
* A value equal to the largest unsigned integer that is returned in case
* of an error by functions in RVO2D::RVOSimulator2D.
*/
const size_t RVO2D_ERROR = std::numeric_limits<size_t>::max();
/**
* \brief Defines a directed line.
*/
class Line {
public:
/**
* \brief A point on the directed line.
*/
Vector2 point;
/**
* \brief The direction of the directed line.
*/
Vector2 direction;
};
class Agent2D;
class KdTree2D;
class Obstacle2D;
/**
* \brief Defines the simulation.
*
* The main class of the library that contains all simulation functionality.
*/
class RVOSimulator2D {
public:
/**
* \brief Constructs a simulator instance.
*/
RVOSimulator2D();
/**
* \brief Constructs a simulator instance and sets the default
* properties for any new agent that is added.
* \param timeStep The time step of the simulation.
* Must be positive.
* \param neighborDist The default maximum distance (center point
* to center point) to other agents a new agent
* takes into account in the navigation. The
* larger this number, the longer he running
* time of the simulation. If the number is too
* low, the simulation will not be safe. Must be
* non-negative.
* \param maxNeighbors The default maximum number of other agents a
* new agent takes into account in the
* navigation. The larger this number, the
* longer the running time of the simulation.
* If the number is too low, the simulation
* will not be safe.
* \param timeHorizon The default minimal amount of time for which
* a new agent's velocities that are computed
* by the simulation are safe with respect to
* other agents. The larger this number, the
* sooner an agent will respond to the presence
* of other agents, but the less freedom the
* agent has in choosing its velocities.
* Must be positive.
* \param timeHorizonObst The default minimal amount of time for which
* a new agent's velocities that are computed
* by the simulation are safe with respect to
* obstacles. The larger this number, the
* sooner an agent will respond to the presence
* of obstacles, but the less freedom the agent
* has in choosing its velocities.
* Must be positive.
* \param radius The default radius of a new agent.
* Must be non-negative.
* \param maxSpeed The default maximum speed of a new agent.
* Must be non-negative.
* \param velocity The default initial two-dimensional linear
* velocity of a new agent (optional).
*/
RVOSimulator2D(float timeStep, float neighborDist, size_t maxNeighbors,
float timeHorizon, float timeHorizonObst, float radius,
float maxSpeed, const Vector2 &velocity = Vector2());
/**
* \brief Destroys this simulator instance.
*/
~RVOSimulator2D();
/**
* \brief Adds a new agent with default properties to the
* simulation.
* \param position The two-dimensional starting position of
* this agent.
* \return The number of the agent, or RVO2D::RVO2D_ERROR when the agent
* defaults have not been set.
*/
size_t addAgent(const Vector2 &position);
/**
* \brief Adds a new agent to the simulation.
* \param position The two-dimensional starting position of
* this agent.
* \param neighborDist The maximum distance (center point to
* center point) to other agents this agent
* takes into account in the navigation. The
* larger this number, the longer the running
* time of the simulation. If the number is too
* low, the simulation will not be safe.
* Must be non-negative.
* \param maxNeighbors The maximum number of other agents this
* agent takes into account in the navigation.
* The larger this number, the longer the
* running time of the simulation. If the
* number is too low, the simulation will not
* be safe.
* \param timeHorizon The minimal amount of time for which this
* agent's velocities that are computed by the
* simulation are safe with respect to other
* agents. The larger this number, the sooner
* this agent will respond to the presence of
* other agents, but the less freedom this
* agent has in choosing its velocities.
* Must be positive.
* \param timeHorizonObst The minimal amount of time for which this
* agent's velocities that are computed by the
* simulation are safe with respect to
* obstacles. The larger this number, the
* sooner this agent will respond to the
* presence of obstacles, but the less freedom
* this agent has in choosing its velocities.
* Must be positive.
* \param radius The radius of this agent.
* Must be non-negative.
* \param maxSpeed The maximum speed of this agent.
* Must be non-negative.
* \param velocity The initial two-dimensional linear velocity
* of this agent (optional).
* \return The number of the agent.
*/
size_t addAgent(const Vector2 &position, float neighborDist,
size_t maxNeighbors, float timeHorizon,
float timeHorizonObst, float radius, float maxSpeed,
const Vector2 &velocity = Vector2());
/**
* \brief Adds a new obstacle to the simulation.
* \param vertices List of the vertices of the polygonal
* obstacle in counterclockwise order.
* \return The number of the first vertex of the obstacle,
* or RVO2D::RVO2D_ERROR when the number of vertices is less than two.
* \note To add a "negative" obstacle, e.g. a bounding polygon around
* the environment, the vertices should be listed in clockwise
* order.
*/
size_t addObstacle(const std::vector<Vector2> &vertices);
/**
* \brief Lets the simulator perform a simulation step and updates the
* two-dimensional position and two-dimensional velocity of
* each agent.
*/
void doStep();
/**
* \brief Returns the specified agent neighbor of the specified
* agent.
* \param agentNo The number of the agent whose agent
* neighbor is to be retrieved.
* \param neighborNo The number of the agent neighbor to be
* retrieved.
* \return The number of the neighboring agent.
*/
size_t getAgentAgentNeighbor(size_t agentNo, size_t neighborNo) const;
/**
* \brief Returns the maximum neighbor count of a specified agent.
* \param agentNo The number of the agent whose maximum
* neighbor count is to be retrieved.
* \return The present maximum neighbor count of the agent.
*/
size_t getAgentMaxNeighbors(size_t agentNo) const;
/**
* \brief Returns the maximum speed of a specified agent.
* \param agentNo The number of the agent whose maximum speed
* is to be retrieved.
* \return The present maximum speed of the agent.
*/
float getAgentMaxSpeed(size_t agentNo) const;
/**
* \brief Returns the maximum neighbor distance of a specified
* agent.
* \param agentNo The number of the agent whose maximum
* neighbor distance is to be retrieved.
* \return The present maximum neighbor distance of the agent.
*/
float getAgentNeighborDist(size_t agentNo) const;
/**
* \brief Returns the count of agent neighbors taken into account to
* compute the current velocity for the specified agent.
* \param agentNo The number of the agent whose count of agent
* neighbors is to be retrieved.
* \return The count of agent neighbors taken into account to compute
* the current velocity for the specified agent.
*/
size_t getAgentNumAgentNeighbors(size_t agentNo) const;
/**
* \brief Returns the count of obstacle neighbors taken into account
* to compute the current velocity for the specified agent.
* \param agentNo The number of the agent whose count of
* obstacle neighbors is to be retrieved.
* \return The count of obstacle neighbors taken into account to
* compute the current velocity for the specified agent.
*/
size_t getAgentNumObstacleNeighbors(size_t agentNo) const;
/**
* \brief Returns the count of ORCA constraints used to compute
* the current velocity for the specified agent.
* \param agentNo The number of the agent whose count of ORCA
* constraints is to be retrieved.
* \return The count of ORCA constraints used to compute the current
* velocity for the specified agent.
*/
size_t getAgentNumORCALines(size_t agentNo) const;
/**
* \brief Returns the specified obstacle neighbor of the specified
* agent.
* \param agentNo The number of the agent whose obstacle
* neighbor is to be retrieved.
* \param neighborNo The number of the obstacle neighbor to be
* retrieved.
* \return The number of the first vertex of the neighboring obstacle
* edge.
*/
size_t getAgentObstacleNeighbor(size_t agentNo, size_t neighborNo) const;
/**
* \brief Returns the specified ORCA constraint of the specified
* agent.
* \param agentNo The number of the agent whose ORCA
* constraint is to be retrieved.
* \param lineNo The number of the ORCA constraint to be
* retrieved.
* \return A line representing the specified ORCA constraint.
* \note The halfplane to the left of the line is the region of
* permissible velocities with respect to the specified
* ORCA constraint.
*/
const Line &getAgentORCALine(size_t agentNo, size_t lineNo) const;
/**
* \brief Returns the two-dimensional position of a specified
* agent.
* \param agentNo The number of the agent whose
* two-dimensional position is to be retrieved.
* \return The present two-dimensional position of the (center of the)
* agent.
*/
const Vector2 &getAgentPosition(size_t agentNo) const;
/**
* \brief Returns the two-dimensional preferred velocity of a
* specified agent.
* \param agentNo The number of the agent whose
* two-dimensional preferred velocity is to be
* retrieved.
* \return The present two-dimensional preferred velocity of the agent.
*/
const Vector2 &getAgentPrefVelocity(size_t agentNo) const;
/**
* \brief Returns the radius of a specified agent.
* \param agentNo The number of the agent whose radius is to
* be retrieved.
* \return The present radius of the agent.
*/
float getAgentRadius(size_t agentNo) const;
/**
* \brief Returns the time horizon of a specified agent.
* \param agentNo The number of the agent whose time horizon
* is to be retrieved.
* \return The present time horizon of the agent.
*/
float getAgentTimeHorizon(size_t agentNo) const;
/**
* \brief Returns the time horizon with respect to obstacles of a
* specified agent.
* \param agentNo The number of the agent whose time horizon
* with respect to obstacles is to be
* retrieved.
* \return The present time horizon with respect to obstacles of the
* agent.
*/
float getAgentTimeHorizonObst(size_t agentNo) const;
/**
* \brief Returns the two-dimensional linear velocity of a
* specified agent.
* \param agentNo The number of the agent whose
* two-dimensional linear velocity is to be
* retrieved.
* \return The present two-dimensional linear velocity of the agent.
*/
const Vector2 &getAgentVelocity(size_t agentNo) const;
/**
* \brief Returns the global time of the simulation.
* \return The present global time of the simulation (zero initially).
*/
float getGlobalTime() const;
/**
* \brief Returns the count of agents in the simulation.
* \return The count of agents in the simulation.
*/
size_t getNumAgents() const;
/**
* \brief Returns the count of obstacle vertices in the simulation.
* \return The count of obstacle vertices in the simulation.
*/
size_t getNumObstacleVertices() const;
/**
* \brief Returns the two-dimensional position of a specified obstacle
* vertex.
* \param vertexNo The number of the obstacle vertex to be
* retrieved.
* \return The two-dimensional position of the specified obstacle
* vertex.
*/
const Vector2 &getObstacleVertex(size_t vertexNo) const;
/**
* \brief Returns the number of the obstacle vertex succeeding the
* specified obstacle vertex in its polygon.
* \param vertexNo The number of the obstacle vertex whose
* successor is to be retrieved.
* \return The number of the obstacle vertex succeeding the specified
* obstacle vertex in its polygon.
*/
size_t getNextObstacleVertexNo(size_t vertexNo) const;
/**
* \brief Returns the number of the obstacle vertex preceding the
* specified obstacle vertex in its polygon.
* \param vertexNo The number of the obstacle vertex whose
* predecessor is to be retrieved.
* \return The number of the obstacle vertex preceding the specified
* obstacle vertex in its polygon.
*/
size_t getPrevObstacleVertexNo(size_t vertexNo) const;
/**
* \brief Returns the time step of the simulation.
* \return The present time step of the simulation.
*/
float getTimeStep() const;
/**
* \brief Processes the obstacles that have been added so that they
* are accounted for in the simulation.
* \note Obstacles added to the simulation after this function has
* been called are not accounted for in the simulation.
*/
void processObstacles();
/**
* \brief Performs a visibility query between the two specified
* points with respect to the obstacles
* \param point1 The first point of the query.
* \param point2 The second point of the query.
* \param radius The minimal distance between the line
* connecting the two points and the obstacles
* in order for the points to be mutually
* visible (optional). Must be non-negative.
* \return A boolean specifying whether the two points are mutually
* visible. Returns true when the obstacles have not been
* processed.
*/
bool queryVisibility(const Vector2 &point1, const Vector2 &point2,
float radius = 0.0f) const;
/**
* \brief Sets the default properties for any new agent that is
* added.
* \param neighborDist The default maximum distance (center point
* to center point) to other agents a new agent
* takes into account in the navigation. The
* larger this number, the longer he running
* time of the simulation. If the number is too
* low, the simulation will not be safe.
* Must be non-negative.
* \param maxNeighbors The default maximum number of other agents a
* new agent takes into account in the
* navigation. The larger this number, the
* longer the running time of the simulation.
* If the number is too low, the simulation
* will not be safe.
* \param timeHorizon The default minimal amount of time for which
* a new agent's velocities that are computed
* by the simulation are safe with respect to
* other agents. The larger this number, the
* sooner an agent will respond to the presence
* of other agents, but the less freedom the
* agent has in choosing its velocities.
* Must be positive.
* \param timeHorizonObst The default minimal amount of time for which
* a new agent's velocities that are computed
* by the simulation are safe with respect to
* obstacles. The larger this number, the
* sooner an agent will respond to the presence
* of obstacles, but the less freedom the agent
* has in choosing its velocities.
* Must be positive.
* \param radius The default radius of a new agent.
* Must be non-negative.
* \param maxSpeed The default maximum speed of a new agent.
* Must be non-negative.
* \param velocity The default initial two-dimensional linear
* velocity of a new agent (optional).
*/
void setAgentDefaults(float neighborDist, size_t maxNeighbors,
float timeHorizon, float timeHorizonObst,
float radius, float maxSpeed,
const Vector2 &velocity = Vector2());
/**
* \brief Sets the maximum neighbor count of a specified agent.
* \param agentNo The number of the agent whose maximum
* neighbor count is to be modified.
* \param maxNeighbors The replacement maximum neighbor count.
*/
void setAgentMaxNeighbors(size_t agentNo, size_t maxNeighbors);
/**
* \brief Sets the maximum speed of a specified agent.
* \param agentNo The number of the agent whose maximum speed
* is to be modified.
* \param maxSpeed The replacement maximum speed. Must be
* non-negative.
*/
void setAgentMaxSpeed(size_t agentNo, float maxSpeed);
/**
* \brief Sets the maximum neighbor distance of a specified agent.
* \param agentNo The number of the agent whose maximum
* neighbor distance is to be modified.
* \param neighborDist The replacement maximum neighbor distance.
* Must be non-negative.
*/
void setAgentNeighborDist(size_t agentNo, float neighborDist);
/**
* \brief Sets the two-dimensional position of a specified agent.
* \param agentNo The number of the agent whose
* two-dimensional position is to be modified.
* \param position The replacement of the two-dimensional
* position.
*/
void setAgentPosition(size_t agentNo, const Vector2 &position);
/**
* \brief Sets the two-dimensional preferred velocity of a
* specified agent.
* \param agentNo The number of the agent whose
* two-dimensional preferred velocity is to be
* modified.
* \param prefVelocity The replacement of the two-dimensional
* preferred velocity.
*/
void setAgentPrefVelocity(size_t agentNo, const Vector2 &prefVelocity);
/**
* \brief Sets the radius of a specified agent.
* \param agentNo The number of the agent whose radius is to
* be modified.
* \param radius The replacement radius.
* Must be non-negative.
*/
void setAgentRadius(size_t agentNo, float radius);
/**
* \brief Sets the time horizon of a specified agent with respect
* to other agents.
* \param agentNo The number of the agent whose time horizon
* is to be modified.
* \param timeHorizon The replacement time horizon with respect
* to other agents. Must be positive.
*/
void setAgentTimeHorizon(size_t agentNo, float timeHorizon);
/**
* \brief Sets the time horizon of a specified agent with respect
* to obstacles.
* \param agentNo The number of the agent whose time horizon
* with respect to obstacles is to be modified.
* \param timeHorizonObst The replacement time horizon with respect to
* obstacles. Must be positive.
*/
void setAgentTimeHorizonObst(size_t agentNo, float timeHorizonObst);
/**
* \brief Sets the two-dimensional linear velocity of a specified
* agent.
* \param agentNo The number of the agent whose
* two-dimensional linear velocity is to be
* modified.
* \param velocity The replacement two-dimensional linear
* velocity.
*/
void setAgentVelocity(size_t agentNo, const Vector2 &velocity);
/**
* \brief Sets the time step of the simulation.
* \param timeStep The time step of the simulation.
* Must be positive.
*/
void setTimeStep(float timeStep);
public:
std::vector<Agent2D *> agents_;
Agent2D *defaultAgent_;
float globalTime_;
KdTree2D *kdTree_;
std::vector<Obstacle2D *> obstacles_;
float timeStep_;
friend class Agent2D;
friend class KdTree2D;
friend class Obstacle2D;
};
}
#endif /* RVO2D_RVO_SIMULATOR_H_ */

346
thirdparty/rvo2/rvo2_2d/Vector2.h vendored Normal file
View File

@@ -0,0 +1,346 @@
/*
* Vector2.h
* RVO2 Library
*
* Copyright 2008 University of North Carolina at Chapel Hill
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Please send all bug reports to <geom@cs.unc.edu>.
*
* The authors may be contacted via:
*
* Jur van den Berg, Stephen J. Guy, Jamie Snape, Ming C. Lin, Dinesh Manocha
* Dept. of Computer Science
* 201 S. Columbia St.
* Frederick P. Brooks, Jr. Computer Science Bldg.
* Chapel Hill, N.C. 27599-3175
* United States of America
*
* <http://gamma.cs.unc.edu/RVO2/>
*/
#ifndef RVO_VECTOR2_H_
#define RVO_VECTOR2_H_
/**
* \file Vector2.h
* \brief Contains the Vector2 class.
*/
#include <cmath>
#include <ostream>
namespace RVO2D {
/**
* \brief Defines a two-dimensional vector.
*/
class Vector2 {
public:
/**
* \brief Constructs and initializes a two-dimensional vector instance
* to (0.0, 0.0).
*/
inline Vector2() : x_(0.0f), y_(0.0f) { }
/**
* \brief Constructs and initializes a two-dimensional vector from
* the specified xy-coordinates.
* \param x The x-coordinate of the two-dimensional
* vector.
* \param y The y-coordinate of the two-dimensional
* vector.
*/
inline Vector2(float x, float y) : x_(x), y_(y) { }
inline Vector2(const Vector2 &vector)
{
x_ = vector.x();
y_ = vector.y();
}
/**
* \brief Returns the x-coordinate of this two-dimensional vector.
* \return The x-coordinate of the two-dimensional vector.
*/
inline float x() const { return x_; }
/**
* \brief Returns the y-coordinate of this two-dimensional vector.
* \return The y-coordinate of the two-dimensional vector.
*/
inline float y() const { return y_; }
/**
* \brief Computes the negation of this two-dimensional vector.
* \return The negation of this two-dimensional vector.
*/
inline Vector2 operator-() const
{
return Vector2(-x_, -y_);
}
/**
* \brief Computes the dot product of this two-dimensional vector with
* the specified two-dimensional vector.
* \param vector The two-dimensional vector with which the
* dot product should be computed.
* \return The dot product of this two-dimensional vector with a
* specified two-dimensional vector.
*/
inline float operator*(const Vector2 &vector) const
{
return x_ * vector.x() + y_ * vector.y();
}
/**
* \brief Computes the scalar multiplication of this
* two-dimensional vector with the specified scalar value.
* \param s The scalar value with which the scalar
* multiplication should be computed.
* \return The scalar multiplication of this two-dimensional vector
* with a specified scalar value.
*/
inline Vector2 operator*(float s) const
{
return Vector2(x_ * s, y_ * s);
}
/**
* \brief Computes the scalar division of this two-dimensional vector
* with the specified scalar value.
* \param s The scalar value with which the scalar
* division should be computed.
* \return The scalar division of this two-dimensional vector with a
* specified scalar value.
*/
inline Vector2 operator/(float s) const
{
const float invS = 1.0f / s;
return Vector2(x_ * invS, y_ * invS);
}
/**
* \brief Computes the vector sum of this two-dimensional vector with
* the specified two-dimensional vector.
* \param vector The two-dimensional vector with which the
* vector sum should be computed.
* \return The vector sum of this two-dimensional vector with a
* specified two-dimensional vector.
*/
inline Vector2 operator+(const Vector2 &vector) const
{
return Vector2(x_ + vector.x(), y_ + vector.y());
}
/**
* \brief Computes the vector difference of this two-dimensional
* vector with the specified two-dimensional vector.
* \param vector The two-dimensional vector with which the
* vector difference should be computed.
* \return The vector difference of this two-dimensional vector with a
* specified two-dimensional vector.
*/
inline Vector2 operator-(const Vector2 &vector) const
{
return Vector2(x_ - vector.x(), y_ - vector.y());
}
/**
* \brief Tests this two-dimensional vector for equality with the
* specified two-dimensional vector.
* \param vector The two-dimensional vector with which to
* test for equality.
* \return True if the two-dimensional vectors are equal.
*/
inline bool operator==(const Vector2 &vector) const
{
return x_ == vector.x() && y_ == vector.y();
}
/**
* \brief Tests this two-dimensional vector for inequality with the
* specified two-dimensional vector.
* \param vector The two-dimensional vector with which to
* test for inequality.
* \return True if the two-dimensional vectors are not equal.
*/
inline bool operator!=(const Vector2 &vector) const
{
return x_ != vector.x() || y_ != vector.y();
}
/**
* \brief Sets the value of this two-dimensional vector to the scalar
* multiplication of itself with the specified scalar value.
* \param s The scalar value with which the scalar
* multiplication should be computed.
* \return A reference to this two-dimensional vector.
*/
inline Vector2 &operator*=(float s)
{
x_ *= s;
y_ *= s;
return *this;
}
/**
* \brief Sets the value of this two-dimensional vector to the scalar
* division of itself with the specified scalar value.
* \param s The scalar value with which the scalar
* division should be computed.
* \return A reference to this two-dimensional vector.
*/
inline Vector2 &operator/=(float s)
{
const float invS = 1.0f / s;
x_ *= invS;
y_ *= invS;
return *this;
}
/**
* \brief Sets the value of this two-dimensional vector to the vector
* sum of itself with the specified two-dimensional vector.
* \param vector The two-dimensional vector with which the
* vector sum should be computed.
* \return A reference to this two-dimensional vector.
*/
inline Vector2 &operator+=(const Vector2 &vector)
{
x_ += vector.x();
y_ += vector.y();
return *this;
}
/**
* \brief Sets the value of this two-dimensional vector to the vector
* difference of itself with the specified two-dimensional
* vector.
* \param vector The two-dimensional vector with which the
* vector difference should be computed.
* \return A reference to this two-dimensional vector.
*/
inline Vector2 &operator-=(const Vector2 &vector)
{
x_ -= vector.x();
y_ -= vector.y();
return *this;
}
inline Vector2 &operator=(const Vector2 &vector)
{
x_ = vector.x();
y_ = vector.y();
return *this;
}
private:
float x_;
float y_;
};
/**
* \relates Vector2
* \brief Computes the scalar multiplication of the specified
* two-dimensional vector with the specified scalar value.
* \param s The scalar value with which the scalar
* multiplication should be computed.
* \param vector The two-dimensional vector with which the scalar
* multiplication should be computed.
* \return The scalar multiplication of the two-dimensional vector with the
* scalar value.
*/
inline Vector2 operator*(float s, const Vector2 &vector)
{
return Vector2(s * vector.x(), s * vector.y());
}
/**
* \relates Vector2
* \brief Inserts the specified two-dimensional vector into the specified
* output stream.
* \param os The output stream into which the two-dimensional
* vector should be inserted.
* \param vector The two-dimensional vector which to insert into
* the output stream.
* \return A reference to the output stream.
*/
inline std::ostream &operator<<(std::ostream &os, const Vector2 &vector)
{
os << "(" << vector.x() << "," << vector.y() << ")";
return os;
}
/**
* \relates Vector2
* \brief Computes the length of a specified two-dimensional vector.
* \param vector The two-dimensional vector whose length is to be
* computed.
* \return The length of the two-dimensional vector.
*/
inline float abs(const Vector2 &vector)
{
return std::sqrt(vector * vector);
}
/**
* \relates Vector2
* \brief Computes the squared length of a specified two-dimensional
* vector.
* \param vector The two-dimensional vector whose squared length
* is to be computed.
* \return The squared length of the two-dimensional vector.
*/
inline float absSq(const Vector2 &vector)
{
return vector * vector;
}
/**
* \relates Vector2
* \brief Computes the determinant of a two-dimensional square matrix with
* rows consisting of the specified two-dimensional vectors.
* \param vector1 The top row of the two-dimensional square
* matrix.
* \param vector2 The bottom row of the two-dimensional square
* matrix.
* \return The determinant of the two-dimensional square matrix.
*/
inline float det(const Vector2 &vector1, const Vector2 &vector2)
{
return vector1.x() * vector2.y() - vector1.y() * vector2.x();
}
/**
* \relates Vector2
* \brief Computes the normalization of the specified two-dimensional
* vector.
* \param vector The two-dimensional vector whose normalization
* is to be computed.
* \return The normalization of the two-dimensional vector.
*/
inline Vector2 normalize(const Vector2 &vector)
{
return vector / abs(vector);
}
}
#endif /* RVO_VECTOR2_H_ */