Skip to content

Commit

Permalink
Refactored maze
Browse files Browse the repository at this point in the history
  • Loading branch information
gregjesl committed Feb 5, 2023
1 parent f03607c commit b166823
Show file tree
Hide file tree
Showing 5 changed files with 23 additions and 253 deletions.
2 changes: 1 addition & 1 deletion inc/glnav_dijkstra.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ namespace glnav
dijkstra(const maze<T, Q> &input)
: version_dependent(input),
__maze(input),
__map(input.seed_map())
__map(input)
{
this->__to_go.insert(input.finish());
this->__map.set(this->__maze.finish(), 0);
Expand Down
176 changes: 6 additions & 170 deletions inc/glnav_maze.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,190 +12,26 @@ namespace glnav
* The maze class is designed such multiple mazes can share one common network
*/
template<typename T, typename Q>
class maze : public version_dependent
class maze : public network<T, Q>
{
public:
maze(const network<T, Q> &net,
const point<T> &start,
maze(const point<T> &start,
const point<T> &finish)
: version_dependent(net),
__net(net),
: network<T, Q>(),
__start(start),
__finish(finish)
{
if(!net.contains(start)) throw unknown_point_exception<T>(start);
if(!net.contains(finish)) throw unknown_point_exception<T>(finish);
this->__attach_ramps();
this->__verify_resync();
}

maze(const network<T, Q> &net,
const point<T> &start,
const point<T> &finish,
const cost_map<T, Q> &onramp,
const cost_map<T, Q> &offramp)
: version_dependent(net),
__net(net),
__start(start),
__finish(finish),
__onramp(onramp),
__offramp(offramp)
{
this->__attach_ramps();
this->__verify_resync();
}

maze(const maze<T, Q> &other)
: version_dependent(other),
__net(other.__net),
__start(other.__start),
__finish(other.__finish),
__onramp(other.__onramp),
__offramp(other.__offramp)
{
this->force_synchronization();
assert(this->__onramp.is_attached());
assert(this->__offramp.is_attached());
assert(this->__line_of_sight || this->__onramp.overlap(this->__net).size() > 0);
assert(this->__line_of_sight || this->__offramp.overlap(this->__net).size() > 0);
}
{ }

virtual ~maze()
{

}

const network<T, Q> & network() const { return this->__net; }

bool is_synchronized() const
{
return this->versions_synchronized(this->__net)
&& this->versions_synchronized(this->__onramp)
&& this->versions_synchronized(this->__offramp);
}

void update()
{
this->__onramp.detatch();
this->__offramp.detatch();
this->synchronize_version(this->__net);
this->__attach_ramps();
this->__verify_resync();
}

void update(const cost_map<T, Q> &onramp, const cost_map<T, Q> &offramp)
{
this->__onramp = onramp;
this->__offramp = offramp;
this->__attach_ramps();
if(!this->__net.versions_synchronized(this->__onramp)) throw version_mismatch(this->__net, this->__onramp);
if(!this->__net.versions_synchronized(this->__offramp)) throw version_mismatch(this->__net, this->__offramp);
this->set_version(this->__net.version());
assert(this->is_synchronized());
}

void update(const point<T> &start, const point<T> &finish, const cost_map<T, Q> &onramp, const cost_map<T, Q> &offramp)
{
this->__start = start;
this->__finish = finish;
this->update(onramp, offramp);
this->__verify_resync();
}

neighborhood<T, Q> neighbors(const point<T> &from) const
{
this->__force_synchronization();

if(from == this->__start)
{
if(this->__onramp.size() > 0)
{
assert(!this->__net.contains(from));
return this->__onramp.as_neighborhood();
}
assert(this->__net.contains(from));
return this->__net.neighbors(from);
}

if(from == this->__finish)
{
if(this->__offramp.size() > 0)
{
assert(!this->__net.contains(from));
return this->__offramp.as_neighborhood();
}
assert(this->__net.contains(from));
return this->__net.neighbors(from);
}

if(!this->__net.contains(from)) throw unknown_point_exception<T>(from);

neighborhood<T, Q> result = this->__net.neighbors(from);

if(this->__onramp.contains(from))
{
result.push_back(neighbor<T, Q>(this->__start, this->__onramp.cost(from)));
}

if(this->__offramp.contains(from))
{
result.push_back(neighbor<T, Q>(this->__finish, this->__offramp.cost(from)));
}

return result;
}

cost_map<T, Q> seed_map() const
{
this->__force_synchronization();
cost_map<T, Q> result(this->__net);
if(!this->__onramp.empty())
{
assert(!this->__net.contains(this->__start));
result.set(this->__start, std::numeric_limits<Q>::infinity());
}
if(!this->__offramp.empty())
{
assert(!this->__net.contains(this->__finish));
result.set(this->__finish, std::numeric_limits<Q>::infinity());
}
return result;
}
{ }

const point<T> & start() const { return this->__start; }
const point<T> & finish() const { return this->__finish; }
bool is_valid() const { return this->contains(this->__start) && this->contains(this->__finish); }

private:
const glnav::network<T, Q> &__net;
point<T> __start;
point<T> __finish;
cost_map<T, Q> __onramp;
cost_map<T, Q> __offramp;

void __verify_resync()
{
if(this->__net.contains(this->__start) && this->__onramp.size() > 0) throw std::runtime_error("Starting point on network");
if(this->__net.contains(this->__finish) && this->__offramp.size() > 0) throw std::runtime_error("Ending point on network");
this->__force_synchronization();
if(this->__onramp.overlap(this->__net).size() == 0 && !this->__net.contains(this->__start)) throw std::runtime_error("Onramp does not connect to network");
if(this->__offramp.overlap(this->__net).size() == 0 && !this->__net.contains(this->__finish)) throw std::runtime_error("Offramp does not connect to network");
}

void __attach_ramps()
{
if(!this->__onramp.is_attached())
this->__onramp.attach(this->__net);
if(!this->__offramp.is_attached())
this->__offramp.attach(this->__net);
}

void __force_synchronization() const
{
if(this->version() != this->__net.version()) throw version_mismatch(this->version(), this->__net.version());
if(this->version() != this->__onramp.version()) throw version_mismatch(this->version(), this->__onramp.version());
if(this->version() != this->__offramp.version()) throw version_mismatch(this->version(), this->__offramp.version());
assert(this->is_synchronized());
}
};
}

Expand Down
41 changes: 7 additions & 34 deletions inc/glnav_obstacle.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,12 @@
namespace glnav
{
template<typename T>
class obstacle : virtual public obstacle_interface<T>
class obstacle : public cartesian_area<T>, virtual public obstacle_interface<T>
{
public:
obstacle(const std::vector<point<T> > &outline)
: __corners(outline),
__minX(outline.front().x),
__minY(outline.front().y),
__maxX(outline.front().x),
__maxY(outline.front().y)
: cartesian_area<T>(outline.front()),
__corners(outline)
{
if(outline.size() < 3) throw std::invalid_argument("Insufficent points");
if(point_group<T>(outline).size() < outline.size()) throw std::invalid_argument("Duplicate points");
Expand All @@ -38,18 +35,19 @@ namespace glnav

for(size_t i = 1; i < outline.size(); i++)
{
this->__update_axis(outline.at(i).x, this->__minX, this->__maxX);
this->__update_axis(outline.at(i).y, this->__minY, this->__maxY);
this->expand(outline.at(i));
}
}

obstacle(const obstacle &other)
: __corners(other.__corners),
: cartesian_area<T>(other),
__corners(other.__corners),
__clockwise(other.__clockwise)
{ }

obstacle& operator=(const obstacle &other)
{
cartesian_area<T>::operator=(other);
this->__corners = other.__corners;
this->__clockwise = other.__clockwise;
return this;
Expand Down Expand Up @@ -124,11 +122,6 @@ namespace glnav
return result;
}

virtual T minX() const { return this->__minX; }
virtual T maxX() const { return this->__maxX; }
virtual T minY() const { return this->__minY; }
virtual T maxY() const { return this->__maxY; }

std::string svg() const
{
std::string result = "<polygon points=\"";
Expand All @@ -146,10 +139,6 @@ namespace glnav
private:
std::vector<point<T> > __corners;
bool __clockwise;
T __minX;
T __minY;
T __maxX;
T __maxY;

bool __corner_obstructs(const path<T> &input, const size_t index) const
{
Expand Down Expand Up @@ -192,22 +181,6 @@ namespace glnav
}
return false;
}

void __update_min(const T input, T &value)
{
if(input < value) value = input;
}

void __update_max(const T input, T &value)
{
if(input > value) value = input;
}

void __update_axis(const T value, T &min, T &max)
{
this->__update_min(value, min);
this->__update_max(value, max);
}
};
}

Expand Down
5 changes: 2 additions & 3 deletions test/dijkstra.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,13 @@

int main(void)
{
glnav::network<double, double> net;
const glnav::point<double> point1(0, -2);
const glnav::point<double> point2(0, 1);
const glnav::point<double> point3(2, -3);
const glnav::point<double> point4(2, 2);
const glnav::point<double> start(-2, 0);
const glnav::point<double> finish(4, 0);
glnav::maze<double, double> net(start, finish);
glnav::path<double> lower(point1, point3);
glnav::path<double> upper(point2, point4);
glnav::path<double> start1(start, point1);
Expand All @@ -23,8 +23,7 @@ int main(void)
net.add(finish1, start1.length<double>());
net.add(finish2, start2.length<double>());

glnav::maze<double, double> _maze(net, start, finish);
glnav::dijkstra<double, double> test(_maze);
glnav::dijkstra<double, double> test(net);
TEST_FALSE(test.is_solved());

const size_t max_iterations = 100;
Expand Down
52 changes: 7 additions & 45 deletions test/maze.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -10,49 +10,11 @@ int main(void)
glnav::point<int>(2, 5),
glnav::point<int>(2, 1)
};
glnav::network<int, int> net;
net.add(glnav::path<int>(corners[0], corners[1]), 1);
net.add(glnav::path<int>(corners[1], corners[2]), 1);
net.add(glnav::path<int>(corners[2], corners[3]), 1);
net.add(glnav::path<int>(corners[3], corners[0]), 1);

// Build a maze with start and end on the network
glnav::maze<int, int> test(net, corners[0], corners[2]);
TEST_EQUAL(test.neighbors(corners[0]).size(), 2);
TEST_TRUE(test.neighbors(corners[0]).contains(corners[1]));
TEST_TRUE(test.neighbors(corners[0]).contains(corners[3]));
TEST_EQUAL(test.neighbors(corners[2]).size(), 2);
TEST_TRUE(test.neighbors(corners[2]).contains(corners[1]));
TEST_TRUE(test.neighbors(corners[2]).contains(corners[3]));
TEST_TRUE(test.is_synchronized());

// Update the network
const glnav::point<int> ur(3, 5);
const glnav::point<int> lr(3, 1);
net.add(glnav::path<int>(corners[2], ur), 1);
net.add(glnav::path<int>(corners[3], lr), 1);
TEST_FALSE(test.is_synchronized());
test.update();
TEST_TRUE(test.is_synchronized());

// Build a maze with points starting off of the network
const glnav::point<int> start(-4, 0);
glnav::cost_map<int, int> onramp;
onramp.set(corners[0], 2);
onramp.set(corners[1], 2);
const glnav::point<int> finish(4, 0);
glnav::cost_map<int, int> offramp;
offramp.set(ur, 2);
offramp.set(lr, 2);
test.update(start, finish, onramp, offramp);
TEST_EQUAL(test.neighbors(start).size(), 2);
TEST_TRUE(test.neighbors(start).contains(corners[0]));
TEST_TRUE(test.neighbors(start).contains(corners[1]));
TEST_EQUAL(test.neighbors(finish).size(), 2);
TEST_TRUE(test.neighbors(finish).contains(ur));
TEST_TRUE(test.neighbors(finish).contains(lr));
TEST_EQUAL(test.neighbors(corners[0]).size(), 3);
TEST_TRUE(test.neighbors(corners[0]).contains(start));
TEST_EQUAL(test.neighbors(lr).size(), 2);
TEST_TRUE(test.neighbors(lr).contains(finish));
glnav::maze<int, int> test(corners[0], corners[2]);
TEST_FALSE(test.is_valid());
test.add(glnav::path<int>(corners[0], corners[1]), 1);
test.add(glnav::path<int>(corners[1], corners[2]), 1);
test.add(glnav::path<int>(corners[2], corners[3]), 1);
test.add(glnav::path<int>(corners[3], corners[0]), 1);
TEST_TRUE(test.is_valid());
}

0 comments on commit b166823

Please sign in to comment.