From 0283aeb2c21b2719b92829037ae2bbc9b011093f Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 02:02:27 +0300 Subject: [PATCH 01/42] Add some helpers classes and structures --- Backend/optimal_way/circleobstacle.h | 55 ++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 Backend/optimal_way/circleobstacle.h diff --git a/Backend/optimal_way/circleobstacle.h b/Backend/optimal_way/circleobstacle.h new file mode 100644 index 0000000..891ed78 --- /dev/null +++ b/Backend/optimal_way/circleobstacle.h @@ -0,0 +1,55 @@ +#pragma once + +#include +#include + +#include "../lib/point.h" + +namespace math { + +// Структура хранит коэфиценты для прямой вида ax+by+c=0 +struct LinearАunction { + LinearАunction(double a, double b, double c) + : a_coef{a}, b_coef{b}, c_coef{c} {} + double a_coef, b_coef, c_coef; + bool operator==(const LinearАunction& other) { + return (a_coef == other.a_coef && b_coef == other.b_coef && + c_coef == other.c_coef); + } +}; + +struct Point : public lib::Point { + Point(double xx, double yy) : lib::Point{xx, yy} {} + std::vector tangents; + std::shared_ptr another_tangent_point = nullptr; +}; + +class CircleObstacle { + public: + CircleObstacle(Point center, double radius) + : center_{center}, radius_{radius} {} + + Point GetCenter() const { return center_; } + double GetRadius() const { return radius_; } + std::vector GetTangentLines() { return tangents_; } + std::vector GetTangentPoints() { return tangent_points_; } + + void SetCenter(const Point& center) { center_ = center; } + void SetRadius(double r) { radius_ = r; } + void AddTangentLine(const LinearАunction& tangent) { + tangents_.push_back(tangent); + } + void AddTangentPoint(const Point& tangent_point) { + tangent_points_.push_back(tangent_point); + } + bool operator==(const CircleObstacle& other) { + return (center_ == other.center_ && radius_ == other.radius_); + } + + private: + Point center_; + double radius_; + std::vector tangents_; + std::vector tangent_points_; +}; +} // namespace math From 1bfc8672bebc156125c54314f24c460da5c64c33 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 02:04:31 +0300 Subject: [PATCH 02/42] Add constructor of class PathGraph #Constructs a graph by obstacles --- Backend/optimal_way/pathgraph.cpp | 29 +++++++++++++++++++++++++++++ Backend/optimal_way/pathgraph.h | 26 ++++++++++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 Backend/optimal_way/pathgraph.cpp create mode 100644 Backend/optimal_way/pathgraph.h diff --git a/Backend/optimal_way/pathgraph.cpp b/Backend/optimal_way/pathgraph.cpp new file mode 100644 index 0000000..0f840ab --- /dev/null +++ b/Backend/optimal_way/pathgraph.cpp @@ -0,0 +1,29 @@ +#include "pathgraph.h" + +#include + +namespace math { + +PathGraph::PathGraph(std::vector obstacles, Point point1, + Point point2) { + for (auto& obstacle : obstacles) { + for (auto& point : obstacle.GetTangentPoints()) { + if (point.another_tangent_point) { + PathWayNode new_node{point}; + new_node.circle_prt = std::make_unique(obstacle); + for (auto& prev : graph_) { + if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { + prev.edges.push_back(std::make_shared(new_node)); + new_node.edges.push_back(std::make_shared(prev)); + } else if (prev.circle_prt && + (new_node.point == (*prev.point.another_tangent_point))) { + prev.edges.push_back(std::make_shared(new_node)); + new_node.edges.push_back(std::make_shared(prev)); + } + } + graph_.push_back(new_node); + } + } + } +} +} // namespace math diff --git a/Backend/optimal_way/pathgraph.h b/Backend/optimal_way/pathgraph.h new file mode 100644 index 0000000..d259ec8 --- /dev/null +++ b/Backend/optimal_way/pathgraph.h @@ -0,0 +1,26 @@ +#pragma once + +#include +#include + +#include "circleobstacle.h" +namespace math { + +struct PathWayNode { + PathWayNode(Point p) : point{p} {} + std::vector> edges; + std::unique_ptr circle_prt = nullptr; + Point point; +}; + +class PathGraph { + public: + PathGraph(std::vector obstacles, Point point1, Point point2); + + private: + std::vector graph_; + + double FindTheShortestWay(); +}; + +} // namespace math From c6f5c24c2972767296f7ce3b72560384d7146b00 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 02:08:29 +0300 Subject: [PATCH 03/42] Delete useless include --- Backend/optimal_way/pathgraph.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Backend/optimal_way/pathgraph.cpp b/Backend/optimal_way/pathgraph.cpp index 0f840ab..9c8bade 100644 --- a/Backend/optimal_way/pathgraph.cpp +++ b/Backend/optimal_way/pathgraph.cpp @@ -1,7 +1,5 @@ #include "pathgraph.h" -#include - namespace math { PathGraph::PathGraph(std::vector obstacles, Point point1, From b77205a3a600102f1e83bca14fb09c938e7311cc Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 02:10:48 +0300 Subject: [PATCH 04/42] Add class OptimalWay --- Backend/optimal_way/optimal_way.cpp | 183 ++++++++++++++++++++++++++++ Backend/optimal_way/optimal_way.h | 48 ++++++++ 2 files changed, 231 insertions(+) create mode 100644 Backend/optimal_way/optimal_way.cpp create mode 100644 Backend/optimal_way/optimal_way.h diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp new file mode 100644 index 0000000..b2b5377 --- /dev/null +++ b/Backend/optimal_way/optimal_way.cpp @@ -0,0 +1,183 @@ +#include "optimal_way.h" + +#include + +namespace math { + +LinearАunction MinimumDistanceCalculator::MakeLinearАunction( + const Point& point1, const Point& point2) const { + double slope = (point2.y - point1.y) / (point2.x - point1.x); + double b_coef = point1.y - slope * point1.x; + return LinearАunction{slope, -1, b_coef}; +} + +double MinimumDistanceCalculator::DistanceBetweenPoints(const Point& p1, + const Point p2) const { + return pow(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2), 0.5); +} + +std::pair MinimumDistanceCalculator::CrossPoints( + const LinearАunction& tangent, const CircleObstacle& circle1, + const CircleObstacle& circle2) const { + double a = tangent.a_coef; + double b = tangent.b_coef; + double c = tangent.c_coef; + double x_0 = circle1.GetCenter().x; + double y_0 = circle1.GetCenter().y; + double x_1 = circle2.GetCenter().x; + double y_1 = circle2.GetCenter().y; + double point1_x = (-((a / b) * (c / b + y_0) - x_0)) / (1 + pow(a / b, 2)); + double point1_y = a / b * point1_x - c / b; + double point2_x = (-((a / b) * (c / b + y_1) - x_1)) / (1 + pow(a / b, 2)); + double point2_y = a / b * point2_x - c / b; + Point point1{point1_x, point1_y}; + Point point2{point2_x, point2_y}; + return std::pair{point1, point2}; +} + +std::pair MinimumDistanceCalculator::TangentPointsToCircle( + const CircleObstacle& crcl, const Point& pnt) const { + Point center = crcl.GetCenter(); + double radius = crcl.GetRadius(); + double discriminant = pow((center.x - pnt.x) * (center.y - pnt.y), 2) - + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double slope_1 = + (-(center.x - pnt.x) * (center.y - pnt.y) + sqrt(discriminant)) / + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double slope_2 = + (-(center.x - pnt.x) * (center.y - pnt.y) - sqrt(discriminant)) / + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double b1_coef = pnt.y - slope_1 * pnt.x; + double b2_coef = pnt.y - slope_2 * pnt.x; + double x1_cross_pnt = (-(slope_1 * b1_coef - center.x - slope_1 * center.y)) / + (1 + pow(slope_1, 2)); + double x2_cross_pnt = (-(slope_2 * b2_coef - center.x - slope_2 * center.y)) / + (1 + pow(slope_2, 2)); + double y1_cross_pnt = slope_1 * x1_cross_pnt + b1_coef; + double y2_cross_pnt = slope_2 * x2_cross_pnt + b2_coef; + return std::pair{{x1_cross_pnt, y1_cross_pnt}, + {x2_cross_pnt, y2_cross_pnt}}; +} + +std::vector MinimumDistanceCalculator::TangentsBetweenCircles( + const CircleObstacle& circle1, const CircleObstacle& circle2) const { + std::vector tangents; + double x_1 = circle2.GetCenter().x; + double y_1 = circle2.GetCenter().y; + double r_1 = circle2.GetRadius(); + double x_0 = circle1.GetCenter().x; + double y_0 = circle1.GetCenter().y; + double r_0 = circle1.GetRadius(); + + auto FindTangent = [&x_1, &x_0, &y_1, &y_0](double r_0, double r_1) { + double b = + ((r_1 - r_0) * (y_1 - y_0) + + sqrt(pow(x_1 - x_0, 2) * + (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2) - pow(r_1 - r_0, 2)))) / + (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2)); + double a = ((r_1 - r_0) - b * (y_1 - y_0)) / (x_1 - x_0); + double c = r_0 - a * x_0 - b * y_0; + LinearАunction tangent{a, b, c}; + return tangent; + }; + + for (auto n1 : {-1, 1}) + for (auto n2 : {-1, 1}) tangents.push_back(FindTangent(r_0 * n1, r_1 * n2)); + return tangents; +} + +bool MinimumDistanceCalculator::AreThereIntersections( + const CircleObstacle& crcl, const Point& pnt1, const Point& pnt2) const { + double slope = (point2_.y - point1_.y) / (point2_.x - point1_.x); + double b_coef = point1_.y - slope * point1_.x; + Point center = crcl.GetCenter(); + double radius = crcl.GetRadius(); + double discriminant = (pow(slope * b_coef - center.x - slope * center.y, 2)) + + (pow(radius, 2) - pow(center.x, 2) - pow(b_coef, 2) - + pow(center.y, 2) + 2 * b_coef * center.y) * + (1 + pow(slope, 2)); + if (discriminant <= 0) + return false; + else { + float x_1 = + (-(slope * b_coef - center.x - slope * center.y) + sqrt(discriminant)) / + (1 + pow(slope, 2)); + float x_2 = + (-(slope * b_coef - center.x - slope * center.y) - sqrt(discriminant)) / + (1 + pow(slope, 2)); + if ((std::min(point1_.x, point2_.x) <= x_1 <= + std::max(point1_.x, point2_.x)) || + (std::min(point1_.x, point2_.x) <= x_2 <= + std::max(point1_.x, point2_.x))) + return true; + else + return false; + } +} + +void MinimumDistanceCalculator::FillTangentsCircles() { + for (int i = 0; i < circles_.size(); ++i) { + for (int j = i + 1; j < circles_.size(); ++j) { + std::vector tangents = + TangentsBetweenCircles(circles_[i], circles_[j]); + for (int k = 0; k < tangents.size(); ++k) { + bool is_exist = true; + for (int l = 0; l < circles_.size(); ++l) { + if (l != i && l != j) { + std::pair tangent_points = + CrossPoints(tangents[k], circles_[i], circles_[j]); + if (AreThereIntersections(circles_[l], tangent_points.first, + tangent_points.second)) { + is_exist = false; + break; + } + } + } + if (is_exist) { + std::pair tangent_points = + CrossPoints(tangents[k], circles_[i], circles_[j]); + tangent_points.first.another_tangent_point = + std::make_shared(tangent_points.second); + tangent_points.second.another_tangent_point = + std::make_shared(tangent_points.first); + circles_[i].AddTangentLine(tangents[k]); + circles_[i].AddTangentPoint(tangent_points.first); + circles_[j].AddTangentLine(tangents[k]); + circles_[j].AddTangentPoint(tangent_points.second); + } + } + } + } +} + +void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { + for (int i = 0; i < circles_.size(); ++i) { + std::pair tangent_points_1 = + TangentPointsToCircle(circles_[i], point); + bool is_exist_tangent1 = true; + bool is_exist_tangent2 = true; + for (int j = 0; j < circles_.size(); ++j) { + if (j != i) { + if (AreThereIntersections(circles_[j], point, tangent_points_1.first)) + is_exist_tangent1 = false; + if (AreThereIntersections(circles_[j], point, tangent_points_1.second)) + is_exist_tangent2 = false; + } + } + if (is_exist_tangent1) + point.tangents.push_back( + MakeLinearАunction(point, tangent_points_1.first)); + if (is_exist_tangent2) + point.tangents.push_back( + MakeLinearАunction(point, tangent_points_1.second)); + } +} + +double MinimumDistanceCalculator::FindOptimalWay(const Point& pnt1, + const Point& pnt2) { + FillTangentsCircles(); + FillTangentsPoints(point1_); + FillTangentsPoints(point2_); + PathGraph optimal_way{circles_, point1_, point2_}; +} +} // namespace math diff --git a/Backend/optimal_way/optimal_way.h b/Backend/optimal_way/optimal_way.h new file mode 100644 index 0000000..5a96058 --- /dev/null +++ b/Backend/optimal_way/optimal_way.h @@ -0,0 +1,48 @@ +#pragma once + +#include + +#include "pathgraph.h" + +namespace math { + +class MinimumDistanceCalculator { + public: + MinimumDistanceCalculator(Point p1, Point p2) + : point1_{p1}, point2_{p2}, circles_(0) {} + MinimumDistanceCalculator(Point p1, Point p2, std::vector v) + : point1_{p1}, point2_{p2}, circles_{v} {} + + private: + Point point1_; + Point point2_; + std::vector circles_; + std::vector ways_; + + double DistanceBetweenPoints(const Point& p1, const Point p2) const; + + LinearАunction MakeLinearАunction(const Point& point1, + const Point& point2) const; + // Точки касания прямой к окружснотям + std::pair CrossPoints(const LinearАunction& tangent, + const CircleObstacle& circle1, + const CircleObstacle& circle2) const; + + std::pair TangentPointsToCircle(const CircleObstacle& crcl, + const Point& point) const; + + std::vector TangentsBetweenCircles( + const CircleObstacle& circle1, const CircleObstacle& circle2) const; + + // Пересекает ли отрезок, проведенный через две точки, окружность + bool AreThereIntersections(const CircleObstacle& crcl, const Point& pnt1, + const Point& pnt2) const; + + // Заполняет вектор точек касательных для каждой окружности + void FillTangentsCircles(); + + void FillTangentsPoints(Point& point); + + double FindOptimalWay(const Point& pnt1, const Point& pnt2); +}; +} // namespace math From 69b7e7db5e71fb78d1c546e09aff0ada7628da6c Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 11:43:37 +0300 Subject: [PATCH 05/42] Change type of pointer to copy it --- Backend/optimal_way/pathgraph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Backend/optimal_way/pathgraph.h b/Backend/optimal_way/pathgraph.h index d259ec8..9c20ba1 100644 --- a/Backend/optimal_way/pathgraph.h +++ b/Backend/optimal_way/pathgraph.h @@ -9,7 +9,7 @@ namespace math { struct PathWayNode { PathWayNode(Point p) : point{p} {} std::vector> edges; - std::unique_ptr circle_prt = nullptr; + std::shared_ptr circle_prt = nullptr; Point point; }; From 6734801964170ae1b7014da7757520a1af554a3a Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Sat, 6 Apr 2024 11:50:55 +0300 Subject: [PATCH 06/42] Add default constructor --- Backend/optimal_way/circleobstacle.h | 1 + 1 file changed, 1 insertion(+) diff --git a/Backend/optimal_way/circleobstacle.h b/Backend/optimal_way/circleobstacle.h index 891ed78..da9a057 100644 --- a/Backend/optimal_way/circleobstacle.h +++ b/Backend/optimal_way/circleobstacle.h @@ -28,6 +28,7 @@ class CircleObstacle { public: CircleObstacle(Point center, double radius) : center_{center}, radius_{radius} {} + CircleObstacle() : center_{0, 0}, radius_{0} {} Point GetCenter() const { return center_; } double GetRadius() const { return radius_; } From 999d2f78b3227e9332cb71085e3ded76465f8f64 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 16:08:14 +0300 Subject: [PATCH 07/42] Remove function from class --- Backend/optimal_way/helpers_functions.cpp | 112 +++++++++++++++++++++ Backend/optimal_way/helpers_functions.h | 24 +++++ Backend/optimal_way/optimal_way.cpp | 114 +--------------------- Backend/optimal_way/optimal_way.h | 21 +--- 4 files changed, 139 insertions(+), 132 deletions(-) create mode 100644 Backend/optimal_way/helpers_functions.cpp create mode 100644 Backend/optimal_way/helpers_functions.h diff --git a/Backend/optimal_way/helpers_functions.cpp b/Backend/optimal_way/helpers_functions.cpp new file mode 100644 index 0000000..177bee5 --- /dev/null +++ b/Backend/optimal_way/helpers_functions.cpp @@ -0,0 +1,112 @@ +#include "helpers_functions.h" + +#include + +namespace math { +LinearАunction MakeLinearАunction(const Point& point1, const Point& point2) { + double slope = (point2.y - point1.y) / (point2.x - point1.x); + double b_coef = point1.y - slope * point1.x; + return LinearАunction{slope, -1, b_coef}; +} + +double DistanceBetweenPoints(const Point& p1, const Point& p2) { + return pow(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2), 0.5); +} + +std::pair CrossPoints(const LinearАunction& tangent, + const CircleObstacle& circle1, + const CircleObstacle& circle2) { + double a = tangent.a_coef; + double b = tangent.b_coef; + double c = tangent.c_coef; + double x_0 = circle1.GetCenter().x; + double y_0 = circle1.GetCenter().y; + double x_1 = circle2.GetCenter().x; + double y_1 = circle2.GetCenter().y; + double point1_x = (-((a / b) * (c / b + y_0) - x_0)) / (1 + pow(a / b, 2)); + double point1_y = a / b * point1_x - c / b; + double point2_x = (-((a / b) * (c / b + y_1) - x_1)) / (1 + pow(a / b, 2)); + double point2_y = a / b * point2_x - c / b; + Point point1{point1_x, point1_y}; + Point point2{point2_x, point2_y}; + return std::pair{point1, point2}; +} + +std::pair TangentPointsToCircle(const CircleObstacle& crcl, + const Point& pnt) { + Point center = crcl.GetCenter(); + double radius = crcl.GetRadius(); + double discriminant = pow((center.x - pnt.x) * (center.y - pnt.y), 2) - + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double slope_1 = + (-(center.x - pnt.x) * (center.y - pnt.y) + sqrt(discriminant)) / + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double slope_2 = + (-(center.x - pnt.x) * (center.y - pnt.y) - sqrt(discriminant)) / + (pow(radius, 2) - pow(pnt.x - center.x, 2)); + double b1_coef = pnt.y - slope_1 * pnt.x; + double b2_coef = pnt.y - slope_2 * pnt.x; + double x1_cross_pnt = (-(slope_1 * b1_coef - center.x - slope_1 * center.y)) / + (1 + pow(slope_1, 2)); + double x2_cross_pnt = (-(slope_2 * b2_coef - center.x - slope_2 * center.y)) / + (1 + pow(slope_2, 2)); + double y1_cross_pnt = slope_1 * x1_cross_pnt + b1_coef; + double y2_cross_pnt = slope_2 * x2_cross_pnt + b2_coef; + return std::pair{{x1_cross_pnt, y1_cross_pnt}, + {x2_cross_pnt, y2_cross_pnt}}; +} + +std::vector TangentsBetweenCircles( + const CircleObstacle& circle1, const CircleObstacle& circle2) { + std::vector tangents; + double x_1 = circle2.GetCenter().x; + double y_1 = circle2.GetCenter().y; + double r_1 = circle2.GetRadius(); + double x_0 = circle1.GetCenter().x; + double y_0 = circle1.GetCenter().y; + double r_0 = circle1.GetRadius(); + + auto FindTangent = [&x_1, &x_0, &y_1, &y_0](double r_0, double r_1) { + double b = + ((r_1 - r_0) * (y_1 - y_0) + + sqrt(pow(x_1 - x_0, 2) * + (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2) - pow(r_1 - r_0, 2)))) / + (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2)); + double a = ((r_1 - r_0) - b * (y_1 - y_0)) / (x_1 - x_0); + double c = r_0 - a * x_0 - b * y_0; + LinearАunction tangent{a, b, c}; + return tangent; + }; + + for (auto n1 : {-1, 1}) + for (auto n2 : {-1, 1}) tangents.push_back(FindTangent(r_0 * n1, r_1 * n2)); + return tangents; +} + +bool AreThereIntersections(const CircleObstacle& crcl, const Point& point1, + const Point& point2) { + double slope = (point2.y - point1.y) / (point2.x - point1.x); + double b_coef = point1.y - slope * point1.x; + Point center = crcl.GetCenter(); + double radius = crcl.GetRadius(); + double discriminant = (pow(slope * b_coef - center.x - slope * center.y, 2)) + + (pow(radius, 2) - pow(center.x, 2) - pow(b_coef, 2) - + pow(center.y, 2) + 2 * b_coef * center.y) * + (1 + pow(slope, 2)); + if (discriminant <= 0) + return false; + else { + float x_1 = + (-(slope * b_coef - center.x - slope * center.y) + sqrt(discriminant)) / + (1 + pow(slope, 2)); + float x_2 = + (-(slope * b_coef - center.x - slope * center.y) - sqrt(discriminant)) / + (1 + pow(slope, 2)); + if ((std::min(point1.x, point2.x) <= x_1 <= std::max(point1.x, point2.x)) || + (std::min(point1.x, point2.x) <= x_2 <= std::max(point1.x, point2.x))) + return true; + else + return false; + } +} +} // namespace math diff --git a/Backend/optimal_way/helpers_functions.h b/Backend/optimal_way/helpers_functions.h new file mode 100644 index 0000000..4a5895b --- /dev/null +++ b/Backend/optimal_way/helpers_functions.h @@ -0,0 +1,24 @@ +#pragma once + +#include "circleobstacle.h" +namespace math { +double DistanceBetweenPoints(const Point& p1, const Point p2); + +LinearАunction MakeLinearАunction(const Point& point1, const Point& point2); + +// Точки касания прямой к окружснотям +std::pair CrossPoints(const LinearАunction& tangent, + const CircleObstacle& circle1, + const CircleObstacle& circle2); + +std::pair TangentPointsToCircle(const CircleObstacle& crcl, + const Point& point); + +std::vector TangentsBetweenCircles( + const CircleObstacle& circle1, const CircleObstacle& circle2); + +// Пересекает ли отрезок, проведенный через две точки, окружность +bool AreThereIntersections(const CircleObstacle& crcl, const Point& pnt1, + const Point& pnt2); + +} // namespace math diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp index b2b5377..752ca8a 100644 --- a/Backend/optimal_way/optimal_way.cpp +++ b/Backend/optimal_way/optimal_way.cpp @@ -1,120 +1,10 @@ #include "optimal_way.h" -#include +#include "helpers_functions.h" +#include "pathgraph.h" namespace math { -LinearАunction MinimumDistanceCalculator::MakeLinearАunction( - const Point& point1, const Point& point2) const { - double slope = (point2.y - point1.y) / (point2.x - point1.x); - double b_coef = point1.y - slope * point1.x; - return LinearАunction{slope, -1, b_coef}; -} - -double MinimumDistanceCalculator::DistanceBetweenPoints(const Point& p1, - const Point p2) const { - return pow(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2), 0.5); -} - -std::pair MinimumDistanceCalculator::CrossPoints( - const LinearАunction& tangent, const CircleObstacle& circle1, - const CircleObstacle& circle2) const { - double a = tangent.a_coef; - double b = tangent.b_coef; - double c = tangent.c_coef; - double x_0 = circle1.GetCenter().x; - double y_0 = circle1.GetCenter().y; - double x_1 = circle2.GetCenter().x; - double y_1 = circle2.GetCenter().y; - double point1_x = (-((a / b) * (c / b + y_0) - x_0)) / (1 + pow(a / b, 2)); - double point1_y = a / b * point1_x - c / b; - double point2_x = (-((a / b) * (c / b + y_1) - x_1)) / (1 + pow(a / b, 2)); - double point2_y = a / b * point2_x - c / b; - Point point1{point1_x, point1_y}; - Point point2{point2_x, point2_y}; - return std::pair{point1, point2}; -} - -std::pair MinimumDistanceCalculator::TangentPointsToCircle( - const CircleObstacle& crcl, const Point& pnt) const { - Point center = crcl.GetCenter(); - double radius = crcl.GetRadius(); - double discriminant = pow((center.x - pnt.x) * (center.y - pnt.y), 2) - - (pow(radius, 2) - pow(pnt.x - center.x, 2)); - double slope_1 = - (-(center.x - pnt.x) * (center.y - pnt.y) + sqrt(discriminant)) / - (pow(radius, 2) - pow(pnt.x - center.x, 2)); - double slope_2 = - (-(center.x - pnt.x) * (center.y - pnt.y) - sqrt(discriminant)) / - (pow(radius, 2) - pow(pnt.x - center.x, 2)); - double b1_coef = pnt.y - slope_1 * pnt.x; - double b2_coef = pnt.y - slope_2 * pnt.x; - double x1_cross_pnt = (-(slope_1 * b1_coef - center.x - slope_1 * center.y)) / - (1 + pow(slope_1, 2)); - double x2_cross_pnt = (-(slope_2 * b2_coef - center.x - slope_2 * center.y)) / - (1 + pow(slope_2, 2)); - double y1_cross_pnt = slope_1 * x1_cross_pnt + b1_coef; - double y2_cross_pnt = slope_2 * x2_cross_pnt + b2_coef; - return std::pair{{x1_cross_pnt, y1_cross_pnt}, - {x2_cross_pnt, y2_cross_pnt}}; -} - -std::vector MinimumDistanceCalculator::TangentsBetweenCircles( - const CircleObstacle& circle1, const CircleObstacle& circle2) const { - std::vector tangents; - double x_1 = circle2.GetCenter().x; - double y_1 = circle2.GetCenter().y; - double r_1 = circle2.GetRadius(); - double x_0 = circle1.GetCenter().x; - double y_0 = circle1.GetCenter().y; - double r_0 = circle1.GetRadius(); - - auto FindTangent = [&x_1, &x_0, &y_1, &y_0](double r_0, double r_1) { - double b = - ((r_1 - r_0) * (y_1 - y_0) + - sqrt(pow(x_1 - x_0, 2) * - (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2) - pow(r_1 - r_0, 2)))) / - (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2)); - double a = ((r_1 - r_0) - b * (y_1 - y_0)) / (x_1 - x_0); - double c = r_0 - a * x_0 - b * y_0; - LinearАunction tangent{a, b, c}; - return tangent; - }; - - for (auto n1 : {-1, 1}) - for (auto n2 : {-1, 1}) tangents.push_back(FindTangent(r_0 * n1, r_1 * n2)); - return tangents; -} - -bool MinimumDistanceCalculator::AreThereIntersections( - const CircleObstacle& crcl, const Point& pnt1, const Point& pnt2) const { - double slope = (point2_.y - point1_.y) / (point2_.x - point1_.x); - double b_coef = point1_.y - slope * point1_.x; - Point center = crcl.GetCenter(); - double radius = crcl.GetRadius(); - double discriminant = (pow(slope * b_coef - center.x - slope * center.y, 2)) + - (pow(radius, 2) - pow(center.x, 2) - pow(b_coef, 2) - - pow(center.y, 2) + 2 * b_coef * center.y) * - (1 + pow(slope, 2)); - if (discriminant <= 0) - return false; - else { - float x_1 = - (-(slope * b_coef - center.x - slope * center.y) + sqrt(discriminant)) / - (1 + pow(slope, 2)); - float x_2 = - (-(slope * b_coef - center.x - slope * center.y) - sqrt(discriminant)) / - (1 + pow(slope, 2)); - if ((std::min(point1_.x, point2_.x) <= x_1 <= - std::max(point1_.x, point2_.x)) || - (std::min(point1_.x, point2_.x) <= x_2 <= - std::max(point1_.x, point2_.x))) - return true; - else - return false; - } -} - void MinimumDistanceCalculator::FillTangentsCircles() { for (int i = 0; i < circles_.size(); ++i) { for (int j = i + 1; j < circles_.size(); ++j) { diff --git a/Backend/optimal_way/optimal_way.h b/Backend/optimal_way/optimal_way.h index 5a96058..bb09d9c 100644 --- a/Backend/optimal_way/optimal_way.h +++ b/Backend/optimal_way/optimal_way.h @@ -2,7 +2,7 @@ #include -#include "pathgraph.h" +#include "circleobstacle.h" namespace math { @@ -19,25 +19,6 @@ class MinimumDistanceCalculator { std::vector circles_; std::vector ways_; - double DistanceBetweenPoints(const Point& p1, const Point p2) const; - - LinearАunction MakeLinearАunction(const Point& point1, - const Point& point2) const; - // Точки касания прямой к окружснотям - std::pair CrossPoints(const LinearАunction& tangent, - const CircleObstacle& circle1, - const CircleObstacle& circle2) const; - - std::pair TangentPointsToCircle(const CircleObstacle& crcl, - const Point& point) const; - - std::vector TangentsBetweenCircles( - const CircleObstacle& circle1, const CircleObstacle& circle2) const; - - // Пересекает ли отрезок, проведенный через две точки, окружность - bool AreThereIntersections(const CircleObstacle& crcl, const Point& pnt1, - const Point& pnt2) const; - // Заполняет вектор точек касательных для каждой окружности void FillTangentsCircles(); From ef2701bdb4a62583969281939e931febebb43333 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 18:40:24 +0300 Subject: [PATCH 08/42] Change comparing of circle obstacle and Linear function. --- Backend/optimal_way/circleobstacle.h | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/Backend/optimal_way/circleobstacle.h b/Backend/optimal_way/circleobstacle.h index da9a057..b9eec65 100644 --- a/Backend/optimal_way/circleobstacle.h +++ b/Backend/optimal_way/circleobstacle.h @@ -1,11 +1,13 @@ #pragma once +#include #include #include #include "../lib/point.h" namespace math { +constexpr double precision = 0.000001; // Структура хранит коэфиценты для прямой вида ax+by+c=0 struct LinearАunction { @@ -13,8 +15,9 @@ struct LinearАunction { : a_coef{a}, b_coef{b}, c_coef{c} {} double a_coef, b_coef, c_coef; bool operator==(const LinearАunction& other) { - return (a_coef == other.a_coef && b_coef == other.b_coef && - c_coef == other.c_coef); + return (std::abs(a_coef - other.a_coef) < precision && + std::abs(b_coef - other.b_coef) < precision && + std::abs(c_coef - other.c_coef) < precision); } }; @@ -44,7 +47,12 @@ class CircleObstacle { tangent_points_.push_back(tangent_point); } bool operator==(const CircleObstacle& other) { - return (center_ == other.center_ && radius_ == other.radius_); + return (center_ == other.center_ && + std::abs(radius_ - other.radius_) < precision); + } + bool operator!=(const CircleObstacle& other) { + return (center_ != other.center_ || + std::abs(radius_ - other.radius_) >= precision); } private: From aa8a91f75cf7ecb6780d3200a0ffb7b92abb6880 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 19:09:17 +0300 Subject: [PATCH 09/42] Split FillTangentsCircles function into 3 functions --- Backend/optimal_way/optimal_way.cpp | 57 ++++++++++++++++------------- Backend/optimal_way/optimal_way.h | 6 +++ 2 files changed, 37 insertions(+), 26 deletions(-) diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp index 752ca8a..d351b2f 100644 --- a/Backend/optimal_way/optimal_way.cpp +++ b/Backend/optimal_way/optimal_way.cpp @@ -5,37 +5,42 @@ namespace math { +bool MinimumDistanceCalculator::TangentGoesTroughOtherCircle( + const LinearАunction& tangent, int circle1_index, int circle2_index) { + std::pair tangent_points = + CrossPoints(tangent, circles_[circle1_index], circles_[circle2_index]); + for (int l = 0; l < circles_.size(); ++l) + if (l != circle1_index && l != circle2_index) + if (AreThereIntersections(circles_[l], tangent_points.first, + tangent_points.second)) + return true; + return false; +} + +void MinimumDistanceCalculator::AddTangent(const LinearАunction& tangent, + CircleObstacle& circle1, + CircleObstacle& circle2) { + std::pair tangent_points = + CrossPoints(tangent, circle1, circle2); + tangent_points.first.another_tangent_point = + std::make_shared(tangent_points.second); + tangent_points.second.another_tangent_point = + std::make_shared(tangent_points.first); + circle1.AddTangentLine(tangent); + circle1.AddTangentPoint(tangent_points.first); + circle2.AddTangentLine(tangent); + circle2.AddTangentPoint(tangent_points.second); +} + void MinimumDistanceCalculator::FillTangentsCircles() { for (int i = 0; i < circles_.size(); ++i) { for (int j = i + 1; j < circles_.size(); ++j) { std::vector tangents = TangentsBetweenCircles(circles_[i], circles_[j]); - for (int k = 0; k < tangents.size(); ++k) { - bool is_exist = true; - for (int l = 0; l < circles_.size(); ++l) { - if (l != i && l != j) { - std::pair tangent_points = - CrossPoints(tangents[k], circles_[i], circles_[j]); - if (AreThereIntersections(circles_[l], tangent_points.first, - tangent_points.second)) { - is_exist = false; - break; - } - } - } - if (is_exist) { - std::pair tangent_points = - CrossPoints(tangents[k], circles_[i], circles_[j]); - tangent_points.first.another_tangent_point = - std::make_shared(tangent_points.second); - tangent_points.second.another_tangent_point = - std::make_shared(tangent_points.first); - circles_[i].AddTangentLine(tangents[k]); - circles_[i].AddTangentPoint(tangent_points.first); - circles_[j].AddTangentLine(tangents[k]); - circles_[j].AddTangentPoint(tangent_points.second); - } - } + + for (int k = 0; k < tangents.size(); ++k) + if (!TangentGoesTroughOtherCircle(tangents[k], i, j)) + AddTangent(tangents[k], circles_[i], circles_[j]); } } } diff --git a/Backend/optimal_way/optimal_way.h b/Backend/optimal_way/optimal_way.h index bb09d9c..1cc37fb 100644 --- a/Backend/optimal_way/optimal_way.h +++ b/Backend/optimal_way/optimal_way.h @@ -19,6 +19,12 @@ class MinimumDistanceCalculator { std::vector circles_; std::vector ways_; + bool TangentGoesTroughOtherCircle(const LinearАunction& tangent, + int circle1_index, int circle2_index); + + void AddTangent(const LinearАunction& tangent, CircleObstacle& circle1, + CircleObstacle& circle2); + // Заполняет вектор точек касательных для каждой окружности void FillTangentsCircles(); From 4d267605d25caa0505c4ebb1672dfe6cd1768986 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 22:51:26 +0300 Subject: [PATCH 10/42] Update structure --- Backend/optimal_way/pathgraph.cpp | 27 --------------------------- Backend/optimal_way/pathgraph.h | 22 +++++++++++++--------- 2 files changed, 13 insertions(+), 36 deletions(-) delete mode 100644 Backend/optimal_way/pathgraph.cpp diff --git a/Backend/optimal_way/pathgraph.cpp b/Backend/optimal_way/pathgraph.cpp deleted file mode 100644 index 9c8bade..0000000 --- a/Backend/optimal_way/pathgraph.cpp +++ /dev/null @@ -1,27 +0,0 @@ -#include "pathgraph.h" - -namespace math { - -PathGraph::PathGraph(std::vector obstacles, Point point1, - Point point2) { - for (auto& obstacle : obstacles) { - for (auto& point : obstacle.GetTangentPoints()) { - if (point.another_tangent_point) { - PathWayNode new_node{point}; - new_node.circle_prt = std::make_unique(obstacle); - for (auto& prev : graph_) { - if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { - prev.edges.push_back(std::make_shared(new_node)); - new_node.edges.push_back(std::make_shared(prev)); - } else if (prev.circle_prt && - (new_node.point == (*prev.point.another_tangent_point))) { - prev.edges.push_back(std::make_shared(new_node)); - new_node.edges.push_back(std::make_shared(prev)); - } - } - graph_.push_back(new_node); - } - } - } -} -} // namespace math diff --git a/Backend/optimal_way/pathgraph.h b/Backend/optimal_way/pathgraph.h index 9c20ba1..750835c 100644 --- a/Backend/optimal_way/pathgraph.h +++ b/Backend/optimal_way/pathgraph.h @@ -4,23 +4,27 @@ #include #include "circleobstacle.h" + namespace math { +struct Path; + struct PathWayNode { PathWayNode(Point p) : point{p} {} - std::vector> edges; + std::vector edges; std::shared_ptr circle_prt = nullptr; Point point; }; -class PathGraph { - public: - PathGraph(std::vector obstacles, Point point1, Point point2); - - private: - std::vector graph_; - - double FindTheShortestWay(); +struct Path { + Path(std::shared_ptr node_ptr, double length) + : next{node_ptr}, length{length} {} + std::shared_ptr next; + double length; }; +void ConnectTwoNodes(PathWayNode& node1, PathWayNode& node2, double distance) { + node1.edges.push_back({std::make_shared(node2), distance}); + node2.edges.push_back({std::make_shared(node1), distance}); +} } // namespace math From 55bdd6adc20c5e51fad84a9e9094b51404a51904 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 23:01:06 +0300 Subject: [PATCH 11/42] Rename files --- Backend/optimal_way/{circleobstacle.h => circle_obstacle.h} | 0 Backend/optimal_way/{pathgraph.h => path_graph.h} | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename Backend/optimal_way/{circleobstacle.h => circle_obstacle.h} (100%) rename Backend/optimal_way/{pathgraph.h => path_graph.h} (100%) diff --git a/Backend/optimal_way/circleobstacle.h b/Backend/optimal_way/circle_obstacle.h similarity index 100% rename from Backend/optimal_way/circleobstacle.h rename to Backend/optimal_way/circle_obstacle.h diff --git a/Backend/optimal_way/pathgraph.h b/Backend/optimal_way/path_graph.h similarity index 100% rename from Backend/optimal_way/pathgraph.h rename to Backend/optimal_way/path_graph.h From 1994bc8f00465849ae1e3c08faccd4c0c0cda4d6 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 23:22:41 +0300 Subject: [PATCH 12/42] Add Distance between points on circle --- Backend/optimal_way/helpers_functions.cpp | 8 ++++++++ Backend/optimal_way/helpers_functions.h | 7 +++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/Backend/optimal_way/helpers_functions.cpp b/Backend/optimal_way/helpers_functions.cpp index 177bee5..b265b76 100644 --- a/Backend/optimal_way/helpers_functions.cpp +++ b/Backend/optimal_way/helpers_functions.cpp @@ -13,6 +13,14 @@ double DistanceBetweenPoints(const Point& p1, const Point& p2) { return pow(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2), 0.5); } +double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, + const Point& p1, const Point& p2) { + double line = DistanceBetweenPoints(p1, p2); + double cos_alpha = (pow(line, 2) - 2 * pow(circle.GetRadius(), 2)) / + (2 * circle.GetRadius()); + return circle.GetRadius() * acos(cos_alpha); +} + std::pair CrossPoints(const LinearАunction& tangent, const CircleObstacle& circle1, const CircleObstacle& circle2) { diff --git a/Backend/optimal_way/helpers_functions.h b/Backend/optimal_way/helpers_functions.h index 4a5895b..aa38afe 100644 --- a/Backend/optimal_way/helpers_functions.h +++ b/Backend/optimal_way/helpers_functions.h @@ -1,8 +1,11 @@ #pragma once -#include "circleobstacle.h" +#include "circle_obstacle.h" namespace math { -double DistanceBetweenPoints(const Point& p1, const Point p2); +double DistanceBetweenPoints(const Point& p1, const Point& p2); + +double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, + const Point& p1, const Point& p2); LinearАunction MakeLinearАunction(const Point& point1, const Point& point2); From 83305e191c0dd39e3dd5a82bd15703ea07e9860d Mon Sep 17 00:00:00 2001 From: Romanov-Fedor Date: Fri, 12 Apr 2024 23:24:43 +0300 Subject: [PATCH 13/42] Add new function to construct graph --- Backend/optimal_way/optimal_way.cpp | 27 +++++++++++++++++++++++++-- Backend/optimal_way/optimal_way.h | 4 +++- Backend/optimal_way/path_graph.h | 2 +- 3 files changed, 29 insertions(+), 4 deletions(-) diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp index d351b2f..8b8aeb3 100644 --- a/Backend/optimal_way/optimal_way.cpp +++ b/Backend/optimal_way/optimal_way.cpp @@ -1,7 +1,7 @@ #include "optimal_way.h" #include "helpers_functions.h" -#include "pathgraph.h" +#include "path_graph.h" namespace math { @@ -68,11 +68,34 @@ void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { } } +void MinimumDistanceCalculator::FillPathNodes() { + std::vector graph_; + for (auto& obstacle : circles_) { + for (auto& point : obstacle.GetTangentPoints()) { + if (point.another_tangent_point) { + PathWayNode new_node{point}; + new_node.circle_prt = std::make_unique(obstacle); + for (auto& prev : graph_) { + if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { + ConnectTwoNodes(prev, new_node, + DistanceBetweenPointsOnCircle(obstacle, prev.point, + new_node.point)); + } else if (prev.circle_prt && + (new_node.point == (*prev.point.another_tangent_point))) { + ConnectTwoNodes(prev, new_node, + DistanceBetweenPoints(prev.point, new_node.point)); + } + } + graph_.push_back(new_node); + } + } + } +} + double MinimumDistanceCalculator::FindOptimalWay(const Point& pnt1, const Point& pnt2) { FillTangentsCircles(); FillTangentsPoints(point1_); FillTangentsPoints(point2_); - PathGraph optimal_way{circles_, point1_, point2_}; } } // namespace math diff --git a/Backend/optimal_way/optimal_way.h b/Backend/optimal_way/optimal_way.h index 1cc37fb..af209f9 100644 --- a/Backend/optimal_way/optimal_way.h +++ b/Backend/optimal_way/optimal_way.h @@ -2,7 +2,7 @@ #include -#include "circleobstacle.h" +#include "circle_obstacle.h" namespace math { @@ -30,6 +30,8 @@ class MinimumDistanceCalculator { void FillTangentsPoints(Point& point); + void FillPathNodes(); + double FindOptimalWay(const Point& pnt1, const Point& pnt2); }; } // namespace math diff --git a/Backend/optimal_way/path_graph.h b/Backend/optimal_way/path_graph.h index 750835c..a4b055e 100644 --- a/Backend/optimal_way/path_graph.h +++ b/Backend/optimal_way/path_graph.h @@ -3,7 +3,7 @@ #include #include -#include "circleobstacle.h" +#include "circle_obstacle.h" namespace math { From 1cb06e31eeb729644da33967367f9ea47cf64a5d Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 00:33:56 +0300 Subject: [PATCH 14/42] include fix --- Backend/CMakeLists.txt | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Backend/CMakeLists.txt b/Backend/CMakeLists.txt index eb9f543..6ba8df2 100644 --- a/Backend/CMakeLists.txt +++ b/Backend/CMakeLists.txt @@ -7,4 +7,7 @@ file(GLOB_RECURSE PROJECT_SOURCES "*.h" "*.cpp") add_library(backend STATIC ${PROJECT_SOURCES}) include(${CMAKESCRIPTS_DIR}/scripts_for_vscode.cmake) -add_qt_runtime(${CMAKE_CURRENT_SOURCE_DIR} backend) \ No newline at end of file +add_qt_runtime(${CMAKE_CURRENT_SOURCE_DIR} backend) + +find_package(IcecreamCpp) +include_directories(${IcecreamCpp_INCLUDE_DIRS}) From 1f8eedb34b80947aeb02c88bb24da20c9cf65292 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 00:35:33 +0300 Subject: [PATCH 15/42] embed Dijkstra's algorithm --- Backend/optimal_way/optimal_way.cpp | 2 +- Backend/optimal_way/path_graph.cpp | 41 +++++++++++++++++++++++ Backend/optimal_way/path_graph.h | 52 ++++++++++++++++++++++++++++- 3 files changed, 93 insertions(+), 2 deletions(-) create mode 100644 Backend/optimal_way/path_graph.cpp diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp index 8b8aeb3..072112a 100644 --- a/Backend/optimal_way/optimal_way.cpp +++ b/Backend/optimal_way/optimal_way.cpp @@ -73,7 +73,7 @@ void MinimumDistanceCalculator::FillPathNodes() { for (auto& obstacle : circles_) { for (auto& point : obstacle.GetTangentPoints()) { if (point.another_tangent_point) { - PathWayNode new_node{point}; + PathWayNode new_node{point, graph_.size()}; new_node.circle_prt = std::make_unique(obstacle); for (auto& prev : graph_) { if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { diff --git a/Backend/optimal_way/path_graph.cpp b/Backend/optimal_way/path_graph.cpp new file mode 100644 index 0000000..f0a741f --- /dev/null +++ b/Backend/optimal_way/path_graph.cpp @@ -0,0 +1,41 @@ +#include "path_graph.h" + +#include + +namespace math { + +void Dijkstras_algorithm::Calculate_Min_Path() { + while (graphs_vertex_[second_point_] > min_length_) { + IC(graphs_vertex_[second_point_]); + std::shared_ptr min_len_key; + for (auto& elem : graphs_vertex_) + if ((elem.second == min_length_) && (path_nodes_[elem.first].is_useful)) + min_len_key = std::make_shared(path_nodes_[elem.first]); + + for (auto& elem : (*min_len_key).edges) { + IC(elem.length); + if ((graphs_vertex_.find((*elem.next).number) == graphs_vertex_.end()) || + (elem.length + graphs_vertex_[(*min_len_key).number] < + graphs_vertex_[(*elem.next).number])) { + graphs_vertex_[(*elem.next).number] = + elem.length + graphs_vertex_[(*min_len_key).number]; + (*elem.next).is_useful = true; + } else { + (*elem.next).is_useful = false; + continue; + } + } + (*min_len_key).is_useful = false; + + min_length_ = inf; + for (auto& elem : graphs_vertex_) { + IC(elem.second); + if ((elem.second < min_length_) && (path_nodes_[elem.first].is_useful)) { + IC(elem.second); + min_length_ = elem.second; + } + } + } +} + +} // namespace math diff --git a/Backend/optimal_way/path_graph.h b/Backend/optimal_way/path_graph.h index a4b055e..fc19001 100644 --- a/Backend/optimal_way/path_graph.h +++ b/Backend/optimal_way/path_graph.h @@ -1,5 +1,6 @@ #pragma once +#include #include #include @@ -7,13 +8,17 @@ namespace math { +#define inf std::numeric_limits::infinity() + struct Path; struct PathWayNode { - PathWayNode(Point p) : point{p} {} + PathWayNode(Point p, std::size_t n) : point{p}, is_useful{true} {} std::vector edges; std::shared_ptr circle_prt = nullptr; Point point; + std::size_t number; + bool is_useful; }; struct Path { @@ -27,4 +32,49 @@ void ConnectTwoNodes(PathWayNode& node1, PathWayNode& node2, double distance) { node1.edges.push_back({std::make_shared(node2), distance}); node2.edges.push_back({std::make_shared(node1), distance}); } + +// @brief алгоритм Дейкстры +class Dijkstras_algorithm { + public: + /** + * @brief инициализирует новый экземпляр Dijkstras_algorithm + * @param start: начальная точка + * @param end: конечная точка + */ + Dijkstras_algorithm(std::vector nodes) + : path_nodes_{nodes}, + first_point_{nodes.size() - 2}, + second_point_{nodes.size() - 1}, + min_length_{0} { + Calculate_Min_Path(); + } + + // Возвращает длину кратчайшего пути + double Get_Min_Len() const { return min_length_; } + + // Возвращает последовательность точек для GUI + // Get_Min_Path(); + + private: + // Номер первой точки + std::size_t first_point_; + + // Номер второй точки + std::size_t second_point_; + + // Все вершины графа + std::vector path_nodes_; + + // Длина кратчайшего пути из start_ в end_ + double min_length_; + + // Кратчайшие найденные растояния до рассматриваемых вершин + std::map graphs_vertex_; + + /** + * @brief определяет длинукратчайшего пути из start_ в end_ + */ + void Calculate_Min_Path(); +}; + } // namespace math From 52e59902aeccf5f3f857fb0beeaa20b6c36d079d Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:02:07 +0300 Subject: [PATCH 16/42] Change comparing for points --- Backend/optimal_way/circle_obstacle.h | 2 +- lib/point.h | 7 ++++++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/Backend/optimal_way/circle_obstacle.h b/Backend/optimal_way/circle_obstacle.h index b9eec65..a8cab43 100644 --- a/Backend/optimal_way/circle_obstacle.h +++ b/Backend/optimal_way/circle_obstacle.h @@ -7,7 +7,7 @@ #include "../lib/point.h" namespace math { -constexpr double precision = 0.000001; +constexpr double precision = lib::precision; // Структура хранит коэфиценты для прямой вида ax+by+c=0 struct LinearАunction { diff --git a/lib/point.h b/lib/point.h index 1161781..4ae66dd 100644 --- a/lib/point.h +++ b/lib/point.h @@ -1,6 +1,9 @@ #pragma once +#include + namespace lib { +constexpr double precision = 0.000001; struct Point { double x; @@ -28,7 +31,9 @@ struct Point { inline Point operator+(Point a, Point b) { return a += b; } inline Point operator-(Point a, Point b) { return a -= b; } -inline bool operator==(Point a, Point b) { return a.x == b.x && a.y == b.y; } +inline bool operator==(Point a, Point b) { + return std::abs(a.x - b.x) < precision && std::abs(a.y - b.y) < precision; +} inline bool operator!=(Point a, Point b) { return !(a == b); } } // namespace lib From 678d084513b7f88de27a208c21094c40472f9725 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Sat, 13 Apr 2024 01:03:16 +0300 Subject: [PATCH 17/42] Add function to add main points to graph as node --- Backend/optimal_way/optimal_way.cpp | 47 ++++++++++++++++++----------- Backend/optimal_way/optimal_way.h | 8 +++-- 2 files changed, 35 insertions(+), 20 deletions(-) diff --git a/Backend/optimal_way/optimal_way.cpp b/Backend/optimal_way/optimal_way.cpp index 072112a..a3931f8 100644 --- a/Backend/optimal_way/optimal_way.cpp +++ b/Backend/optimal_way/optimal_way.cpp @@ -1,7 +1,6 @@ #include "optimal_way.h" #include "helpers_functions.h" -#include "path_graph.h" namespace math { @@ -62,34 +61,48 @@ void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { if (is_exist_tangent1) point.tangents.push_back( MakeLinearАunction(point, tangent_points_1.first)); + if (is_exist_tangent2) point.tangents.push_back( MakeLinearАunction(point, tangent_points_1.second)); } } -void MinimumDistanceCalculator::FillPathNodes() { - std::vector graph_; +void MinimumDistanceCalculator::FillPathNodesOnCircles() { for (auto& obstacle : circles_) { for (auto& point : obstacle.GetTangentPoints()) { - if (point.another_tangent_point) { - PathWayNode new_node{point, graph_.size()}; - new_node.circle_prt = std::make_unique(obstacle); - for (auto& prev : graph_) { - if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { - ConnectTwoNodes(prev, new_node, - DistanceBetweenPointsOnCircle(obstacle, prev.point, - new_node.point)); - } else if (prev.circle_prt && - (new_node.point == (*prev.point.another_tangent_point))) { - ConnectTwoNodes(prev, new_node, - DistanceBetweenPoints(prev.point, new_node.point)); - } + PathWayNode new_node{point, graph_.size()}; + new_node.circle_prt = std::make_unique(obstacle); + for (auto& prev : graph_) { + if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { + ConnectTwoNodes(prev, new_node, + DistanceBetweenPointsOnCircle(obstacle, prev.point, + new_node.point)); + } else if (prev.circle_prt && + (new_node.point == (*prev.point.another_tangent_point))) { + ConnectTwoNodes(prev, new_node, + DistanceBetweenPoints(prev.point, new_node.point)); } - graph_.push_back(new_node); + } + graph_.push_back(new_node); + } + } +} + +void MinimumDistanceCalculator::FillPathNodesOnPoint(const Point& point) { + PathWayNode new_node{point, graph_.size()}; + for (auto& prev : graph_) { + if (prev.circle_prt) { + std::pair tangent_points = + TangentPointsToCircle((*prev.circle_prt), point); + if (tangent_points.first == prev.point || + tangent_points.second == prev.point) { + ConnectTwoNodes(prev, new_node, + DistanceBetweenPoints(prev.point, new_node.point)); } } } + graph_.push_back(new_node); } double MinimumDistanceCalculator::FindOptimalWay(const Point& pnt1, diff --git a/Backend/optimal_way/optimal_way.h b/Backend/optimal_way/optimal_way.h index af209f9..c2a385a 100644 --- a/Backend/optimal_way/optimal_way.h +++ b/Backend/optimal_way/optimal_way.h @@ -2,7 +2,7 @@ #include -#include "circle_obstacle.h" +#include "path_graph.h" namespace math { @@ -17,7 +17,7 @@ class MinimumDistanceCalculator { Point point1_; Point point2_; std::vector circles_; - std::vector ways_; + std::vector graph_; bool TangentGoesTroughOtherCircle(const LinearАunction& tangent, int circle1_index, int circle2_index); @@ -30,7 +30,9 @@ class MinimumDistanceCalculator { void FillTangentsPoints(Point& point); - void FillPathNodes(); + void FillPathNodesOnCircles(); + + void FillPathNodesOnPoint(const Point& point); double FindOptimalWay(const Point& pnt1, const Point& pnt2); }; From f965dc6b04aa599bddaa21929727f4986e0bfead Mon Sep 17 00:00:00 2001 From: Dmitry Krivoruchko <144147209+UmbrellaLeaf5@users.noreply.github.com> Date: Sat, 13 Apr 2024 03:26:26 +0300 Subject: [PATCH 18/42] rename backend --- {Backend => backend}/CMakeLists.txt | 0 {Backend => backend}/adjacency_matrix.cpp | 0 {Backend => backend}/adjacency_matrix.h | 0 {Backend => backend}/optimal_way/circle_obstacle.h | 0 {Backend => backend}/optimal_way/helpers_functions.cpp | 0 {Backend => backend}/optimal_way/helpers_functions.h | 0 {Backend => backend}/optimal_way/optimal_way.cpp | 0 {Backend => backend}/optimal_way/optimal_way.h | 0 {Backend => backend}/optimal_way/path_graph.cpp | 0 {Backend => backend}/optimal_way/path_graph.h | 0 {Backend => backend}/travelling_salesmans_problem.cpp | 0 {Backend => backend}/travelling_salesmans_problem.h | 0 {Backend => backend}/tspgraph.h | 0 13 files changed, 0 insertions(+), 0 deletions(-) rename {Backend => backend}/CMakeLists.txt (100%) rename {Backend => backend}/adjacency_matrix.cpp (100%) rename {Backend => backend}/adjacency_matrix.h (100%) rename {Backend => backend}/optimal_way/circle_obstacle.h (100%) rename {Backend => backend}/optimal_way/helpers_functions.cpp (100%) rename {Backend => backend}/optimal_way/helpers_functions.h (100%) rename {Backend => backend}/optimal_way/optimal_way.cpp (100%) rename {Backend => backend}/optimal_way/optimal_way.h (100%) rename {Backend => backend}/optimal_way/path_graph.cpp (100%) rename {Backend => backend}/optimal_way/path_graph.h (100%) rename {Backend => backend}/travelling_salesmans_problem.cpp (100%) rename {Backend => backend}/travelling_salesmans_problem.h (100%) rename {Backend => backend}/tspgraph.h (100%) diff --git a/Backend/CMakeLists.txt b/backend/CMakeLists.txt similarity index 100% rename from Backend/CMakeLists.txt rename to backend/CMakeLists.txt diff --git a/Backend/adjacency_matrix.cpp b/backend/adjacency_matrix.cpp similarity index 100% rename from Backend/adjacency_matrix.cpp rename to backend/adjacency_matrix.cpp diff --git a/Backend/adjacency_matrix.h b/backend/adjacency_matrix.h similarity index 100% rename from Backend/adjacency_matrix.h rename to backend/adjacency_matrix.h diff --git a/Backend/optimal_way/circle_obstacle.h b/backend/optimal_way/circle_obstacle.h similarity index 100% rename from Backend/optimal_way/circle_obstacle.h rename to backend/optimal_way/circle_obstacle.h diff --git a/Backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp similarity index 100% rename from Backend/optimal_way/helpers_functions.cpp rename to backend/optimal_way/helpers_functions.cpp diff --git a/Backend/optimal_way/helpers_functions.h b/backend/optimal_way/helpers_functions.h similarity index 100% rename from Backend/optimal_way/helpers_functions.h rename to backend/optimal_way/helpers_functions.h diff --git a/Backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp similarity index 100% rename from Backend/optimal_way/optimal_way.cpp rename to backend/optimal_way/optimal_way.cpp diff --git a/Backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h similarity index 100% rename from Backend/optimal_way/optimal_way.h rename to backend/optimal_way/optimal_way.h diff --git a/Backend/optimal_way/path_graph.cpp b/backend/optimal_way/path_graph.cpp similarity index 100% rename from Backend/optimal_way/path_graph.cpp rename to backend/optimal_way/path_graph.cpp diff --git a/Backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h similarity index 100% rename from Backend/optimal_way/path_graph.h rename to backend/optimal_way/path_graph.h diff --git a/Backend/travelling_salesmans_problem.cpp b/backend/travelling_salesmans_problem.cpp similarity index 100% rename from Backend/travelling_salesmans_problem.cpp rename to backend/travelling_salesmans_problem.cpp diff --git a/Backend/travelling_salesmans_problem.h b/backend/travelling_salesmans_problem.h similarity index 100% rename from Backend/travelling_salesmans_problem.h rename to backend/travelling_salesmans_problem.h diff --git a/Backend/tspgraph.h b/backend/tspgraph.h similarity index 100% rename from Backend/tspgraph.h rename to backend/tspgraph.h From 1f7e334f9b443437944bb04ae663a7ce953bfeab Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 12:02:36 +0300 Subject: [PATCH 19/42] remove useless header --- tests/matrix_test.h | 1 - 1 file changed, 1 deletion(-) delete mode 100644 tests/matrix_test.h diff --git a/tests/matrix_test.h b/tests/matrix_test.h deleted file mode 100644 index 6f70f09..0000000 --- a/tests/matrix_test.h +++ /dev/null @@ -1 +0,0 @@ -#pragma once From 2aa335bba25bf9d5e935ce7ef6697a8ea4d7328b Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 12:02:54 +0300 Subject: [PATCH 20/42] slight struct changes --- backend/optimal_way/path_graph.cpp | 12 +++++------- backend/optimal_way/path_graph.h | 7 ++++--- 2 files changed, 9 insertions(+), 10 deletions(-) diff --git a/backend/optimal_way/path_graph.cpp b/backend/optimal_way/path_graph.cpp index f0a741f..5d465b2 100644 --- a/backend/optimal_way/path_graph.cpp +++ b/backend/optimal_way/path_graph.cpp @@ -9,7 +9,7 @@ void Dijkstras_algorithm::Calculate_Min_Path() { IC(graphs_vertex_[second_point_]); std::shared_ptr min_len_key; for (auto& elem : graphs_vertex_) - if ((elem.second == min_length_) && (path_nodes_[elem.first].is_useful)) + if ((elem.second == min_length_) && (!path_nodes_[elem.first].is_visited)) min_len_key = std::make_shared(path_nodes_[elem.first]); for (auto& elem : (*min_len_key).edges) { @@ -19,18 +19,16 @@ void Dijkstras_algorithm::Calculate_Min_Path() { graphs_vertex_[(*elem.next).number])) { graphs_vertex_[(*elem.next).number] = elem.length + graphs_vertex_[(*min_len_key).number]; - (*elem.next).is_useful = true; - } else { - (*elem.next).is_useful = false; + } else continue; - } } - (*min_len_key).is_useful = false; + (*min_len_key).is_visited = true; min_length_ = inf; for (auto& elem : graphs_vertex_) { IC(elem.second); - if ((elem.second < min_length_) && (path_nodes_[elem.first].is_useful)) { + if ((elem.second < min_length_) && + (!path_nodes_[elem.first].is_visited)) { IC(elem.second); min_length_ = elem.second; } diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index fc19001..fb7318c 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -13,12 +13,13 @@ namespace math { struct Path; struct PathWayNode { - PathWayNode(Point p, std::size_t n) : point{p}, is_useful{true} {} + PathWayNode(Point p, std::size_t n) + : point{p}, number{n}, is_visited{false} {} std::vector edges; std::shared_ptr circle_prt = nullptr; Point point; std::size_t number; - bool is_useful; + bool is_visited; }; struct Path { @@ -72,7 +73,7 @@ class Dijkstras_algorithm { std::map graphs_vertex_; /** - * @brief определяет длинукратчайшего пути из start_ в end_ + * @brief определяет длину кратчайшего пути из start_ в end_ */ void Calculate_Min_Path(); }; From 89a2de6ff9f3b638d4391ff021d7939664a7341a Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 15:02:20 +0300 Subject: [PATCH 21/42] Connect graph correctly --- backend/optimal_way/optimal_way.cpp | 40 +++++++++++----------- backend/optimal_way/optimal_way.h | 2 +- backend/optimal_way/path_graph.h | 51 ++++++++++++++++++----------- tests/CMakeLists.txt | 3 ++ 4 files changed, 56 insertions(+), 40 deletions(-) diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index a3931f8..7519ca4 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -71,38 +71,38 @@ void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { void MinimumDistanceCalculator::FillPathNodesOnCircles() { for (auto& obstacle : circles_) { for (auto& point : obstacle.GetTangentPoints()) { - PathWayNode new_node{point, graph_.size()}; + PathWayNode new_node{point, graph_.nodes.size()}; new_node.circle_prt = std::make_unique(obstacle); - for (auto& prev : graph_) { - if (prev.circle_prt && ((*prev.circle_prt) == obstacle)) { - ConnectTwoNodes(prev, new_node, - DistanceBetweenPointsOnCircle(obstacle, prev.point, - new_node.point)); - } else if (prev.circle_prt && - (new_node.point == (*prev.point.another_tangent_point))) { - ConnectTwoNodes(prev, new_node, - DistanceBetweenPoints(prev.point, new_node.point)); + for (auto& prev : graph_.nodes) { + if ((*prev).circle_prt && ((*(*prev).circle_prt) == obstacle)) { + graph_.AddEdge((*prev).number, new_node.number, + DistanceBetweenPointsOnCircle(obstacle, (*prev).point, + new_node.point)); + } else if ((*prev).circle_prt && + (new_node.point == (*(*prev).point.another_tangent_point))) { + graph_.AddEdge((*prev).number, new_node.number, + DistanceBetweenPoints((*prev).point, new_node.point)); } } - graph_.push_back(new_node); + graph_.nodes.push_back(std::make_shared(new_node)); } } } void MinimumDistanceCalculator::FillPathNodesOnPoint(const Point& point) { - PathWayNode new_node{point, graph_.size()}; - for (auto& prev : graph_) { - if (prev.circle_prt) { + PathWayNode new_node{point, graph_.nodes.size()}; + for (auto& prev : graph_.nodes) { + if ((*prev).circle_prt) { std::pair tangent_points = - TangentPointsToCircle((*prev.circle_prt), point); - if (tangent_points.first == prev.point || - tangent_points.second == prev.point) { - ConnectTwoNodes(prev, new_node, - DistanceBetweenPoints(prev.point, new_node.point)); + TangentPointsToCircle((*(*prev).circle_prt), point); + if (tangent_points.first == (*prev).point || + tangent_points.second == (*prev).point) { + graph_.AddEdge((*prev).number, new_node.number, + DistanceBetweenPoints((*prev).point, new_node.point)); } } } - graph_.push_back(new_node); + graph_.nodes.push_back(std::make_shared(new_node)); } double MinimumDistanceCalculator::FindOptimalWay(const Point& pnt1, diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index c2a385a..669a4fd 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -17,7 +17,7 @@ class MinimumDistanceCalculator { Point point1_; Point point2_; std::vector circles_; - std::vector graph_; + PathWayGraph graph_; bool TangentGoesTroughOtherCircle(const LinearАunction& tangent, int circle1_index, int circle2_index); diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index fb7318c..8d02259 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -10,31 +10,42 @@ namespace math { #define inf std::numeric_limits::infinity() -struct Path; - struct PathWayNode { PathWayNode(Point p, std::size_t n) : point{p}, number{n}, is_visited{false} {} - std::vector edges; + std::vector> edges; + std::vector edges_lens; std::shared_ptr circle_prt = nullptr; Point point; std::size_t number; bool is_visited; }; -struct Path { - Path(std::shared_ptr node_ptr, double length) - : next{node_ptr}, length{length} {} - std::shared_ptr next; - double length; -}; +struct PathWayGraph { + std::vector> nodes; + + void AddNode(std::shared_ptr new_node) { + nodes.push_back(new_node); + } -void ConnectTwoNodes(PathWayNode& node1, PathWayNode& node2, double distance) { - node1.edges.push_back({std::make_shared(node2), distance}); - node2.edges.push_back({std::make_shared(node1), distance}); -} + void AddEdge(std::size_t node_1, std::size_t node_2, double length) { + std::shared_ptr node_ptr1, node_ptr2; + + for (auto node : nodes) { + if (node->number == node_1) + node_ptr1 = node; + else if (node->number == node_2) + node_ptr2 = node; + } + + node_ptr1->edges.push_back(node_ptr2); + node_ptr1->edges_lens.push_back(length); + node_ptr2->edges.push_back(node_ptr1); + node_ptr2->edges_lens.push_back(length); + } +}; -// @brief алгоритм Дейкстры +/// @brief алгоритм Дейкстры class Dijkstras_algorithm { public: /** @@ -42,11 +53,13 @@ class Dijkstras_algorithm { * @param start: начальная точка * @param end: конечная точка */ - Dijkstras_algorithm(std::vector nodes) - : path_nodes_{nodes}, - first_point_{nodes.size() - 2}, - second_point_{nodes.size() - 1}, + Dijkstras_algorithm(PathWayGraph graph) + : path_nodes_{graph.nodes}, + first_point_{graph.nodes.size() - 2}, + second_point_{graph.nodes.size() - 1}, min_length_{0} { + graphs_vertex_[first_point_] = 0; + graphs_vertex_[second_point_] = inf; Calculate_Min_Path(); } @@ -64,7 +77,7 @@ class Dijkstras_algorithm { std::size_t second_point_; // Все вершины графа - std::vector path_nodes_; + std::vector> path_nodes_; // Длина кратчайшего пути из start_ в end_ double min_length_; diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt index b446fc1..aa56b9e 100644 --- a/tests/CMakeLists.txt +++ b/tests/CMakeLists.txt @@ -53,3 +53,6 @@ add_qt_runtime(${CMAKE_CURRENT_SOURCE_DIR} tests) if(QT_VERSION_MAJOR EQUAL 6) qt_finalize_executable(tests) endif() + +find_package(IcecreamCpp) +include_directories(${IcecreamCpp_INCLUDE_DIRS}) From d4c0c20430620e1d15d16b1edfc8f8643a49f5ff Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 15:34:58 +0300 Subject: [PATCH 22/42] fixed dijkstras algorithm due to new arhitecture --- backend/optimal_way/path_graph.cpp | 35 +++++++++++++----------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/backend/optimal_way/path_graph.cpp b/backend/optimal_way/path_graph.cpp index 5d465b2..408157d 100644 --- a/backend/optimal_way/path_graph.cpp +++ b/backend/optimal_way/path_graph.cpp @@ -1,38 +1,33 @@ #include "path_graph.h" -#include - namespace math { void Dijkstras_algorithm::Calculate_Min_Path() { while (graphs_vertex_[second_point_] > min_length_) { - IC(graphs_vertex_[second_point_]); std::shared_ptr min_len_key; for (auto& elem : graphs_vertex_) - if ((elem.second == min_length_) && (!path_nodes_[elem.first].is_visited)) - min_len_key = std::make_shared(path_nodes_[elem.first]); + if ((elem.second == min_length_) && + (!(*path_nodes_[elem.first]).is_visited)) + min_len_key = path_nodes_[elem.first]; - for (auto& elem : (*min_len_key).edges) { - IC(elem.length); - if ((graphs_vertex_.find((*elem.next).number) == graphs_vertex_.end()) || - (elem.length + graphs_vertex_[(*min_len_key).number] < - graphs_vertex_[(*elem.next).number])) { - graphs_vertex_[(*elem.next).number] = - elem.length + graphs_vertex_[(*min_len_key).number]; - } else + for (std::size_t i = 0; i < (*min_len_key).edges.size(); ++i) + if ((graphs_vertex_.find((*(*min_len_key).edges[i]).number) == + graphs_vertex_.end()) || + (graphs_vertex_[(*(*min_len_key).edges[i]).number] > + graphs_vertex_[(*min_len_key).number] + + (*min_len_key).edges_lens[i])) + graphs_vertex_[(*(*min_len_key).edges[i]).number] = + graphs_vertex_[(*min_len_key).number] + + (*min_len_key).edges_lens[i]; + else continue; - } (*min_len_key).is_visited = true; min_length_ = inf; - for (auto& elem : graphs_vertex_) { - IC(elem.second); + for (auto& elem : graphs_vertex_) if ((elem.second < min_length_) && - (!path_nodes_[elem.first].is_visited)) { - IC(elem.second); + (!(*path_nodes_[elem.first]).is_visited)) min_length_ = elem.second; - } - } } } From e3363cfdc90188ccf7ccaab86414f3c3f63b5c5a Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 15:35:33 +0300 Subject: [PATCH 23/42] add dijkstras tests --- tests/dijkstra_test.cpp | 60 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) create mode 100644 tests/dijkstra_test.cpp diff --git a/tests/dijkstra_test.cpp b/tests/dijkstra_test.cpp new file mode 100644 index 0000000..84534f8 --- /dev/null +++ b/tests/dijkstra_test.cpp @@ -0,0 +1,60 @@ +#include +#include +#include + +#include "../backend/optimal_way/path_graph.h" + +// #include "qcustomplot.h" + +#if !defined(WIN32) +#define BOOST_TEST_DYN_LINK +#endif +#include + +namespace tt = boost::test_tools; +namespace utf = boost::unit_test; +using namespace math; + +void CreateNodes(PathWayGraph& graph, std::size_t number_of_nodes) { + for (std::size_t i = 0; i < number_of_nodes; ++i) + graph.nodes.push_back(std::make_shared(Point(0, 0), i)); +} + +BOOST_AUTO_TEST_SUITE(tests) + +BOOST_AUTO_TEST_CASE(test_1) { + PathWayGraph graph; + CreateNodes(graph, 9); + graph.AddEdge(0, 5, 7); + graph.AddEdge(0, 6, 9); + graph.AddEdge(0, 7, 27); + graph.AddEdge(1, 2, 15); + graph.AddEdge(1, 3, 17); + graph.AddEdge(1, 6, 11); + graph.AddEdge(2, 3, 21); + graph.AddEdge(2, 7, 15); + graph.AddEdge(3, 8, 32); + graph.AddEdge(4, 5, 10); + graph.AddEdge(4, 6, 8); + graph.AddEdge(4, 8, 31); + double ans = 68; + Dijkstras_algorithm da(graph); + BOOST_TEST(da.Get_Min_Len() == ans); +} + +BOOST_AUTO_TEST_CASE(test_2) { + PathWayGraph graph; + CreateNodes(graph, 5); + graph.AddEdge(0, 1, 63); + graph.AddEdge(0, 2, 91); + graph.AddEdge(0, 3, 40); + graph.AddEdge(1, 2, 84); + graph.AddEdge(1, 4, 52); + graph.AddEdge(2, 3, 32); + graph.AddEdge(2, 4, 56); + double ans = 88; + Dijkstras_algorithm da(graph); + BOOST_TEST(da.Get_Min_Len() == ans); +} + +BOOST_AUTO_TEST_SUITE_END() From 1bae80d364c94c9195bf2beac6b5b0b5d1bee6ef Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:01:34 +0300 Subject: [PATCH 24/42] =?UTF-8?q?Renaming=20Linear=D0=90unction=20to=20Lin?= =?UTF-8?q?earFunction?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- backend/optimal_way/circle_obstacle.h | 14 +++++++------- backend/optimal_way/helpers_functions.cpp | 12 ++++++------ backend/optimal_way/helpers_functions.h | 6 +++--- backend/optimal_way/optimal_way.cpp | 10 +++++----- backend/optimal_way/optimal_way.h | 4 ++-- 5 files changed, 23 insertions(+), 23 deletions(-) diff --git a/backend/optimal_way/circle_obstacle.h b/backend/optimal_way/circle_obstacle.h index a8cab43..5222955 100644 --- a/backend/optimal_way/circle_obstacle.h +++ b/backend/optimal_way/circle_obstacle.h @@ -10,11 +10,11 @@ namespace math { constexpr double precision = lib::precision; // Структура хранит коэфиценты для прямой вида ax+by+c=0 -struct LinearАunction { - LinearАunction(double a, double b, double c) +struct LinearFunction { + LinearFunction(double a, double b, double c) : a_coef{a}, b_coef{b}, c_coef{c} {} double a_coef, b_coef, c_coef; - bool operator==(const LinearАunction& other) { + bool operator==(const LinearFunction& other) { return (std::abs(a_coef - other.a_coef) < precision && std::abs(b_coef - other.b_coef) < precision && std::abs(c_coef - other.c_coef) < precision); @@ -23,7 +23,7 @@ struct LinearАunction { struct Point : public lib::Point { Point(double xx, double yy) : lib::Point{xx, yy} {} - std::vector tangents; + std::vector tangents; std::shared_ptr another_tangent_point = nullptr; }; @@ -35,12 +35,12 @@ class CircleObstacle { Point GetCenter() const { return center_; } double GetRadius() const { return radius_; } - std::vector GetTangentLines() { return tangents_; } + std::vector GetTangentLines() { return tangents_; } std::vector GetTangentPoints() { return tangent_points_; } void SetCenter(const Point& center) { center_ = center; } void SetRadius(double r) { radius_ = r; } - void AddTangentLine(const LinearАunction& tangent) { + void AddTangentLine(const LinearFunction& tangent) { tangents_.push_back(tangent); } void AddTangentPoint(const Point& tangent_point) { @@ -58,7 +58,7 @@ class CircleObstacle { private: Point center_; double radius_; - std::vector tangents_; + std::vector tangents_; std::vector tangent_points_; }; } // namespace math diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index b265b76..8e8ebea 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -3,10 +3,10 @@ #include namespace math { -LinearАunction MakeLinearАunction(const Point& point1, const Point& point2) { +LinearFunction MakeLinearFunction(const Point& point1, const Point& point2) { double slope = (point2.y - point1.y) / (point2.x - point1.x); double b_coef = point1.y - slope * point1.x; - return LinearАunction{slope, -1, b_coef}; + return LinearFunction{slope, -1, b_coef}; } double DistanceBetweenPoints(const Point& p1, const Point& p2) { @@ -21,7 +21,7 @@ double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, return circle.GetRadius() * acos(cos_alpha); } -std::pair CrossPoints(const LinearАunction& tangent, +std::pair CrossPoints(const LinearFunction& tangent, const CircleObstacle& circle1, const CircleObstacle& circle2) { double a = tangent.a_coef; @@ -64,9 +64,9 @@ std::pair TangentPointsToCircle(const CircleObstacle& crcl, {x2_cross_pnt, y2_cross_pnt}}; } -std::vector TangentsBetweenCircles( +std::vector TangentsBetweenCircles( const CircleObstacle& circle1, const CircleObstacle& circle2) { - std::vector tangents; + std::vector tangents; double x_1 = circle2.GetCenter().x; double y_1 = circle2.GetCenter().y; double r_1 = circle2.GetRadius(); @@ -82,7 +82,7 @@ std::vector TangentsBetweenCircles( (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2)); double a = ((r_1 - r_0) - b * (y_1 - y_0)) / (x_1 - x_0); double c = r_0 - a * x_0 - b * y_0; - LinearАunction tangent{a, b, c}; + LinearFunction tangent{a, b, c}; return tangent; }; diff --git a/backend/optimal_way/helpers_functions.h b/backend/optimal_way/helpers_functions.h index aa38afe..f6de97e 100644 --- a/backend/optimal_way/helpers_functions.h +++ b/backend/optimal_way/helpers_functions.h @@ -7,17 +7,17 @@ double DistanceBetweenPoints(const Point& p1, const Point& p2); double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, const Point& p1, const Point& p2); -LinearАunction MakeLinearАunction(const Point& point1, const Point& point2); +LinearFunction MakeLinearFunction(const Point& point1, const Point& point2); // Точки касания прямой к окружснотям -std::pair CrossPoints(const LinearАunction& tangent, +std::pair CrossPoints(const LinearFunction& tangent, const CircleObstacle& circle1, const CircleObstacle& circle2); std::pair TangentPointsToCircle(const CircleObstacle& crcl, const Point& point); -std::vector TangentsBetweenCircles( +std::vector TangentsBetweenCircles( const CircleObstacle& circle1, const CircleObstacle& circle2); // Пересекает ли отрезок, проведенный через две точки, окружность diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index 7519ca4..c31e2b0 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -5,7 +5,7 @@ namespace math { bool MinimumDistanceCalculator::TangentGoesTroughOtherCircle( - const LinearАunction& tangent, int circle1_index, int circle2_index) { + const LinearFunction& tangent, int circle1_index, int circle2_index) { std::pair tangent_points = CrossPoints(tangent, circles_[circle1_index], circles_[circle2_index]); for (int l = 0; l < circles_.size(); ++l) @@ -16,7 +16,7 @@ bool MinimumDistanceCalculator::TangentGoesTroughOtherCircle( return false; } -void MinimumDistanceCalculator::AddTangent(const LinearАunction& tangent, +void MinimumDistanceCalculator::AddTangent(const LinearFunction& tangent, CircleObstacle& circle1, CircleObstacle& circle2) { std::pair tangent_points = @@ -34,7 +34,7 @@ void MinimumDistanceCalculator::AddTangent(const LinearАunction& tangent, void MinimumDistanceCalculator::FillTangentsCircles() { for (int i = 0; i < circles_.size(); ++i) { for (int j = i + 1; j < circles_.size(); ++j) { - std::vector tangents = + std::vector tangents = TangentsBetweenCircles(circles_[i], circles_[j]); for (int k = 0; k < tangents.size(); ++k) @@ -60,11 +60,11 @@ void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { } if (is_exist_tangent1) point.tangents.push_back( - MakeLinearАunction(point, tangent_points_1.first)); + MakeLinearFunction(point, tangent_points_1.first)); if (is_exist_tangent2) point.tangents.push_back( - MakeLinearАunction(point, tangent_points_1.second)); + MakeLinearFunction(point, tangent_points_1.second)); } } diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index 669a4fd..b6f9737 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -19,10 +19,10 @@ class MinimumDistanceCalculator { std::vector circles_; PathWayGraph graph_; - bool TangentGoesTroughOtherCircle(const LinearАunction& tangent, + bool TangentGoesTroughOtherCircle(const LinearFunction& tangent, int circle1_index, int circle2_index); - void AddTangent(const LinearАunction& tangent, CircleObstacle& circle1, + void AddTangent(const LinearFunction& tangent, CircleObstacle& circle1, CircleObstacle& circle2); // Заполняет вектор точек касательных для каждой окружности From 73baa55f54b9f5247d804f65e401dad55ac8931d Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sat, 13 Apr 2024 18:13:52 +0300 Subject: [PATCH 25/42] Add comments --- backend/optimal_way/path_graph.h | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index 8d02259..72cac99 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -10,24 +10,46 @@ namespace math { #define inf std::numeric_limits::infinity() +/// @brief Вершина графа struct PathWayNode { + /** + * @brief PathWayNode + * @param p координаты + * @param n номер вершины + */ PathWayNode(Point p, std::size_t n) : point{p}, number{n}, is_visited{false} {} + + // Ребра данной вершины std::vector> edges; + + // Длины ребер std::vector edges_lens; + std::shared_ptr circle_prt = nullptr; + + // Координаты вершины Point point; + + // Номер вершины std::size_t number; + + // Была ли уже посещена вершина + // в алгоритме Дейкстры bool is_visited; }; +/// @brief Граф вершин между контрольными точками struct PathWayGraph { + // Вершины графа std::vector> nodes; + // Добавить новую вершину void AddNode(std::shared_ptr new_node) { nodes.push_back(new_node); } + // Добавить новое ребро void AddEdge(std::size_t node_1, std::size_t node_2, double length) { std::shared_ptr node_ptr1, node_ptr2; From b4c49efd7fef077e02f638ae2d9755059e36553f Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 08:49:39 +0300 Subject: [PATCH 26/42] change test style --- tests/dijkstra_test.cpp | 73 +++++++++++++++++++++++++---------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/tests/dijkstra_test.cpp b/tests/dijkstra_test.cpp index 84534f8..12cf19f 100644 --- a/tests/dijkstra_test.cpp +++ b/tests/dijkstra_test.cpp @@ -15,46 +15,61 @@ namespace tt = boost::test_tools; namespace utf = boost::unit_test; using namespace math; -void CreateNodes(PathWayGraph& graph, std::size_t number_of_nodes) { +struct TestEdge { + std::size_t node_1; + std::size_t node_2; + double length; +}; + +void AddNodes(PathWayGraph& graph, std::size_t number_of_nodes) { for (std::size_t i = 0; i < number_of_nodes; ++i) - graph.nodes.push_back(std::make_shared(Point(0, 0), i)); + graph.AddNode(std::make_shared(Point(0, 0), i)); +} + +void CHECK_GRAPH(std::vector edges, double ans) { + PathWayGraph graph; + + std::size_t number_of_nodes = 0; + for (auto& edge : edges) + number_of_nodes = + std::max(number_of_nodes, std::max(edge.node_1, edge.node_2) + 1); + AddNodes(graph, number_of_nodes); + + for (auto& edge : edges) graph.AddEdge(edge.node_1, edge.node_2, edge.length); + + Dijkstras_algorithm da(graph); + BOOST_TEST(da.Get_Min_Len() == ans); } BOOST_AUTO_TEST_SUITE(tests) BOOST_AUTO_TEST_CASE(test_1) { - PathWayGraph graph; - CreateNodes(graph, 9); - graph.AddEdge(0, 5, 7); - graph.AddEdge(0, 6, 9); - graph.AddEdge(0, 7, 27); - graph.AddEdge(1, 2, 15); - graph.AddEdge(1, 3, 17); - graph.AddEdge(1, 6, 11); - graph.AddEdge(2, 3, 21); - graph.AddEdge(2, 7, 15); - graph.AddEdge(3, 8, 32); - graph.AddEdge(4, 5, 10); - graph.AddEdge(4, 6, 8); - graph.AddEdge(4, 8, 31); + std::vector edges({{0, 5, 7}, + {0, 6, 9}, + {0, 7, 27}, + {1, 2, 15}, + {1, 3, 17}, + {1, 6, 11}, + {2, 3, 21}, + {2, 7, 15}, + {3, 8, 32}, + {4, 5, 10}, + {4, 6, 8}, + {4, 8, 31}}); double ans = 68; - Dijkstras_algorithm da(graph); - BOOST_TEST(da.Get_Min_Len() == ans); + CHECK_GRAPH(edges, ans); } BOOST_AUTO_TEST_CASE(test_2) { - PathWayGraph graph; - CreateNodes(graph, 5); - graph.AddEdge(0, 1, 63); - graph.AddEdge(0, 2, 91); - graph.AddEdge(0, 3, 40); - graph.AddEdge(1, 2, 84); - graph.AddEdge(1, 4, 52); - graph.AddEdge(2, 3, 32); - graph.AddEdge(2, 4, 56); + std::vector edges({{0, 1, 63}, + {0, 2, 91}, + {0, 3, 40}, + {1, 2, 84}, + {1, 4, 52}, + {2, 3, 32}, + {2, 4, 56}}); double ans = 88; - Dijkstras_algorithm da(graph); - BOOST_TEST(da.Get_Min_Len() == ans); + CHECK_GRAPH(edges, ans); } BOOST_AUTO_TEST_SUITE_END() From d10761de587bb27fd3ddf3f00de1baa89c116125 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 22:52:19 +0300 Subject: [PATCH 27/42] add dijkstra tests --- tests/dijkstra_test.cpp | 59 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 57 insertions(+), 2 deletions(-) diff --git a/tests/dijkstra_test.cpp b/tests/dijkstra_test.cpp index 12cf19f..965113e 100644 --- a/tests/dijkstra_test.cpp +++ b/tests/dijkstra_test.cpp @@ -43,7 +43,7 @@ void CHECK_GRAPH(std::vector edges, double ans) { BOOST_AUTO_TEST_SUITE(tests) -BOOST_AUTO_TEST_CASE(test_1) { +BOOST_AUTO_TEST_CASE(graph_) { std::vector edges({{0, 5, 7}, {0, 6, 9}, {0, 7, 27}, @@ -60,7 +60,7 @@ BOOST_AUTO_TEST_CASE(test_1) { CHECK_GRAPH(edges, ans); } -BOOST_AUTO_TEST_CASE(test_2) { +BOOST_AUTO_TEST_CASE(graph_1) { std::vector edges({{0, 1, 63}, {0, 2, 91}, {0, 3, 40}, @@ -72,4 +72,59 @@ BOOST_AUTO_TEST_CASE(test_2) { CHECK_GRAPH(edges, ans); } +BOOST_AUTO_TEST_CASE(graph_2) { + std::vector edges({{0, 1, 98}, + {0, 3, 84}, + {0, 4, 84}, + {0, 5, 85}, + {1, 4, 38}, + {1, 5, 18}, + {2, 3, 43}, + {2, 4, 35}, + {2, 5, 69}, + {3, 4, 66}}); + double ans = 56; + CHECK_GRAPH(edges, ans); +} + +BOOST_AUTO_TEST_CASE(graph_3) { + std::vector edges({{0, 1, 51}, + {0, 2, 259}, + {0, 4, 215}, + {0, 5, 84}, + {0, 6, 24}, + {1, 2, 45}, + {1, 6, 90}, + {2, 3, 287}, + {2, 4, 27}, + {2, 5, 97}, + {2, 6, 214}, + {3, 5, 160}, + {3, 6, 170}, + {4, 5, 93}}); + double ans = 108; + CHECK_GRAPH(edges, ans); +} + +BOOST_AUTO_TEST_CASE(graph_4) { + std::vector edges( + {{0, 1, 454}, {0, 2, 308}, {0, 3, 417}, {0, 5, 329}, {0, 6, 171}, + {0, 7, 477}, {1, 3, 372}, {1, 4, 303}, {1, 5, 186}, {1, 7, 480}, + {2, 3, 37}, {2, 4, 315}, {2, 5, 57}, {2, 7, 360}, {3, 4, 478}, + {3, 6, 139}, {4, 5, 276}, {4, 6, 230}, {4, 7, 353}, {5, 6, 429}}); + double ans = 536; + CHECK_GRAPH(edges, ans); +} + +BOOST_AUTO_TEST_CASE(graph_5) { + std::vector edges( + {{0, 1, 444}, {0, 2, 289}, {0, 4, 182}, {0, 7, 124}, {0, 9, 293}, + {1, 2, 272}, {1, 4, 371}, {1, 6, 253}, {1, 7, 243}, {1, 8, 215}, + {1, 9, 202}, {2, 3, 465}, {2, 4, 255}, {2, 6, 84}, {2, 7, 49}, + {2, 9, 171}, {3, 4, 234}, {3, 5, 154}, {3, 6, 49}, {3, 7, 374}, + {3, 8, 41}, {3, 9, 422}, {4, 9, 424}, {5, 7, 361}, {6, 8, 148}}); + double ans = 345; + CHECK_GRAPH(edges, ans); +} + BOOST_AUTO_TEST_SUITE_END() From efb0b19497d700713053a34c2b77025cb632e2d4 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 22:58:40 +0300 Subject: [PATCH 28/42] rename test suite --- tests/dijkstra_test.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/dijkstra_test.cpp b/tests/dijkstra_test.cpp index 965113e..ad63ede 100644 --- a/tests/dijkstra_test.cpp +++ b/tests/dijkstra_test.cpp @@ -41,7 +41,7 @@ void CHECK_GRAPH(std::vector edges, double ans) { BOOST_TEST(da.Get_Min_Len() == ans); } -BOOST_AUTO_TEST_SUITE(tests) +BOOST_AUTO_TEST_SUITE(dijkstras_tests) BOOST_AUTO_TEST_CASE(graph_) { std::vector edges({{0, 5, 7}, From 6ee3a9e31e5f271f0f11d17ec23ab2e6247d0e22 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 23:49:57 +0300 Subject: [PATCH 29/42] add algorithm which finds optimal path add Get_Min_Path() method which returns optimal path --- backend/optimal_way/path_graph.cpp | 17 +++++++++++++++++ backend/optimal_way/path_graph.h | 7 +++++-- 2 files changed, 22 insertions(+), 2 deletions(-) diff --git a/backend/optimal_way/path_graph.cpp b/backend/optimal_way/path_graph.cpp index 408157d..8bcd4b7 100644 --- a/backend/optimal_way/path_graph.cpp +++ b/backend/optimal_way/path_graph.cpp @@ -1,5 +1,7 @@ #include "path_graph.h" +#include + namespace math { void Dijkstras_algorithm::Calculate_Min_Path() { @@ -29,6 +31,21 @@ void Dijkstras_algorithm::Calculate_Min_Path() { (!(*path_nodes_[elem.first]).is_visited)) min_length_ = elem.second; } + + // Определение маршрута по длинам, сохранившимся в graphs_vertex_ + std::size_t end = second_point_; + min_path_.push_back(end); + while (end != first_point_) { + for (std::size_t i = 0; i < (*path_nodes_[end]).edges.size(); ++i) + if (graphs_vertex_[(*path_nodes_[end]).number] == + graphs_vertex_[(*(*path_nodes_[end]).edges[i]).number] + + (*path_nodes_[end]).edges_lens[i]) { + end = (*(*path_nodes_[end]).edges[i]).number; + min_path_.push_back(end); + break; + } + } + std::reverse(min_path_.begin(), min_path_.end()); } } // namespace math diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index 72cac99..34c3944 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -88,8 +88,8 @@ class Dijkstras_algorithm { // Возвращает длину кратчайшего пути double Get_Min_Len() const { return min_length_; } - // Возвращает последовательность точек для GUI - // Get_Min_Path(); + // Возвращает кратчайший путь + std::vector Get_Min_Path() const { return min_path_; } private: // Номер первой точки @@ -104,6 +104,9 @@ class Dijkstras_algorithm { // Длина кратчайшего пути из start_ в end_ double min_length_; + // Кратчайший маршрут из start_ в end_ + std::vector min_path_; + // Кратчайшие найденные растояния до рассматриваемых вершин std::map graphs_vertex_; From b408bfc184366cc5fcb5222a48579d798f9e7d62 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 23:51:50 +0300 Subject: [PATCH 30/42] delete useless includes in test files --- tests/dijkstra_test.cpp | 6 ------ tests/matrix_test.cpp | 3 --- 2 files changed, 9 deletions(-) diff --git a/tests/dijkstra_test.cpp b/tests/dijkstra_test.cpp index ad63ede..ebca8c1 100644 --- a/tests/dijkstra_test.cpp +++ b/tests/dijkstra_test.cpp @@ -1,11 +1,5 @@ -#include -#include -#include - #include "../backend/optimal_way/path_graph.h" -// #include "qcustomplot.h" - #if !defined(WIN32) #define BOOST_TEST_DYN_LINK #endif diff --git a/tests/matrix_test.cpp b/tests/matrix_test.cpp index 9907435..8818cf8 100644 --- a/tests/matrix_test.cpp +++ b/tests/matrix_test.cpp @@ -1,10 +1,7 @@ -#include #include #include "../Backend/adjacency_matrix.h" -// #include "qcustomplot.h" - #if !defined(WIN32) #define BOOST_TEST_DYN_LINK #endif From c23a16eb1de10cdbac3c1c48cd72786eaf118ec0 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Sun, 14 Apr 2024 23:55:07 +0300 Subject: [PATCH 31/42] complete FindOptimalWay() method --- backend/optimal_way/optimal_way.cpp | 6 ++++-- backend/optimal_way/optimal_way.h | 2 +- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index c31e2b0..63cbcdf 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -105,10 +105,12 @@ void MinimumDistanceCalculator::FillPathNodesOnPoint(const Point& point) { graph_.nodes.push_back(std::make_shared(new_node)); } -double MinimumDistanceCalculator::FindOptimalWay(const Point& pnt1, - const Point& pnt2) { +std::vector MinimumDistanceCalculator::FindOptimalWay() { FillTangentsCircles(); FillTangentsPoints(point1_); FillTangentsPoints(point2_); + Dijkstras_algorithm da(graph_); + return da.Get_Min_Path(); } + } // namespace math diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index b6f9737..07cb402 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -34,6 +34,6 @@ class MinimumDistanceCalculator { void FillPathNodesOnPoint(const Point& point); - double FindOptimalWay(const Point& pnt1, const Point& pnt2); + std::vector FindOptimalWay(); }; } // namespace math From 5a01ce55c70cd86e08b723833891e3c61373ca18 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 14:00:21 +0300 Subject: [PATCH 32/42] Add empty lines in between class members and methods --- backend/adjacency_matrix.h | 6 ++++++ backend/optimal_way/circle_obstacle.h | 17 +++++++++++++++++ backend/optimal_way/helpers_functions.cpp | 2 ++ backend/optimal_way/helpers_functions.h | 3 ++- backend/optimal_way/optimal_way.h | 5 +++++ 5 files changed, 32 insertions(+), 1 deletion(-) diff --git a/backend/adjacency_matrix.h b/backend/adjacency_matrix.h index 01f37c4..4067081 100644 --- a/backend/adjacency_matrix.h +++ b/backend/adjacency_matrix.h @@ -62,16 +62,22 @@ class AdjacencyMatrix { private: // Размер матрицы std::size_t size_; + // Матрица std::vector> matrix_; + // Редуцированная версия матрицы std::vector> reducted_matrix_; + // Минимальный элемент в каждой строке и в каждом столбце std::vector min_numbers_; + // Оценка пути для данной матрицы double evaluation_ = 0; + // Ребро, которое выбирается для следующего шага в алгоритме Литтла std::pair selected_edge_; + // Значение матрицы, которое выбирается для следующего шага в алгоритме // Литтла std::pair selected_value_; diff --git a/backend/optimal_way/circle_obstacle.h b/backend/optimal_way/circle_obstacle.h index 5222955..4c75dfa 100644 --- a/backend/optimal_way/circle_obstacle.h +++ b/backend/optimal_way/circle_obstacle.h @@ -13,7 +13,9 @@ constexpr double precision = lib::precision; struct LinearFunction { LinearFunction(double a, double b, double c) : a_coef{a}, b_coef{b}, c_coef{c} {} + double a_coef, b_coef, c_coef; + bool operator==(const LinearFunction& other) { return (std::abs(a_coef - other.a_coef) < precision && std::abs(b_coef - other.b_coef) < precision && @@ -23,7 +25,9 @@ struct LinearFunction { struct Point : public lib::Point { Point(double xx, double yy) : lib::Point{xx, yy} {} + std::vector tangents; + std::shared_ptr another_tangent_point = nullptr; }; @@ -31,25 +35,34 @@ class CircleObstacle { public: CircleObstacle(Point center, double radius) : center_{center}, radius_{radius} {} + CircleObstacle() : center_{0, 0}, radius_{0} {} Point GetCenter() const { return center_; } + double GetRadius() const { return radius_; } + std::vector GetTangentLines() { return tangents_; } + std::vector GetTangentPoints() { return tangent_points_; } void SetCenter(const Point& center) { center_ = center; } + void SetRadius(double r) { radius_ = r; } + void AddTangentLine(const LinearFunction& tangent) { tangents_.push_back(tangent); } + void AddTangentPoint(const Point& tangent_point) { tangent_points_.push_back(tangent_point); } + bool operator==(const CircleObstacle& other) { return (center_ == other.center_ && std::abs(radius_ - other.radius_) < precision); } + bool operator!=(const CircleObstacle& other) { return (center_ != other.center_ || std::abs(radius_ - other.radius_) >= precision); @@ -57,8 +70,12 @@ class CircleObstacle { private: Point center_; + double radius_; + std::vector tangents_; + std::vector tangent_points_; }; + } // namespace math diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index 8e8ebea..a37db95 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -3,6 +3,7 @@ #include namespace math { + LinearFunction MakeLinearFunction(const Point& point1, const Point& point2) { double slope = (point2.y - point1.y) / (point2.x - point1.x); double b_coef = point1.y - slope * point1.x; @@ -117,4 +118,5 @@ bool AreThereIntersections(const CircleObstacle& crcl, const Point& point1, return false; } } + } // namespace math diff --git a/backend/optimal_way/helpers_functions.h b/backend/optimal_way/helpers_functions.h index f6de97e..17dd947 100644 --- a/backend/optimal_way/helpers_functions.h +++ b/backend/optimal_way/helpers_functions.h @@ -2,6 +2,7 @@ #include "circle_obstacle.h" namespace math { + double DistanceBetweenPoints(const Point& p1, const Point& p2); double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, @@ -9,7 +10,7 @@ double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, LinearFunction MakeLinearFunction(const Point& point1, const Point& point2); -// Точки касания прямой к окружснотям +// Точки касания прямой к окружностям std::pair CrossPoints(const LinearFunction& tangent, const CircleObstacle& circle1, const CircleObstacle& circle2); diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index 07cb402..773f87c 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -10,13 +10,17 @@ class MinimumDistanceCalculator { public: MinimumDistanceCalculator(Point p1, Point p2) : point1_{p1}, point2_{p2}, circles_(0) {} + MinimumDistanceCalculator(Point p1, Point p2, std::vector v) : point1_{p1}, point2_{p2}, circles_{v} {} private: Point point1_; + Point point2_; + std::vector circles_; + PathWayGraph graph_; bool TangentGoesTroughOtherCircle(const LinearFunction& tangent, @@ -36,4 +40,5 @@ class MinimumDistanceCalculator { std::vector FindOptimalWay(); }; + } // namespace math From f202fab0d3bae805fb56fb7a89caa16dd57f8d49 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:17:50 +0300 Subject: [PATCH 33/42] fix problem of passing empty vector to dijkstras algorithm --- backend/optimal_way/optimal_way.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index 63cbcdf..70e810e 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -109,6 +109,9 @@ std::vector MinimumDistanceCalculator::FindOptimalWay() { FillTangentsCircles(); FillTangentsPoints(point1_); FillTangentsPoints(point2_); + FillPathNodesOnCircles(); + FillPathNodesOnPoint(point1_); + FillPathNodesOnPoint(point2_); Dijkstras_algorithm da(graph_); return da.Get_Min_Path(); } From 4d0b92e7029464e9d1f2b9d139731d8f2116ef5b Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:23:09 +0300 Subject: [PATCH 34/42] Add getter to get optimal way --- backend/optimal_way/optimal_way.cpp | 4 ++-- backend/optimal_way/optimal_way.h | 14 +++++++++++--- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index 70e810e..e803fdb 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -105,7 +105,7 @@ void MinimumDistanceCalculator::FillPathNodesOnPoint(const Point& point) { graph_.nodes.push_back(std::make_shared(new_node)); } -std::vector MinimumDistanceCalculator::FindOptimalWay() { +void MinimumDistanceCalculator::FindOptimalWay() { FillTangentsCircles(); FillTangentsPoints(point1_); FillTangentsPoints(point2_); @@ -113,7 +113,7 @@ std::vector MinimumDistanceCalculator::FindOptimalWay() { FillPathNodesOnPoint(point1_); FillPathNodesOnPoint(point2_); Dijkstras_algorithm da(graph_); - return da.Get_Min_Path(); + optimal_way_ = da.Get_Min_Path(); } } // namespace math diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index 773f87c..56fc0cf 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -9,10 +9,16 @@ namespace math { class MinimumDistanceCalculator { public: MinimumDistanceCalculator(Point p1, Point p2) - : point1_{p1}, point2_{p2}, circles_(0) {} + : point1_{p1}, point2_{p2}, circles_(0) { + FindOptimalWay(); + } MinimumDistanceCalculator(Point p1, Point p2, std::vector v) - : point1_{p1}, point2_{p2}, circles_{v} {} + : point1_{p1}, point2_{p2}, circles_{v} { + FindOptimalWay(); + } + + std::vector GetOptimalWay() { return optimal_way_; } private: Point point1_; @@ -23,6 +29,8 @@ class MinimumDistanceCalculator { PathWayGraph graph_; + std::vector optimal_way_; + bool TangentGoesTroughOtherCircle(const LinearFunction& tangent, int circle1_index, int circle2_index); @@ -38,7 +46,7 @@ class MinimumDistanceCalculator { void FillPathNodesOnPoint(const Point& point); - std::vector FindOptimalWay(); + void FindOptimalWay(); }; } // namespace math From 48db1a9aa468d43674ec7b7cd6bbed385cd01785 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Mon, 15 Apr 2024 14:45:02 +0300 Subject: [PATCH 35/42] Delete useless constructor --- backend/optimal_way/optimal_way.h | 5 ----- 1 file changed, 5 deletions(-) diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index 56fc0cf..851b918 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -8,11 +8,6 @@ namespace math { class MinimumDistanceCalculator { public: - MinimumDistanceCalculator(Point p1, Point p2) - : point1_{p1}, point2_{p2}, circles_(0) { - FindOptimalWay(); - } - MinimumDistanceCalculator(Point p1, Point p2, std::vector v) : point1_{p1}, point2_{p2}, circles_{v} { FindOptimalWay(); From 5da32bccf77ef25eed018a770be882b4dc7c7d2a Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 17:08:32 +0300 Subject: [PATCH 36/42] refactor code and add comments --- backend/optimal_way/circle_obstacle.h | 14 +++- backend/optimal_way/helpers_functions.cpp | 18 ++--- backend/optimal_way/helpers_functions.h | 39 +++++++++-- backend/optimal_way/optimal_way.cpp | 84 ++++++++++++----------- backend/optimal_way/optimal_way.h | 36 ++++++++-- 5 files changed, 129 insertions(+), 62 deletions(-) diff --git a/backend/optimal_way/circle_obstacle.h b/backend/optimal_way/circle_obstacle.h index 4c75dfa..7271b52 100644 --- a/backend/optimal_way/circle_obstacle.h +++ b/backend/optimal_way/circle_obstacle.h @@ -7,9 +7,10 @@ #include "../lib/point.h" namespace math { + constexpr double precision = lib::precision; -// Структура хранит коэфиценты для прямой вида ax+by+c=0 +/// @brief прямая вида ax+by+c=0 struct LinearFunction { LinearFunction(double a, double b, double c) : a_coef{a}, b_coef{b}, c_coef{c} {} @@ -23,16 +24,25 @@ struct LinearFunction { } }; +/// @brief точка с геометрическими связями struct Point : public lib::Point { Point(double xx, double yy) : lib::Point{xx, yy} {} + // Касательные, проходящие через точку std::vector tangents; + // Вторая точка касательной std::shared_ptr another_tangent_point = nullptr; }; +/// @brief круговое препятствие class CircleObstacle { public: + /** + * @brief инициалирует экземпляр CircleObstacle + * @param center: центр круга + * @param radius: радиус круга + */ CircleObstacle(Point center, double radius) : center_{center}, radius_{radius} {} @@ -73,8 +83,10 @@ class CircleObstacle { double radius_; + // Касательные std::vector tangents_; + // Точки касания std::vector tangent_points_; }; diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index a37db95..2b20cdf 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -4,12 +4,6 @@ namespace math { -LinearFunction MakeLinearFunction(const Point& point1, const Point& point2) { - double slope = (point2.y - point1.y) / (point2.x - point1.x); - double b_coef = point1.y - slope * point1.x; - return LinearFunction{slope, -1, b_coef}; -} - double DistanceBetweenPoints(const Point& p1, const Point& p2) { return pow(pow(p2.x - p1.x, 2) + pow(p2.y - p1.y, 2), 0.5); } @@ -22,9 +16,15 @@ double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, return circle.GetRadius() * acos(cos_alpha); } -std::pair CrossPoints(const LinearFunction& tangent, - const CircleObstacle& circle1, - const CircleObstacle& circle2) { +LinearFunction MakeLinearFunction(const Point& point1, const Point& point2) { + double slope = (point2.y - point1.y) / (point2.x - point1.x); + double b_coef = point1.y - slope * point1.x; + return LinearFunction{slope, -1, b_coef}; +} + +std::pair TangentPoints(const LinearFunction& tangent, + const CircleObstacle& circle1, + const CircleObstacle& circle2) { double a = tangent.a_coef; double b = tangent.b_coef; double c = tangent.c_coef; diff --git a/backend/optimal_way/helpers_functions.h b/backend/optimal_way/helpers_functions.h index 17dd947..2f09fe2 100644 --- a/backend/optimal_way/helpers_functions.h +++ b/backend/optimal_way/helpers_functions.h @@ -1,6 +1,7 @@ #pragma once #include "circle_obstacle.h" + namespace math { double DistanceBetweenPoints(const Point& p1, const Point& p2); @@ -10,18 +11,44 @@ double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, LinearFunction MakeLinearFunction(const Point& point1, const Point& point2); -// Точки касания прямой к окружностям -std::pair CrossPoints(const LinearFunction& tangent, - const CircleObstacle& circle1, - const CircleObstacle& circle2); - +/** + * @brief находит точки касания кругов с их общей касательной + * @param tangent: касательная + * @param circle1: круг 1 + * @param circle2: круг 2 + * @return точки касательной + */ +std::pair TangentPoints(const LinearFunction& tangent, + const CircleObstacle& circle1, + const CircleObstacle& circle2); + +/** + * @brief находит точки касания кругов c касательной, + * проведенной из контрольной точки + * @param crcl: круг + * @param point: контрольная точка + * @return точки касательной + */ std::pair TangentPointsToCircle(const CircleObstacle& crcl, const Point& point); +/** + * @brief находит уравнения общих касательных двух кругов + * @param circle1: круг 1 + * @param circle2: круг 2 + * @return уравнения касательных + */ std::vector TangentsBetweenCircles( const CircleObstacle& circle1, const CircleObstacle& circle2); -// Пересекает ли отрезок, проведенный через две точки, окружность +/** + * @brief проверяет, пересекает ли отрезок, + * проведенный через две точки, окружность + * @param crcl: круг + * @param pnt1: точка 1 + * @param pnt2: точка 2 + * @return результат проверки + */ bool AreThereIntersections(const CircleObstacle& crcl, const Point& pnt1, const Point& pnt2); diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index e803fdb..8935006 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -7,7 +7,7 @@ namespace math { bool MinimumDistanceCalculator::TangentGoesTroughOtherCircle( const LinearFunction& tangent, int circle1_index, int circle2_index) { std::pair tangent_points = - CrossPoints(tangent, circles_[circle1_index], circles_[circle2_index]); + TangentPoints(tangent, circles_[circle1_index], circles_[circle2_index]); for (int l = 0; l < circles_.size(); ++l) if (l != circle1_index && l != circle2_index) if (AreThereIntersections(circles_[l], tangent_points.first, @@ -20,7 +20,7 @@ void MinimumDistanceCalculator::AddTangent(const LinearFunction& tangent, CircleObstacle& circle1, CircleObstacle& circle2) { std::pair tangent_points = - CrossPoints(tangent, circle1, circle2); + TangentPoints(tangent, circle1, circle2); tangent_points.first.another_tangent_point = std::make_shared(tangent_points.second); tangent_points.second.another_tangent_point = @@ -31,7 +31,7 @@ void MinimumDistanceCalculator::AddTangent(const LinearFunction& tangent, circle2.AddTangentPoint(tangent_points.second); } -void MinimumDistanceCalculator::FillTangentsCircles() { +void MinimumDistanceCalculator::AddCommonTangents() { for (int i = 0; i < circles_.size(); ++i) { for (int j = i + 1; j < circles_.size(); ++j) { std::vector tangents = @@ -44,31 +44,33 @@ void MinimumDistanceCalculator::FillTangentsCircles() { } } -void MinimumDistanceCalculator::FillTangentsPoints(Point& point) { - for (int i = 0; i < circles_.size(); ++i) { - std::pair tangent_points_1 = - TangentPointsToCircle(circles_[i], point); - bool is_exist_tangent1 = true; - bool is_exist_tangent2 = true; - for (int j = 0; j < circles_.size(); ++j) { - if (j != i) { - if (AreThereIntersections(circles_[j], point, tangent_points_1.first)) - is_exist_tangent1 = false; - if (AreThereIntersections(circles_[j], point, tangent_points_1.second)) - is_exist_tangent2 = false; +void MinimumDistanceCalculator::AddControlPointTangents() { + for (auto point : {point1_, point2_}) + for (int i = 0; i < circles_.size(); ++i) { + std::pair tangent_points_1 = + TangentPointsToCircle(circles_[i], point); + bool is_exist_tangent1 = true; + bool is_exist_tangent2 = true; + for (int j = 0; j < circles_.size(); ++j) { + if (j != i) { + if (AreThereIntersections(circles_[j], point, tangent_points_1.first)) + is_exist_tangent1 = false; + if (AreThereIntersections(circles_[j], point, + tangent_points_1.second)) + is_exist_tangent2 = false; + } } - } - if (is_exist_tangent1) - point.tangents.push_back( - MakeLinearFunction(point, tangent_points_1.first)); + if (is_exist_tangent1) + point.tangents.push_back( + MakeLinearFunction(point, tangent_points_1.first)); - if (is_exist_tangent2) - point.tangents.push_back( - MakeLinearFunction(point, tangent_points_1.second)); - } + if (is_exist_tangent2) + point.tangents.push_back( + MakeLinearFunction(point, tangent_points_1.second)); + } } -void MinimumDistanceCalculator::FillPathNodesOnCircles() { +void MinimumDistanceCalculator::AddGraphTangentPoints() { for (auto& obstacle : circles_) { for (auto& point : obstacle.GetTangentPoints()) { PathWayNode new_node{point, graph_.nodes.size()}; @@ -89,29 +91,29 @@ void MinimumDistanceCalculator::FillPathNodesOnCircles() { } } -void MinimumDistanceCalculator::FillPathNodesOnPoint(const Point& point) { - PathWayNode new_node{point, graph_.nodes.size()}; - for (auto& prev : graph_.nodes) { - if ((*prev).circle_prt) { - std::pair tangent_points = - TangentPointsToCircle((*(*prev).circle_prt), point); - if (tangent_points.first == (*prev).point || - tangent_points.second == (*prev).point) { - graph_.AddEdge((*prev).number, new_node.number, - DistanceBetweenPoints((*prev).point, new_node.point)); +void MinimumDistanceCalculator::AddGraphControlPoints() { + for (auto point : {point1_, point2_}) { + PathWayNode new_node{point, graph_.nodes.size()}; + for (auto& prev : graph_.nodes) { + if ((*prev).circle_prt) { + std::pair tangent_points = + TangentPointsToCircle((*(*prev).circle_prt), point); + if (tangent_points.first == (*prev).point || + tangent_points.second == (*prev).point) { + graph_.AddEdge((*prev).number, new_node.number, + DistanceBetweenPoints((*prev).point, new_node.point)); + } } } + graph_.nodes.push_back(std::make_shared(new_node)); } - graph_.nodes.push_back(std::make_shared(new_node)); } void MinimumDistanceCalculator::FindOptimalWay() { - FillTangentsCircles(); - FillTangentsPoints(point1_); - FillTangentsPoints(point2_); - FillPathNodesOnCircles(); - FillPathNodesOnPoint(point1_); - FillPathNodesOnPoint(point2_); + AddCommonTangents(); + AddControlPointTangents(); + AddGraphTangentPoints(); + AddGraphControlPoints(); Dijkstras_algorithm da(graph_); optimal_way_ = da.Get_Min_Path(); } diff --git a/backend/optimal_way/optimal_way.h b/backend/optimal_way/optimal_way.h index 851b918..7b4f115 100644 --- a/backend/optimal_way/optimal_way.h +++ b/backend/optimal_way/optimal_way.h @@ -6,8 +6,15 @@ namespace math { +/// @brief функтор, находящий кратчайший путь между точками class MinimumDistanceCalculator { public: + /** + * @brief находит кратчайший путь между точками + * @param p1: точка 1 + * @param p2: точка 2 + * @param v: круговые препятствия + */ MinimumDistanceCalculator(Point p1, Point p2, std::vector v) : point1_{p1}, point2_{p2}, circles_{v} { FindOptimalWay(); @@ -22,25 +29,44 @@ class MinimumDistanceCalculator { std::vector circles_; + // Граф для алгоритма Дейстры PathWayGraph graph_; + // Оптимальный путь std::vector optimal_way_; + /** + * @brief проверяет, пересекат ли общая касательная двух кругов другой круг + * @param tangent: общая касательная + * @param circle1_index: номер круга 1 + * @param circle2_index: номер круга 2 + * @return результат проверки + */ bool TangentGoesTroughOtherCircle(const LinearFunction& tangent, int circle1_index, int circle2_index); + /** + * @brief добавляет информацию об общей касательной двух кругов + * @param tangent: общая касательная + * @param circle1: круг 1 + * @param circle2: круг 2 + */ void AddTangent(const LinearFunction& tangent, CircleObstacle& circle1, CircleObstacle& circle2); - // Заполняет вектор точек касательных для каждой окружности - void FillTangentsCircles(); + // Добавляет информацию о всех общих касательных всех окржностей + void AddCommonTangents(); - void FillTangentsPoints(Point& point); + // Добавляет информацию о всех касательных из контрольных точек + void AddControlPointTangents(); - void FillPathNodesOnCircles(); + // Добавляет в граф точки касания + void AddGraphTangentPoints(); - void FillPathNodesOnPoint(const Point& point); + // Добавляет в граф контрольные точки + void AddGraphControlPoints(); + // Находит оптимальный маршрут void FindOptimalWay(); }; From fe9995643f5f1b6693d5b249881929ff2fd619db Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 17:20:07 +0300 Subject: [PATCH 37/42] change #define to constexpr --- backend/optimal_way/path_graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index 34c3944..91a99ce 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -8,7 +8,7 @@ namespace math { -#define inf std::numeric_limits::infinity() +constexpr inf = std::numeric_limits::infinity(); /// @brief Вершина графа struct PathWayNode { From 96e90d8a7812dfd2616db2acfd1d96ffc1a48119 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 17:28:03 +0300 Subject: [PATCH 38/42] delete conflicting file # because correct version in the main branch --- tests/matrix_test.cpp | 168 ------------------------------------------ 1 file changed, 168 deletions(-) delete mode 100644 tests/matrix_test.cpp diff --git a/tests/matrix_test.cpp b/tests/matrix_test.cpp deleted file mode 100644 index 8818cf8..0000000 --- a/tests/matrix_test.cpp +++ /dev/null @@ -1,168 +0,0 @@ -#include - -#include "../Backend/adjacency_matrix.h" - -#if !defined(WIN32) -#define BOOST_TEST_DYN_LINK -#endif -#include - -namespace tt = boost::test_tools; -namespace utf = boost::unit_test; - -BOOST_AUTO_TEST_SUITE(random_matrix) - -BOOST_AUTO_TEST_CASE(random_matrix_2x2) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 80}, {91, FLT_MAX}}); - - double asmt = 171; - std::pair edge = {1, 2}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(random_matrix_3x3) { - AdjacencyMatrix matrix = AdjacencyMatrix( - {{FLT_MAX, 80, 98}, {91, FLT_MAX, 59}, {16, 21, FLT_MAX}}); - - double asmt = 155; - std::pair edge = {2, 3}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(random_matrix_4x4) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 36, 35, 91}, - {16, FLT_MAX, 31, 92}, - {13, 75, FLT_MAX, 63}, - {88, 24, 58, FLT_MAX}}); - - double asmt = 138; - std::pair edge = {4, 2}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(random_matrix_5x5) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 59, 74, 21, 81}, - {92, FLT_MAX, 64, 96, 33}, - {64, 36, FLT_MAX, 47, 87}, - {4, 78, 32, FLT_MAX, 32}, - {57, 86, 83, 24, FLT_MAX}}); - - double asmt = 146; - std::pair edge = {3, 2}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(symmetric_matrix) - -BOOST_AUTO_TEST_CASE(symmetric_matrix_4x4) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 18, 99, 64}, - {18, FLT_MAX, 81, 25}, - {99, 81, FLT_MAX, 55}, - {64, 25, 55, FLT_MAX}}); - - double asmt = 146; - std::pair edge = {1, 2}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(symmetric_matrix_6x6) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 25, 65, 38, 18, 12}, - {25, FLT_MAX, 12, 59, 16, 54}, - {65, 12, FLT_MAX, 50, 19, 69}, - {38, 59, 50, FLT_MAX, 35, 73}, - {18, 16, 19, 35, FLT_MAX, 15}, - {12, 54, 69, 73, 15, FLT_MAX}}); - - double asmt = 118; - std::pair edge = {2, 3}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(symmetric_matrix_10x10) { - AdjacencyMatrix matrix = - AdjacencyMatrix({{FLT_MAX, 21, 188, 268, 461, 131, 366, 449, 492, 62}, - {21, FLT_MAX, 410, 220, 333, 115, 451, 236, 272, 127}, - {188, 410, FLT_MAX, 21, 498, 270, 280, 24, 20, 446}, - {268, 220, 21, FLT_MAX, 48, 382, 492, 119, 414, 330}, - {461, 333, 498, 48, FLT_MAX, 364, 366, 332, 340, 406}, - {131, 115, 270, 382, 364, FLT_MAX, 498, 380, 90, 189}, - {366, 451, 280, 492, 366, 498, FLT_MAX, 477, 105, 379}, - {449, 236, 24, 119, 332, 380, 477, FLT_MAX, 369, 422}, - {492, 272, 20, 414, 340, 90, 105, 369, FLT_MAX, 377}, - {62, 127, 446, 330, 406, 189, 379, 422, 377, FLT_MAX}}); - - double asmt = 659; - std::pair edge = {5, 4}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_SUITE_END() - -BOOST_AUTO_TEST_SUITE(symm_obstacle_wise_matrix) - -BOOST_AUTO_TEST_CASE(symm_obstacle_wise_matrix_4x4) { - AdjacencyMatrix matrix = AdjacencyMatrix({{FLT_MAX, 18, 99, 64}, - {18, FLT_MAX, 81, FLT_MAX}, - {99, 81, FLT_MAX, 55}, - {64, FLT_MAX, 55, FLT_MAX}}); - - double asmt = 146; - std::pair edge = {1, 2}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(symm_obstacle_wise_matrix_6x6) { - AdjacencyMatrix matrix = - AdjacencyMatrix({{FLT_MAX, 25, 65, 38, 18, FLT_MAX}, - {25, FLT_MAX, FLT_MAX, 59, 16, 54}, - {65, FLT_MAX, FLT_MAX, 50, 19, 69}, - {38, 59, 50, FLT_MAX, 35, 73}, - {18, 16, 19, 35, FLT_MAX, 15}, - {FLT_MAX, 54, 69, 73, 15, FLT_MAX}}); - - double asmt = 146; - std::pair edge = {5, 6}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_CASE(symmetric_obstacle_wise_matrix_10x10) { - AdjacencyMatrix matrix = AdjacencyMatrix( - {{FLT_MAX, FLT_MAX, FLT_MAX, 268, 461, FLT_MAX, 366, FLT_MAX, 492, 62}, - {FLT_MAX, FLT_MAX, 410, 220, 333, 115, 451, 236, 272, 127}, - {FLT_MAX, 410, FLT_MAX, 21, 498, 270, 280, 24, 20, 446}, - {268, 220, 21, FLT_MAX, 48, 382, 492, 119, FLT_MAX, 330}, - {461, 333, 498, 48, FLT_MAX, 364, 366, FLT_MAX, FLT_MAX, 406}, - {FLT_MAX, 115, 270, 382, 364, FLT_MAX, 498, 380, 90, 189}, - {366, 451, 280, 492, 366, 498, FLT_MAX, 477, 105, 379}, - {FLT_MAX, 236, 24, 119, FLT_MAX, 380, 477, FLT_MAX, 369, 422}, - {492, 272, 20, FLT_MAX, FLT_MAX, 90, 105, 369, FLT_MAX, 377}, - {62, 127, 446, 330, 406, 189, 379, 422, 377, FLT_MAX}}); - - double asmt = 708; - std::pair edge = {10, 1}; - BOOST_TEST(matrix.GetBottomLineEvaluation() == asmt); - BOOST_TEST(matrix.GetSelectedEdge().first == edge.first - 1); - BOOST_TEST(matrix.GetSelectedEdge().second == edge.second - 1); -} - -BOOST_AUTO_TEST_SUITE_END() From ba40e1ee8723cb61ff7caab3a776c746585a1565 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 17:39:41 +0300 Subject: [PATCH 39/42] small mistake fix --- backend/optimal_way/path_graph.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backend/optimal_way/path_graph.h b/backend/optimal_way/path_graph.h index 91a99ce..3fd1500 100644 --- a/backend/optimal_way/path_graph.h +++ b/backend/optimal_way/path_graph.h @@ -8,7 +8,7 @@ namespace math { -constexpr inf = std::numeric_limits::infinity(); +constexpr double inf = std::numeric_limits::infinity(); /// @brief Вершина графа struct PathWayNode { From 81003c0dbc98393f9e25770e7b6323163c687378 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Mon, 15 Apr 2024 21:22:49 +0300 Subject: [PATCH 40/42] change from float to double --- backend/optimal_way/helpers_functions.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index 2b20cdf..bc6ea84 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -105,10 +105,10 @@ bool AreThereIntersections(const CircleObstacle& crcl, const Point& point1, if (discriminant <= 0) return false; else { - float x_1 = + double x_1 = (-(slope * b_coef - center.x - slope * center.y) + sqrt(discriminant)) / (1 + pow(slope, 2)); - float x_2 = + double x_2 = (-(slope * b_coef - center.x - slope * center.y) - sqrt(discriminant)) / (1 + pow(slope, 2)); if ((std::min(point1.x, point2.x) <= x_1 <= std::max(point1.x, point2.x)) || From 38ef4f2dedc1777ac5f7550d568eef0bdf315cc7 Mon Sep 17 00:00:00 2001 From: Romanov-Fedor <143000900+Romanov-Fedor@users.noreply.github.com> Date: Mon, 15 Apr 2024 21:25:17 +0300 Subject: [PATCH 41/42] fix discriminant formula --- backend/optimal_way/helpers_functions.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index bc6ea84..2cb741d 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -46,7 +46,8 @@ std::pair TangentPointsToCircle(const CircleObstacle& crcl, Point center = crcl.GetCenter(); double radius = crcl.GetRadius(); double discriminant = pow((center.x - pnt.x) * (center.y - pnt.y), 2) - - (pow(radius, 2) - pow(pnt.x - center.x, 2)); + (pow(radius, 2) - pow(pnt.x - center.x, 2)) * + (pow(radius, 2) - pow(pnt.y - center.y, 2)); double slope_1 = (-(center.x - pnt.x) * (center.y - pnt.y) + sqrt(discriminant)) / (pow(radius, 2) - pow(pnt.x - center.x, 2)); From cd3eed8e6a57cbe39e2fbc1efbd06617572124f7 Mon Sep 17 00:00:00 2001 From: Ilya_Rybalkin Date: Mon, 15 Apr 2024 21:38:44 +0300 Subject: [PATCH 42/42] change MakeLinearFunction() method to LinearFunction constructor --- backend/optimal_way/circle_obstacle.h | 8 +++++++- backend/optimal_way/helpers_functions.cpp | 9 +-------- backend/optimal_way/helpers_functions.h | 2 -- backend/optimal_way/optimal_way.cpp | 5 ++--- 4 files changed, 10 insertions(+), 14 deletions(-) diff --git a/backend/optimal_way/circle_obstacle.h b/backend/optimal_way/circle_obstacle.h index 7271b52..bd22e68 100644 --- a/backend/optimal_way/circle_obstacle.h +++ b/backend/optimal_way/circle_obstacle.h @@ -15,6 +15,12 @@ struct LinearFunction { LinearFunction(double a, double b, double c) : a_coef{a}, b_coef{b}, c_coef{c} {} + LinearFunction(const lib::Point& point1, const lib::Point& point2) { + a_coef = (point2.y - point1.y) / (point2.x - point1.x); + b_coef = -1; + c_coef = point1.y - a_coef * point1.x; + } + double a_coef, b_coef, c_coef; bool operator==(const LinearFunction& other) { @@ -32,7 +38,7 @@ struct Point : public lib::Point { std::vector tangents; // Вторая точка касательной - std::shared_ptr another_tangent_point = nullptr; + std::shared_ptr another_tangent_point = nullptr; }; /// @brief круговое препятствие diff --git a/backend/optimal_way/helpers_functions.cpp b/backend/optimal_way/helpers_functions.cpp index 2cb741d..34c1232 100644 --- a/backend/optimal_way/helpers_functions.cpp +++ b/backend/optimal_way/helpers_functions.cpp @@ -16,12 +16,6 @@ double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, return circle.GetRadius() * acos(cos_alpha); } -LinearFunction MakeLinearFunction(const Point& point1, const Point& point2) { - double slope = (point2.y - point1.y) / (point2.x - point1.x); - double b_coef = point1.y - slope * point1.x; - return LinearFunction{slope, -1, b_coef}; -} - std::pair TangentPoints(const LinearFunction& tangent, const CircleObstacle& circle1, const CircleObstacle& circle2) { @@ -84,8 +78,7 @@ std::vector TangentsBetweenCircles( (pow(x_1 - x_0, 2) + pow(y_1 - y_0, 2)); double a = ((r_1 - r_0) - b * (y_1 - y_0)) / (x_1 - x_0); double c = r_0 - a * x_0 - b * y_0; - LinearFunction tangent{a, b, c}; - return tangent; + return LinearFunction(a, b, c); }; for (auto n1 : {-1, 1}) diff --git a/backend/optimal_way/helpers_functions.h b/backend/optimal_way/helpers_functions.h index 2f09fe2..a17e371 100644 --- a/backend/optimal_way/helpers_functions.h +++ b/backend/optimal_way/helpers_functions.h @@ -9,8 +9,6 @@ double DistanceBetweenPoints(const Point& p1, const Point& p2); double DistanceBetweenPointsOnCircle(const CircleObstacle& circle, const Point& p1, const Point& p2); -LinearFunction MakeLinearFunction(const Point& point1, const Point& point2); - /** * @brief находит точки касания кругов с их общей касательной * @param tangent: касательная diff --git a/backend/optimal_way/optimal_way.cpp b/backend/optimal_way/optimal_way.cpp index 8935006..b574529 100644 --- a/backend/optimal_way/optimal_way.cpp +++ b/backend/optimal_way/optimal_way.cpp @@ -61,12 +61,11 @@ void MinimumDistanceCalculator::AddControlPointTangents() { } } if (is_exist_tangent1) - point.tangents.push_back( - MakeLinearFunction(point, tangent_points_1.first)); + point.tangents.push_back(LinearFunction(point, tangent_points_1.first)); if (is_exist_tangent2) point.tangents.push_back( - MakeLinearFunction(point, tangent_points_1.second)); + LinearFunction(point, tangent_points_1.second)); } }