Skip to content

Commit

Permalink
path: Portals between fields.
Browse files Browse the repository at this point in the history
  • Loading branch information
heinezen committed Mar 17, 2024
1 parent a9f6851 commit 9981a7a
Show file tree
Hide file tree
Showing 3 changed files with 301 additions and 0 deletions.
1 change: 1 addition & 0 deletions libopenage/pathfinding/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ add_sources(libopenage
integration_field.cpp
integrator.cpp
path.cpp
portal.cpp
tests.cpp
types.cpp
)
Expand Down
104 changes: 104 additions & 0 deletions libopenage/pathfinding/portal.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
// Copyright 2024-2024 the openage authors. See copying.md for legal info.

#include "portal.h"

#include "error/error.h"


namespace openage::path {

Portal::Portal(std::shared_ptr<CostField> sector0,
std::shared_ptr<CostField> sector1,
std::vector<std::shared_ptr<Portal>> sector0_exits,
std::vector<std::shared_ptr<Portal>> sector1_exits,
PortalDirection direction,
size_t cell_start_x,
size_t cell_start_y,
size_t cell_end_x,
size_t cell_end_y) :
sector0{sector0},
sector1{sector1},
sector0_exits{sector0_exits},
sector1_exits{sector1_exits},
direction{direction},
cell_start_x{cell_start_x},
cell_start_y{cell_start_y},
cell_end_x{cell_end_x},
cell_end_y{cell_end_y} {
}

const std::vector<std::shared_ptr<Portal>> &Portal::get_exits(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->sector1_exits;
}
return this->sector0_exits;
}

const std::shared_ptr<CostField> &Portal::get_exit_sector(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->sector1;
}
return this->sector0;
}

std::pair<size_t, size_t> Portal::get_entry_start(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->get_sector0_start();
}

return this->get_sector1_start();
}

std::pair<size_t, size_t> Portal::get_entry_end(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->get_sector0_end();
}

return this->get_sector1_end();
}

std::pair<size_t, size_t> Portal::get_exit_start(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->get_sector1_start();
}

return this->get_sector0_start();
}

std::pair<size_t, size_t> Portal::get_exit_end(const std::shared_ptr<CostField> &entry_sector) const {
ENSURE(entry_sector == this->sector0 || entry_sector == this->sector1, "Invalid entry sector");

if (entry_sector == this->sector0) {
return this->get_sector1_end();
}

return this->get_sector0_end();
}

std::pair<size_t, size_t> Portal::get_sector0_start() const {
return {this->cell_start_x, this->cell_start_y};
}

std::pair<size_t, size_t> Portal::get_sector0_end() const {
return {this->cell_end_x, this->cell_end_y};
}

std::pair<size_t, size_t> Portal::get_sector1_start() const {
return {this->cell_end_x, this->cell_end_y};
}

std::pair<size_t, size_t> Portal::get_sector1_end() const {
return {this->cell_start_x, this->cell_start_y};
}

} // namespace openage::path
196 changes: 196 additions & 0 deletions libopenage/pathfinding/portal.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
// Copyright 2024-2024 the openage authors. See copying.md for legal info.

#pragma once


#include <memory>

#include "pathfinding/cost_field.h"


