1
0
forked from mirrors/0ad

Consider that the point could be inside the goal area in some PathGoal functions

Reviewed By: wraitii
Comments By: mimo
Differential Revision: https://code.wildfiregames.com/D1089
This was SVN commit r20878.
This commit is contained in:
temple
2018-01-16 02:15:04 +00:00
parent 033489480a
commit 7d172a9b1d
3 changed files with 91 additions and 15 deletions
@@ -1,4 +1,4 @@
/* Copyright (C) 2017 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -64,6 +64,53 @@ public:
TS_ASSERT_EQUALS((Pathfinding::NAVCELL_SIZE >> 1).ToInt_RoundToZero(), Pathfinding::NAVCELL_SIZE_LOG2);
}
void test_pathgoal()
{
entity_pos_t i = Pathfinding::NAVCELL_SIZE;
CFixedVector2D u(i*1, i*0);
CFixedVector2D v(i*0, i*1);
{
PathGoal goal = { PathGoal::POINT, i*8, i*6 };
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*8 + v*4), u*8 + v*6);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*8 + v*4), i*2);
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*0 + v*0), u*8 + v*6);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*0 + v*0), i*10);
}
{
PathGoal goal = { PathGoal::CIRCLE, i*8, i*6, i*5 };
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*8 + v*4), u*8 + v*4);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*8 + v*4), i*0);
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*0 + v*0), u*4 + v*3);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*0 + v*0), i*5);
}
{
PathGoal goal = { PathGoal::INVERTED_CIRCLE, i*8, i*6, i*5 };
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*8 + v*4), u*8 + v*1);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*8 + v*4), i*3);
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*0 + v*0), u*0 + v*0);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*0 + v*0), i*0);
}
{
PathGoal goal = { PathGoal::SQUARE, i*8, i*6, i*4, i*3, u, v };
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*8 + v*4), u*8 + v*4);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*8 + v*4), i*0);
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*0 + v*0), u*4 + v*3);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*0 + v*0), i*5);
}
{
PathGoal goal = { PathGoal::INVERTED_SQUARE, i*8, i*6, i*4, i*3, u, v };
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*8 + v*4), u*8 + v*3);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*8 + v*4), i*1);
TS_ASSERT_EQUALS(goal.NearestPointOnGoal(u*0 + v*0), u*0 + v*0);
TS_ASSERT_EQUALS(goal.DistanceToPoint(u*0 + v*0), i*0);
}
}
void test_performance_DISABLED()
{
CTerrain terrain;
+38 -8
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -293,21 +293,31 @@ bool PathGoal::RectContainsGoal(entity_pos_t x0, entity_pos_t z0, entity_pos_t x
fixed PathGoal::DistanceToPoint(CFixedVector2D pos) const
{
CFixedVector2D d(pos.X - x, pos.Y - z);
switch (type)
{
case POINT:
return (pos - CFixedVector2D(x, z)).Length();
return d.Length();
case CIRCLE:
return d.CompareLength(hw) <= 0 ? fixed::Zero() : d.Length() - hw;
case INVERTED_CIRCLE:
return ((pos - CFixedVector2D(x, z)).Length() - hw).Absolute();
return d.CompareLength(hw) >= 0 ? fixed::Zero() : hw - d.Length();
case SQUARE:
{
CFixedVector2D halfSize(hw, hh);
return Geometry::PointIsInSquare(d, u, v, halfSize) ?
fixed::Zero() : Geometry::DistanceToSquare(d, u, v, halfSize);
}
case INVERTED_SQUARE:
{
CFixedVector2D halfSize(hw, hh);
CFixedVector2D d(pos.X - x, pos.Y - z);
return Geometry::DistanceToSquare(d, u, v, halfSize);
return !Geometry::PointIsInSquare(d, u, v, halfSize) ?
fixed::Zero() : Geometry::DistanceToSquare(d, u, v, halfSize);
}
NODEFAULT;
@@ -324,9 +334,21 @@ CFixedVector2D PathGoal::NearestPointOnGoal(CFixedVector2D pos) const
return g;
case CIRCLE:
{
CFixedVector2D d(pos.X - x, pos.Y - z);
if (d.CompareLength(hw) <= 0)
return pos;
d.Normalize(hw);
return g + d;
}
case INVERTED_CIRCLE:
{
CFixedVector2D d = pos - g;
CFixedVector2D d(pos.X - x, pos.Y - z);
if (d.CompareLength(hw) >= 0)
return pos;
if (d.IsZero())
d = CFixedVector2D(fixed::FromInt(1), fixed::Zero()); // some arbitrary direction
d.Normalize(hw);
@@ -334,11 +356,19 @@ CFixedVector2D PathGoal::NearestPointOnGoal(CFixedVector2D pos) const
}
case SQUARE:
{
CFixedVector2D halfSize(hw, hh);
CFixedVector2D d(pos.X - x, pos.Y - z);
return Geometry::PointIsInSquare(d, u, v, halfSize) ?
pos : g + Geometry::NearestPointOnSquare(d, u, v, halfSize);
}
case INVERTED_SQUARE:
{
CFixedVector2D halfSize(hw, hh);
CFixedVector2D d = pos - g;
return g + Geometry::NearestPointOnSquare(d, u, v, halfSize);
CFixedVector2D d(pos.X - x, pos.Y - z);
return !Geometry::PointIsInSquare(d, u, v, halfSize) ?
pos : g + Geometry::NearestPointOnSquare(d, u, v, halfSize);
}
NODEFAULT;
+5 -6
View File
@@ -1,4 +1,4 @@
/* Copyright (C) 2015 Wildfire Games.
/* Copyright (C) 2018 Wildfire Games.
* This file is part of 0 A.D.
*
* 0 A.D. is free software: you can redistribute it and/or modify
@@ -42,10 +42,10 @@ public:
entity_pos_t x, z; // position of center
CFixedVector2D u, v; // if [INVERTED_]SQUARE, then orthogonal unit axes
entity_pos_t hw, hh; // if [INVERTED_]SQUARE, then half width & height; if [INVERTED_]CIRCLE, then hw is radius
CFixedVector2D u, v; // if [INVERTED_]SQUARE, then orthogonal unit axes
entity_pos_t maxdist; // maximum distance wanted between two path waypoints
/**
@@ -70,13 +70,12 @@ public:
bool RectContainsGoal(entity_pos_t x0, entity_pos_t z0, entity_pos_t x1, entity_pos_t z1) const;
/**
* Returns the minimum distance from the point with the given @p pos
* to any point on the outline of the goal shape.
* Returns the minimum distance from the point pos to any point on the goal shape.
*/
fixed DistanceToPoint(CFixedVector2D pos) const;
/**
* Returns the coordinates of the point on the goal that is closest to pos in a straight line.
* Returns the coordinates of the point on the goal that is closest to the point pos.
*/
CFixedVector2D NearestPointOnGoal(CFixedVector2D pos) const;
};