Skip to content

Commit

Permalink
Merge pull request #3 from lucka-me/minor-improvements
Browse files Browse the repository at this point in the history
Minor improvements
  • Loading branch information
lucka-me authored Dec 3, 2023
2 parents c6d78f5 + be36164 commit 057162c
Show file tree
Hide file tree
Showing 9 changed files with 83 additions and 79 deletions.
6 changes: 5 additions & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@ find_package(Boost REQUIRED
)

set(CMAKE_CXX_STANDARD 20)
set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin)

include_directories(
${Boost_INCLUDE_DIR}
Expand All @@ -30,6 +29,11 @@ file(GLOB_RECURSE CXX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR}/src/*.cpp)

add_executable(${PROJECT_NAME} ${CXX_HEADERS} ${CXX_SOURCE})

set_target_properties(${PROJECT_NAME}
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/bin
)

target_link_libraries(${PROJECT_NAME}
Boost::json
Boost::program_options
Expand Down
15 changes: 10 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ An offline CLI tool to analyze reachable Portals for Ingress Drone Mark I.

Implementations in different languages are listed and compared in [Benchmark](#benchmark).

The CI workflow builds universal binary for macOS and x86_64 binaries for Windows & Linux, the files are available as artifacts.
The CI workflow builds universal binary for macOS, x86_64 and aarch64 binaries for Linux and x86_64 binary for Windows, the files are available as artifacts.

## Build from Source

Expand Down Expand Up @@ -89,21 +89,26 @@ Average exploration time consumed of 100 executions on MacBook Air (M2).
| [C++][cpp-repo] | ![][cpp-loc] | `Current` | 0.583 s
| [Node.js][nodejs-repo] | ![][nodejs-loc] | [`7ad90e9`][nodejs-benchmark-commit] | 1.295 s
| [Python][python-repo] | ![][python-loc] | [`841b9f0`][python-benchmark-commit] | 2.813 s
| [Rust][rust-repo] | ![][rust-loc] | [`cb21807`][rust-benchmark-commit] | 0.371 s
| [Swift][swift-repo] | ![][swift-loc] | [`2c73a58`][swift-benchmark-commit] | 0.722 s

The results of other implementations may be outdated, please check their repositories for latest results.

[cpp-repo]: https://github.com/lucka-me/ingress-drone-explorer-cpp
[cpp-loc]: https://img.shields.io/tokei/lines/github/lucka-me/ingress-drone-explorer-cpp
[cpp-loc]: https://aschey.tech/tokei/github/lucka-me/ingress-drone-explorer-cpp

[nodejs-repo]: https://github.com/lucka-me/ingress-drone-explorer-nodejs
[nodejs-loc]: https://img.shields.io/tokei/lines/github/lucka-me/ingress-drone-explorer-nodejs
[nodejs-loc]: https://aschey.tech/tokei/github/lucka-me/ingress-drone-explorer-nodejs
[nodejs-benchmark-commit]: https://github.com/lucka-me/ingress-drone-explorer-nodejs/commit/7ad90e9

[python-repo]: https://github.com/lucka-me/ingress-drone-explorer-python
[python-loc]: https://img.shields.io/tokei/lines/github/lucka-me/ingress-drone-explorer-python
[python-loc]: https://aschey.tech/tokei/github/lucka-me/ingress-drone-explorer-python
[python-benchmark-commit]: https://github.com/lucka-me/ingress-drone-explorer-python/commit/841b9f0

[rust-repo]: https://github.com/lucka-me/ingress-drone-explorer-rust
[rust-loc]: https://aschey.tech/tokei/github/lucka-me/ingress-drone-explorer-rust
[rust-benchmark-commit]: https://github.com/lucka-me/ingress-drone-explorer-rust/commit/cb21807

[swift-repo]: https://github.com/lucka-me/ingress-drone-explorer-swift
[swift-loc]: https://img.shields.io/tokei/lines/github/lucka-me/ingress-drone-explorer-swift
[swift-loc]: https://aschey.tech/tokei/github/lucka-me/ingress-drone-explorer-swift
[swift-benchmark-commit]: https://github.com/lucka-me/ingress-drone-explorer-swift/commit/2c73a58
2 changes: 1 addition & 1 deletion include/s2/cell_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ struct cell_t {
int32_t _j;

cell_t(const coordinate_t& coordinate, const uint8_t level = 16);
inline cell_t(const uint8_t face, const int32_t i, const int32_t j, uint8_t level = 16);

public:
inline auto operator<=>(const cell_t& other) const = default;
Expand All @@ -28,7 +29,6 @@ struct cell_t {
std::array<coordinate_t, 4> shape() const;

private:
inline cell_t(const uint8_t face, const int32_t i, const int32_t j, uint8_t level = 16);

inline coordinate_t coordinate(const double d_i, const double d_j) const;
inline std::set<cell_t> neighbors() const;
Expand Down
9 changes: 4 additions & 5 deletions include/s2/ecef_coordinate_t.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,12 @@ struct ecef_coordinate_t {
}

inline coordinate_t coordinate() const {
return std::move(
coordinate_t(
std::atan2(_y, _x) / std::numbers::pi * 180.0,
std::atan2(_z, std::sqrt(_x * _x + _y * _y)) / std::numbers::pi * 180.0
)
return coordinate_t(
std::atan2(_y, _x) / std::numbers::pi * 180.0,
std::atan2(_z, std::hypot(_x, _y)) / std::numbers::pi * 180.0
);
}

inline void face_s_t(uint8_t& face, double& s, double& t) const {
const auto abs_x = std::abs(_x);
const auto abs_y = std::abs(_y);
Expand Down
6 changes: 2 additions & 4 deletions src/definitions/coordinate_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,11 @@ double coordinate_t::distance_to(const coordinate_t& other) const {
}

double coordinate_t::distance_to(const coordinate_t& a, const coordinate_t& b) const {
const auto c_1 = (b._lat - a._lat) * (_lat - a._lat)
+ (b._lng - a._lng) * (_lng - a._lng);
const auto c_1 = (b._lat - a._lat) * (_lat - a._lat) + (b._lng - a._lng) * (_lng - a._lng);
if (c_1 <= 0) {
return distance_to(a);
}
const auto c_2 = (b._lat - a._lat) * (b._lat - a._lat)
+ (b._lng - a._lng) * (b._lng - a._lng);
const auto c_2 = (b._lat - a._lat) * (b._lat - a._lat) + (b._lng - a._lng) * (b._lng - a._lng);
if (c_2 <= c_1) {
return distance_to(b);
}
Expand Down
30 changes: 16 additions & 14 deletions src/explorer/explore.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,20 +27,17 @@ void explorer_t::explore_from(const coordinate_t& start) {
const auto progress_digits = digits(_cells.size());

for (auto it = queue.begin(); it != queue.end(); it = queue.begin()) {

const auto cell = *it;
queue.erase(it);

const auto portals = _cells.find(cell);
const auto portals = _cells.find(*it);
if (_cells.end() == portals) {
queue.erase(it);
continue;
}
_reachable_cells.insert(cell);
_reachable_cells.insert(*it);

// Get all neighbors in the visible range (also the possible ones), filter the empty/pending/reached ones and
// search for reachable ones
constexpr int32_t safe_rounds_for_visible_radius = (_visible_radius / 80) + 1;
const auto neighbors = cell.neighbored_cells_in(safe_rounds_for_visible_radius);
const auto neighbors = it->neighbored_cells_in(safe_rounds_for_visible_radius);
for (const auto& neighbor : neighbors) {
if (queue.contains(neighbor) || _reachable_cells.contains(neighbor) || !_cells.contains(neighbor)) {
continue;
Expand All @@ -53,21 +50,26 @@ void explorer_t::explore_from(const coordinate_t& start) {
}
}

queue.erase(it);

// Find keys
/// TODO: Consider to use cell.neighbored_cells_in instead?
if (!_cells_containing_keys.empty()) {
for (const auto& portal : portals->second) {
std::erase_if(_cells_containing_keys, [&](const auto& item) {
bool shouldErase = false;
if (queue.contains(item.first)) {
return true;
}
for (const auto& target : item.second) {
if (portal._coordinate.distance_to(target._coordinate) < _reachable_radius_with_key) {
queue.insert(item.first);
return true;
shouldErase = true;
} else {
for (const auto& target : item.second) {
if (portal._coordinate.distance_to(target._coordinate) < _reachable_radius_with_key) {
queue.insert(item.first);
shouldErase = true;
break;
}
}
}
return false;
return shouldErase;
});
if (_cells_containing_keys.empty()) {
break;
Expand Down
12 changes: 5 additions & 7 deletions src/explorer/report.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -82,14 +82,12 @@ void explorer_t::save_drawn_items_to(const std::string& filename) const {
std::transform(
_cells.begin(), _cells.end(),
std::back_inserter(items),
[&](const auto& entry) {
[&](const auto& entry) -> drawn_item_t {
const auto shape = entry.first.shape();
return std::move(
drawn_item_t(
_reachable_cells.contains(entry.first) ? "#783cbd" : "#404040",
std::move(std::vector<coordinate_t>(shape.begin(), shape.end()))
)
);
return {
_reachable_cells.contains(entry.first) ? "#783cbd" : "#404040",
{ shape.begin(), shape.end() }
};
}
);
const auto value = boost::json::value_from(items);
Expand Down
4 changes: 2 additions & 2 deletions src/extensions/tag_invoke.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ coordinate_t tag_invoke(const boost::json::value_to_tag<coordinate_t>&, const bo
coordinate_t tag;
extract(object, "lng", tag._lng);
extract(object, "lat", tag._lat);
return std::move(tag);
return tag;
}

portal_t tag_invoke(const boost::json::value_to_tag<portal_t>&, const boost::json::value& value) {
Expand All @@ -29,7 +29,7 @@ portal_t tag_invoke(const boost::json::value_to_tag<portal_t>&, const boost::jso
extract(object, "title", tag._title);
}
extract(object, "lngLat", tag._coordinate);
return std::move(tag);
return tag;
}

void tag_invoke(const boost::json::value_from_tag&, boost::json::value& value, const drawn_item_t& tag) {
Expand Down
78 changes: 38 additions & 40 deletions src/s2/cell_t.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,11 +19,25 @@ cell_t::cell_t(const coordinate_t& coordinate, const uint8_t level) {
_j = std::clamp(static_cast<decltype(_j)>(std::floor(t * max)), 0, max - 1);
}

inline cell_t::cell_t(const uint8_t face, const int32_t i, const int32_t j, uint8_t level) {
_level = level;
const int32_t max = 1 << level;
if (i >= 0 && j >= 0 && i < max && j < max) {
_face = face;
_i = i;
_j = j;
return;
}
double s, t;
ecef_coordinate_t(face, (0.5 + i) / max, (0.5 + j) / max).face_s_t(_face, s, t);
_i = std::clamp(static_cast<decltype(_i)>(std::floor(s * max)), 0, max - 1);
_j = std::clamp(static_cast<decltype(_j)>(std::floor(t * max)), 0, max - 1);
}

bool cell_t::intersects_with_cap_of(const coordinate_t& center, const double radius) const {
auto corners = shape();
/// TODO: We only needs the cloest one or two at most
std::sort(
corners.begin(), corners.end(),
std::partial_sort(
corners.begin(), corners.begin() + 2U, corners.end(),
[&](const auto& a, const auto& b) {
return center.closer(a, b);
}
Expand All @@ -36,19 +50,20 @@ std::set<cell_t> cell_t::neighbored_cells_covering_cap_of(const coordinate_t& ce
std::set<cell_t> outside;
std::set<cell_t> queue { *this };
for (auto it = queue.begin(); it != queue.end(); it = queue.begin()) {
const auto cell = *it;
queue.erase(it);
const auto& cell = *it;
if (result.contains(cell) || outside.contains(cell)) {
queue.erase(it);
continue;
}
if (cell.intersects_with_cap_of(center, radius)) {
queue.merge(cell.neighbors());
result.insert(std::move(cell));
result.emplace(cell);
} else {
outside.insert(std::move(cell));
outside.emplace(cell);
}
queue.erase(it);
}
return std::move(result);
return result;
}

std::set<cell_t> cell_t::neighbored_cells_in(const int32_t rounds) const {
Expand All @@ -58,13 +73,13 @@ std::set<cell_t> cell_t::neighbored_cells_in(const int32_t rounds) const {
for (int32_t round = 0; round < rounds; ++round) {
const int32_t steps = (round + 1) * 2;
for (int32_t step = 0; step < steps; ++step) {
result.insert(cell_t(_face, _i - round - 1 , _j - round + step, _level)); // Left, upward
result.insert(cell_t(_face, _i - round + step, _j + round + 1 , _level)); // Top, rightward
result.insert(cell_t(_face, _i + round + 1 , _j + round - step, _level)); // Right, downward
result.insert(cell_t(_face, _i + round - step, _j - round - 1 , _level)); // Bottom, leftward
result.emplace(_face, _i - round - 1 , _j - round + step, _level); // Left, upward
result.emplace(_face, _i - round + step, _j + round + 1 , _level); // Top, rightward
result.emplace(_face, _i + round + 1 , _j + round - step, _level); // Right, downward
result.emplace(_face, _i + round - step, _j - round - 1 , _level); // Bottom, leftward
}
}
return std::move(result);
return result;
}

std::array<coordinate_t, 4> cell_t::shape() const {
Expand All @@ -76,39 +91,22 @@ std::array<coordinate_t, 4> cell_t::shape() const {
};
}

inline cell_t::cell_t(const uint8_t face, const int32_t i, const int32_t j, uint8_t level) {
_level = level;
const int32_t max = 1 << level;
if (i >= 0 && j >= 0 && i < max && j < max) {
_face = face;
_i = i;
_j = j;
return;
}
double s, t;
ecef_coordinate_t(face, (0.5 + i) / max, (0.5 + j) / max).face_s_t(_face, s, t);
_i = std::clamp(static_cast<decltype(_i)>(std::floor(s * max)), 0, max - 1);
_j = std::clamp(static_cast<decltype(_j)>(std::floor(t * max)), 0, max - 1);
}

inline coordinate_t cell_t::coordinate(const double d_i, const double d_j) const {
const double max = 1 << _level;
return std::move(
ecef_coordinate_t(
_face,
(d_i + _i) / max,
(d_j + _j) / max
)
.coordinate()
);
return ecef_coordinate_t(
_face,
(d_i + _i) / max,
(d_j + _j) / max
)
.coordinate();
}

inline std::set<cell_t> cell_t::neighbors() const {
return {
cell_t(_face, _i - 1, _j , _level),
cell_t(_face, _i , _j - 1 , _level),
cell_t(_face, _i + 1, _j + 1 , _level),
cell_t(_face, _i , _j , _level),
{ _face, _i - 1, _j , _level },
{ _face, _i , _j - 1 , _level },
{ _face, _i + 1, _j , _level },
{ _face, _i , _j + 1 , _level },
};
}

Expand Down

0 comments on commit 057162c

Please sign in to comment.