namespace openage::path {
class CostField;

/**
* Possible directions of a portal node.
*/
enum class PortalDirection {
NORTH_SOUTH,
EAST_WEST
};

/**
* Biderectional gateway for connecting two sectors in the flow field pathfinder.
*
* Portals are located at the border of two sectors (0 and 1), and allow units to move between them.
* For each of these sectors, the portal stores the start and end coordinates where the
* sectors overlap as well as the other portals that can be reached in the same
* sector. For simplicity, the portal is assumed to be a straight line of cells from the start
* to the end.
*
* The portal is bidirectional, meaning that it can be entered from either sector and
* exited into the other sector. The direction of the portal from one sector to the other
* is stored in the portal node. As a convention and to simplify computations, sector 0 must be
* the either the north or east sector on the grid in relation to sector 1.
*/
class Portal {
public:
/**
* Create a new portal between two sectors.
*
* As a convention, sector 0 must be the either the north or east sector
* on the grid in relation to sector 1.
*
* @param sector0 First sector connected by the portal.
* Must be north or east on the grid in relation to sector 1.
* @param sector1 Second sector connected by the portal.
* Must be south or west on the grid in relation to sector 0.
* @param sector0_exits Portals reachable from this portal in sector 0.
* @param sector1_exits Portals reachable from this portal in sector 1.
* @param direction Direction of the portal from sector 0 to sector 1.
* @param cell_start_x Start cell x coordinate in sector 0.
* @param cell_start_y Start cell y coordinate in sector 0.
* @param cell_end_x End cell x coordinate in sector 0.
* @param cell_end_y End cell y coordinate in sector 0.
*/
Portal(std::shared_ptr<CostField> sector0,
std::shared_ptr<CostField> sector1,
std::vector<std::shared_ptr<Portal>> sector0_exits,
std::vector<std::shared_ptr<Portal>> sector1_exits,
PortalDirection direction,
size_t cell_start_x,
size_t cell_start_y,
size_t cell_end_x,
size_t cell_end_y);

~Portal() = default;

/**
* Get the exit portals reachable via the portal when entering from a specified sector.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Exit portals reachable from the portal.
*/
const std::vector<std::shared_ptr<Portal>> &get_exits(const std::shared_ptr<CostField> &entry_sector) const;

/**
* Get the cost field of the sector where the portal is exited.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Cost field of the sector where the portal is exited.
*/
const std::shared_ptr<CostField> &get_exit_sector(const std::shared_ptr<CostField> &entry_sector) const;

/**
* Get the cost field of the sector from which the portal is entered.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Cost field of the sector from which the portal is entered.
*/
std::pair<size_t, size_t> get_entry_start(const std::shared_ptr<CostField> &entry_sector) const;

/**
* Get the cell coordinates of the start of the portal in the entry sector.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Cell coordinates of the start of the portal in the entry sector.
*/
std::pair<size_t, size_t> get_entry_end(const std::shared_ptr<CostField> &entry_sector) const;

/**
* Get the cell coordinates of the start of the portal in the exit sector.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Cell coordinates of the start of the portal in the exit sector.
*/
std::pair<size_t, size_t> get_exit_start(const std::shared_ptr<CostField> &entry_sector) const;

/**
* Get the cell coordinates of the end of the portal in the exit sector.
*
* @param entry_sector Sector from which the portal is entered.
*
* @return Cell coordinates of the end of the portal in the exit sector.
*/
std::pair<size_t, size_t> get_exit_end(const std::shared_ptr<CostField> &entry_sector) const;

private:
/**
* Get the start cell coordinates of the portal.
*
* @return Start cell coordinates of the portal.
*/
std::pair<size_t, size_t> get_sector0_start() const;

/**
* Get the end cell coordinates of the portal.
*
* @return End cell coordinates of the portal.
*/
std::pair<size_t, size_t> get_sector0_end() const;

/**
* Get the start cell coordinates of the portal.
*
* @return Start cell coordinates of the portal.
*/
std::pair<size_t, size_t> get_sector1_start() const;

/**
* Get the end cell coordinates of the portal.
*
* @return End cell coordinates of the portal.
*/
std::pair<size_t, size_t> get_sector1_end() const;

/**
* Sector 0
*/
std::shared_ptr<CostField> sector0;

/**
* Sector 1
*/
std::shared_ptr<CostField> sector1;

/**
* Exits from sector 0
*/
std::vector<std::shared_ptr<Portal>> sector0_exits;

/**
* Exits from sector 1
*/
std::vector<std::shared_ptr<Portal>> sector1_exits;

/**
* Direction of the portal
*/
PortalDirection direction;

/**
* Start cell x coordinate
*/
size_t cell_start_x;

/**
* Start cell y coordinate
*/
size_t cell_start_y;

/**
* End cell x coordinate
*/
size_t cell_end_x;

/**
* End cell y coordinate
*/
size_t cell_end_y;
};
} // namespace openage::path

0 comments on commit 9981a7a

Please sign in to comment.