diff --git a/Data/Simulations/Settings.tsv b/Data/Simulations/Settings.tsv index 97639f7e2..9527866e0 100644 --- a/Data/Simulations/Settings.tsv +++ b/Data/Simulations/Settings.tsv @@ -1,4 +1,4 @@ -key value ja-JP +key value ja-JP #Time -------------------- #時間 -------------------------------------------------- start_julian_day 1319309 シミュレーション開始日(ユリウス日) steps_per_year 12 1年あたりのStepの数(step/年) @@ -40,8 +40,8 @@ max_move_distance 1600 最大移動距離(cell) move_probability 0.0021 移動確率 ocean_cost 1.1 海上の通行コスト coast_cost 0.7 海岸の通行コスト -land_cost 1.5 傾斜度0度の陸上の通行コスト +land_cost 4.5 傾斜度0度の陸上の通行コスト move_redo 10 移動再試行回数 move_method astar 移動の手法(astar/random) -move_astar_loop 40 A*を行うルート数 +move_astar_loop 5 A*を行うルート数 move_astar_distance 64 A*を行うルート間隔 \ No newline at end of file diff --git a/Library/PAX_MAHOROBA/LocationPoint.hpp b/Library/PAX_MAHOROBA/LocationPoint.hpp index f909621b1..15953f2a7 100644 --- a/Library/PAX_MAHOROBA/LocationPoint.hpp +++ b/Library/PAX_MAHOROBA/LocationPoint.hpp @@ -739,13 +739,73 @@ namespace paxs { pop_original = settlement.getSNP() * 75.0; break; } - + const std::uint_least8_t pop = (pop_original >= 75) ? 75 : static_cast(pop_original); paxg::Circle(draw_pos, 1.0f + (settlement.getPopulation() / 40.0f)//2.0f ).draw(getColor(pop)); } +#ifdef PAXS_USING_SIV3D + if (settlement.getOldPosition().x != -1 && settlement.getOldPosition().x != 0) { + if (settlement.getPositions().size() >= 1) { + + // 過去の位置 + auto old_lli = lli; + old_lli.coordinate = paxs::MercatorDeg(getLocation(SimulationConstants::getInstance()->getStartArea(), + paxs::Vector2( + settlement.getOldPosition().x, + settlement.getOldPosition().y), 10)); + const paxg::Vec2i draw_old_pos = paxg::Vec2i{ + static_cast((old_lli.coordinate.x - (map_view_center_x - map_view_width / 2)) / map_view_width * double(paxg::Window::width())), + static_cast(double(paxg::Window::height()) - ((old_lli.coordinate.y - (map_view_center_y - map_view_height / 2)) / map_view_height * double(paxg::Window::height()))) + }; + + s3d::Array va; + va << s3d::Vec2{ draw_pos.x(), draw_pos.y() }; + for (auto&& p : settlement.getPositions()) { + auto one_lli = lli; + one_lli.coordinate = paxs::MercatorDeg(getLocation(SimulationConstants::getInstance()->getStartArea(), + paxs::Vector2(p.x, p.y), 10)); + const paxg::Vec2i draw_one_pos = paxg::Vec2i{ + static_cast((one_lli.coordinate.x - (map_view_center_x - map_view_width / 2)) / map_view_width * double(paxg::Window::width())), + static_cast(double(paxg::Window::height()) - ((one_lli.coordinate.y - (map_view_center_y - map_view_height / 2)) / map_view_height * double(paxg::Window::height()))) + }; + va << s3d::Vec2{ draw_one_pos.x(), draw_one_pos.y() }; + } + va << s3d::Vec2{ draw_old_pos.x(), draw_old_pos.y() }; + + const s3d::Spline2D spline(va); + spline.draw(2, Palette::Black); + + // 過去の位置 + auto one_lli = lli; + one_lli.coordinate = paxs::MercatorDeg(getLocation(SimulationConstants::getInstance()->getStartArea(), + paxs::Vector2( + settlement.getPositions()[0].x, + settlement.getPositions()[0].y), 10)); + const paxg::Vec2i draw_one_pos = paxg::Vec2i{ + static_cast((one_lli.coordinate.x - (map_view_center_x - map_view_width / 2)) / map_view_width * double(paxg::Window::width())), + static_cast(double(paxg::Window::height()) - ((one_lli.coordinate.y - (map_view_center_y - map_view_height / 2)) / map_view_height * double(paxg::Window::height()))) + }; + s3d::Line{ draw_one_pos.x(), draw_one_pos.y(), draw_pos.x(), draw_pos.y() }.drawArrow(0.1, s3d::Vec2{ 8, 16 }, s3d::Palette::Black); + } + else { + // 過去の位置 + auto old_lli = lli; + old_lli.coordinate = paxs::MercatorDeg(getLocation(SimulationConstants::getInstance()->getStartArea(), + paxs::Vector2( + settlement.getOldPosition().x, + settlement.getOldPosition().y), 10)); + const paxg::Vec2i draw_old_pos = paxg::Vec2i{ + static_cast((old_lli.coordinate.x - (map_view_center_x - map_view_width / 2)) / map_view_width * double(paxg::Window::width())), + static_cast(double(paxg::Window::height()) - ((old_lli.coordinate.y - (map_view_center_y - map_view_height / 2)) / map_view_height * double(paxg::Window::height()))) + }; + s3d::Line{ draw_old_pos.x(), draw_old_pos.y(), draw_pos.x(), draw_pos.y() }.drawArrow(2, s3d::Vec2{ 8, 16 }, s3d::Palette::Black); + } + } +#endif + } } diff --git a/Library/PAX_SAPIENTICA/Simulation/Settlement.hpp b/Library/PAX_SAPIENTICA/Simulation/Settlement.hpp index a3a0f377d..759b5c08e 100644 --- a/Library/PAX_SAPIENTICA/Simulation/Settlement.hpp +++ b/Library/PAX_SAPIENTICA/Simulation/Settlement.hpp @@ -72,6 +72,10 @@ namespace paxs { class AStar { using AStarVec2 = paxs::Vector2; private: + //始点 元の座標 + AStarVec2 start_vec2_original{}; + //終点 元の座標 + AStarVec2 end_vec2_original{}; //始点 AStarVec2 start_vec2{}; //終点 @@ -85,18 +89,20 @@ namespace paxs { public: AStar() noexcept = default; AStar(const AStarVec2& start_vec2_, const AStarVec2& end_vec2_, const GridType z_) noexcept - :start_vec2(start_vec2_), end_vec2(end_vec2_), z(z_) {} + :start_vec2_original(start_vec2_), end_vec2_original(end_vec2_), + start_vec2(start_vec2_ / z_), end_vec2(end_vec2_ / z_), + z(z_) {} constexpr GridType calculateDistance(const AStarVec2& vec2_) const noexcept { const GridType x{ end_vec2.x - vec2_.x }; const GridType y{ end_vec2.y - vec2_.y }; return (x >= y) ? x : y; } - constexpr bool isRange(const AStarVec2& vec2_) const noexcept { - return vec2_.x >= (std::min)(start_vec2.x, end_vec2.x) - && vec2_.y >= (std::min)(start_vec2.y, end_vec2.y) - && vec2_.x < (std::max)(start_vec2.x, end_vec2.x) - && vec2_.y < (std::max)(start_vec2.y, end_vec2.y); + bool isRange(const AStarVec2& vec2_) const noexcept { + return vec2_.x >= (std::min)(start_vec2.x, end_vec2.x) - std::abs(start_vec2.x - end_vec2.x) / 2 + && vec2_.y >= (std::min)(start_vec2.y, end_vec2.y) - std::abs(start_vec2.y - end_vec2.y) / 2 + && vec2_.x < (std::max)(start_vec2.x, end_vec2.x) + std::abs(start_vec2.x - end_vec2.x) / 2 + && vec2_.y < (std::max)(start_vec2.y, end_vec2.y) + std::abs(start_vec2.y - end_vec2.y) / 2; } bool existPoint(const AStarVec2& vec2_, const double cost_) noexcept { @@ -157,7 +163,7 @@ namespace paxs { const AStarVec2 neighbour_z = neighbour * z; if (!isRange(neighbour)) continue; - //if (!isRange(neighbour, x_, y_) || environment->getSlope(neighbour_z) >= 213) continue; + //if (!isRange(neighbour) || environment->getSlope(neighbour_z) >= 213) continue; //コスト計算 const double node_cost = calcCost(environment, neighbour_z) + node_.cost; const GridType distance = calculateDistance(neighbour); @@ -182,18 +188,21 @@ namespace paxs { return closed.back().cost; } - double setPath(std::vector& path_) noexcept { - path_.emplace_back(end_vec2); - double cost{ 1 + closed.back().cost }; - path_.emplace_back(closed.back().position); + void setPath(std::vector& path_) noexcept { + path_.resize(0); + const AStarVec2 sub = AStarVec2{ + std::abs(start_vec2_original.x - start_vec2.x * z) / 2, + std::abs(start_vec2_original.y - start_vec2.y * z) / 2 + }; + // path_.emplace_back(end_vec2_original); + path_.emplace_back(closed.back().position * z + sub); AStarVec2 parent_node{ closed.back().parent_node }; for (auto&& i{ closed.rbegin() }; i != closed.rend(); ++i) { if (!((*i).position == parent_node) || ((*i).position == start_vec2)) continue; - path_.emplace_back((*i).position); + path_.emplace_back((*i).position * z + sub); parent_node = (*i).parent_node; } - path_.emplace_back(start_vec2); - return cost; + //path_.emplace_back(start_vec2_original); } }; @@ -251,12 +260,21 @@ namespace paxs { /// @brief Set the position of the settlement. /// @brief 集落の座標を設定 void setPosition(const Vector2& position_) noexcept { + old_position = position; position = position_; } + /// @brief + /// @brief 集落の過去の座標を消去 + void clearOldPosition() noexcept { + old_position = Vector2(-1, -1); + positions.resize(0); + } /// @brief Get the position of the settlement. /// @brief 集落の座標を取得 Vector2 getPosition() const noexcept { return position; } + Vector2 getOldPosition() const noexcept { return old_position; } + const std::vector& getPositions() const noexcept { return positions; } /// @brief Get the agent. /// @brief エージェントを取得 @@ -520,12 +538,14 @@ namespace paxs { if (cp_cw == mp_cw) break; // 同じ座標なので AStar 不可能 // 隣接座標なので AStar 不可能 else if (std::abs(cp_cw.x - mp_cw.x) <= 1 && std::abs(cp_cw.y - mp_cw.y) <= 1) break; - AStar astar(cp_cw, mp_cw, cw); + AStar astar(current_position, move_position, cw); astar.search(environment); // 最初の場合または以前よりもコストが低い場合は上書きする if (cost == -1.0 || cost > astar.getCost()) { target_position = move_position; cost = astar.getCost(); + // 経路を設定 + astar.setPath(positions); } } } @@ -662,6 +682,8 @@ namespace paxs { std::uint_least32_t id = 0; /// @brief 集落の座標 Vector2 position{}; + Vector2 old_position{ -1,-1 }; + std::vector positions{}; std::mt19937* gen{}; // 乱数生成器 diff --git a/Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp b/Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp index 933fb26b9..e034ca956 100644 --- a/Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp +++ b/Library/PAX_SAPIENTICA/Simulation/SettlementSimulator.hpp @@ -176,6 +176,9 @@ namespace paxs { for (auto& settlement_grid : settlement_grids) { std::vector& settlements = settlement_grid.second.getSettlements(); for (std::size_t i = 0; i < settlements.size(); ++i) { + // 集落の過去の位置情報を削除 + settlements[i].clearOldPosition(); + if (settlements[i].isMoved()) { continue; }