From ce2bc67d6d2920f391e5e1e46461e29731fb1397 Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Wed, 24 Dec 2025 18:22:24 +0300 Subject: [PATCH 1/4] =?UTF-8?q?Eigen=20=D0=BA=D0=B0=D0=BA=20=D0=B7=D0=B0?= =?UTF-8?q?=D0=B2=D0=B8=D1=81=D0=B8=D0=BC=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Изменение оформления --- .gitmodules | 3 + CMakeLists.txt | 2 +- DRAWer_2_0.ui | 162 ++++++++++++++++++++++++++++----------------- dependencies/eigen | 1 + 4 files changed, 107 insertions(+), 61 deletions(-) create mode 100644 .gitmodules create mode 160000 dependencies/eigen diff --git a/.gitmodules b/.gitmodules new file mode 100644 index 0000000..6075fde --- /dev/null +++ b/.gitmodules @@ -0,0 +1,3 @@ +[submodule "dependencies/eigen"] + path = dependencies/eigen + url = https://gitlab.com/libeigen/eigen.git diff --git a/CMakeLists.txt b/CMakeLists.txt index 3cc9cb3..fea0c1f 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -7,7 +7,7 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) # PlaneGCS PART set(PlaneGCS_project_name "PlaneGCS") set(INCLUDE_BOOST_DIR "C:/local/boost_1_89_0") -set(INCLUDE_EIGEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/eigen-5.0.0) +set(INCLUDE_EIGEN_DIR ${CMAKE_CURRENT_SOURCE_DIR}/dependencies/eigen) add_library(${PlaneGCS_project_name} STATIC GCS/GCS.cpp diff --git a/DRAWer_2_0.ui b/DRAWer_2_0.ui index 8bc1f52..88e5956 100644 --- a/DRAWer_2_0.ui +++ b/DRAWer_2_0.ui @@ -6,14 +6,14 @@ 0 0 - 691 - 615 + 776 + 701 1080 - 1080 + 1060 @@ -27,64 +27,103 @@ 23 - - - - 75 - 24 - - - - Line - - + + + + + + 75 + 24 + + + + Line + + + + + + + + + Primitives + + + Qt::AlignmentFlag::AlignCenter + + + true + + + + + + - - - - 75 - 24 - - - - Parallel - - - - - - - Perpendicular - - - - - - - - 75 - 24 - - - - P2P - - - - - - - Vertical - - - - - - - Horizontal - - + + + + + Constraints + + + Qt::AlignmentFlag::AlignCenter + + + + + + + + + + 75 + 24 + + + + P2P + + + + + + + Perpendicular + + + + + + + Horizontal + + + + + + + + 75 + 24 + + + + Parallel + + + + + + + Vertical + + + + + + @@ -108,6 +147,9 @@ 16777215 + + CrossCursor + Canvas @@ -120,7 +162,7 @@ 0 0 - 691 + 776 21 diff --git a/dependencies/eigen b/dependencies/eigen new file mode 160000 index 0000000..9164d3f --- /dev/null +++ b/dependencies/eigen @@ -0,0 +1 @@ +Subproject commit 9164d3f16ad21c1546d5fc99cd28fffc8ac3c1ee From fe403236ebb7fb305e9231d8438a95516d17b966 Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Wed, 24 Dec 2025 18:46:32 +0300 Subject: [PATCH 2/4] =?UTF-8?q?=D0=97=D0=B0=D1=87=D0=B0=D1=82=D0=B0=D0=BA?= =?UTF-8?q?=D0=B8=20=D0=B4=D0=BB=D1=8F=20Circle?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Canvas.cpp | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- Canvas.h | 5 ++++- 2 files changed, 56 insertions(+), 3 deletions(-) diff --git a/Canvas.cpp b/Canvas.cpp index 0d4a45e..6bdf74d 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -92,6 +92,14 @@ void Canvas::zoomReset() Line* Canvas::findAt(QPointF& pos, qreal tolerance) { + //for (Curve* curve : curves) { + // if (Line* line = dynamic_cast(curve)) { + // if (line->contains(pos, tolerance)) { + // return line; + // } + // } + //} + for (Line* line : lines) { if (line->contains(pos, tolerance)) { return line; @@ -103,6 +111,19 @@ Line* Canvas::findAt(QPointF& pos, qreal tolerance) Point* Canvas::findPointAt(QPointF pos, qreal tolerance) { Point* temp = nullptr; + + //for (Curve* curve : curves) { + // if (Line* line = dynamic_cast(curve)) { + // QPointF p1(*line->p1.x, *line->p1.y); + // QPointF p2(*line->p2.x, *line->p2.y); + + // if (dist_P2P(p1, pos) <= tolerance) + // temp = line->start_ref; + // if (dist_P2P(p2, pos) <= tolerance) + // temp = line->end_ref; + // } + //} + for (Line* line : lines) { QPointF p1(*line->p1.x, *line->p1.y); QPointF p2(*line->p2.x, *line->p2.y); @@ -350,6 +371,7 @@ void Canvas::mousePressEvent(QMouseEvent* event) current_line->set_tag(obj_count++); // Завершаем создание линии lines.append(current_line); + curves.append(current_line); current_line = nullptr; mode = Mode::None; after_constraint = true; @@ -437,6 +459,16 @@ void Canvas::mousePressEvent(QMouseEvent* event) // Находим линии, к которым принадлежат точки Line* l1 = nullptr; Line* l2 = nullptr; + + //for (Curve* curve : curves) { + // if (Line* l = dynamic_cast(curve)) { + // if (l->start_ref == firstPoint || l->end_ref == firstPoint) + // l1 = l; + // if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) + // l2 = l; + // } + //} + for (Line* l : lines) { if (l->start_ref == firstPoint || l->end_ref == firstPoint) l1 = l; @@ -610,6 +642,12 @@ void Canvas::paintEvent(QPaintEvent* event) p.drawLine(0, -5, 0, 5); // ====================== Отрисовка линий ====================== + + // for (Curve* curve : curve){ + // if (Line* line = dynamic_cast(curve)) { + // ... + // } + // } for (Line* line : lines) { bool isSelected = (mode == Mode::Parallel && line == current_line); @@ -803,6 +841,11 @@ void Canvas::solve_for_canvas() } else { sys.applySolution(); + // for (Curve* curve : curve){ + // if (Line* line = dynamic_cast(curve)) { + // ... + // } + // } for (Line* line : lines) { if (abs(*line->p1.x - *line->p2.x) < EPS && abs(*line->p1.y - *line->p2.y) < EPS && after_constraint) { sys.undoSolution(); @@ -811,13 +854,15 @@ void Canvas::solve_for_canvas() } } } - - if (flag) { + if (flag && after_constraint) { QMessageBox::warning(this, QString("Error!"), QString("Last constraint is unavailable!")); remove_constraint(constraints_count - 1); C_Info.erase(constraints_count - 1); constraints_count--; } + else if (flag) { + sys.undoSolution(); + } after_constraint = false; update(); } @@ -840,6 +885,10 @@ void Canvas::clearCanvas() delete pt; } + // for (Curve* curve : curve){ + // delete curve; + // } + for (Line* line : lines) { delete line; } @@ -848,6 +897,7 @@ void Canvas::clearCanvas() params.clear(); points.clear(); lines.clear(); + // curves.clear(); // Очистка контейнеров ограничений parallelPairs.clear(); diff --git a/Canvas.h b/Canvas.h index 3649af8..4df0b52 100644 --- a/Canvas.h +++ b/Canvas.h @@ -34,7 +34,8 @@ enum class Mode : int Coincedent = 3, ///< Режим задания совпадения точек Horizontal = 4, ///< Режим задания горизонтальности Vertical = 5, ///< Режим задания вертикальности - Perpendicular = 6 ///< Режим задания перпендикулярности + Perpendicular = 6, ///< Режим задания перпендикулярности + DrawingCircle = 7 ///< Режим рисования окружности }; /// Удобный тип для хранения пары параллельных линий (порядок не важен) @@ -255,6 +256,8 @@ private: // ====================== Данные геометрической системы ====================== System sys; ///< Геометрический солвер QVector lines; ///< Завершённые линии + QVector circles; ///< Завершённые окружности + QVector curves; QVector points; ///< Все точки сцены std::vector params; ///< Все параметры, передаваемые в солвер From 95f99575e256e304d9a6c71a0ea80e5bd3f4f4c5 Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Wed, 24 Dec 2025 20:36:54 +0300 Subject: [PATCH 3/4] =?UTF-8?q?=D0=9E=D1=82=D1=80=D0=B8=D1=81=D0=BE=D0=B2?= =?UTF-8?q?=D0=BA=D0=B0=20=D0=BE=D0=BA=D1=80=D1=83=D0=B6=D0=BD=D0=BE=D1=81?= =?UTF-8?q?=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Canvas.cpp | 223 ++++++++++++++++++++++++++++------------------------ Canvas.h | 7 +- GCS/Geo.cpp | 7 +- GCS/Geo.h | 10 ++- 4 files changed, 136 insertions(+), 111 deletions(-) diff --git a/Canvas.cpp b/Canvas.cpp index 6bdf74d..492fef6 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -90,19 +90,13 @@ void Canvas::zoomReset() // Методы поиска и проверки // =================================================================== -Line* Canvas::findAt(QPointF& pos, qreal tolerance) +Curve* Canvas::findAt(QPointF& pos, qreal tolerance) { - //for (Curve* curve : curves) { - // if (Line* line = dynamic_cast(curve)) { - // if (line->contains(pos, tolerance)) { - // return line; - // } - // } - //} - - for (Line* line : lines) { - if (line->contains(pos, tolerance)) { - return line; + for (Curve* curve : curves) { + if (Line* line = dynamic_cast(curve)) { + if (line->contains(pos, tolerance)) { + return line; + } } } return nullptr; @@ -112,26 +106,21 @@ Point* Canvas::findPointAt(QPointF pos, qreal tolerance) { Point* temp = nullptr; - //for (Curve* curve : curves) { - // if (Line* line = dynamic_cast(curve)) { - // QPointF p1(*line->p1.x, *line->p1.y); - // QPointF p2(*line->p2.x, *line->p2.y); + for (Curve* curve : curves) { + if (Line* line = dynamic_cast(curve)) { + QPointF p1(*line->p1.x, *line->p1.y); + QPointF p2(*line->p2.x, *line->p2.y); - // if (dist_P2P(p1, pos) <= tolerance) - // temp = line->start_ref; - // if (dist_P2P(p2, pos) <= tolerance) - // temp = line->end_ref; - // } - //} - - for (Line* line : lines) { - QPointF p1(*line->p1.x, *line->p1.y); - QPointF p2(*line->p2.x, *line->p2.y); - - if (dist_P2P(p1, pos) <= tolerance) - temp = line->start_ref; - if (dist_P2P(p2, pos) <= tolerance) - temp = line->end_ref; + if (dist_P2P(p1, pos) <= tolerance) + temp = line->start_ref; + if (dist_P2P(p2, pos) <= tolerance) + temp = line->end_ref; + } + else if (Circle* circle = dynamic_cast(curve)) { + QPointF center(circle->center.get_X(), circle->center.get_Y()); + if (dist_P2P(center, pos) <= tolerance) + temp = circle->center_ref; + } } return temp; } @@ -249,7 +238,7 @@ void Canvas::mousePressEvent(QMouseEvent* event) return; } - Line* found = findAt(scene); + Line* found = dynamic_cast(findAt(scene)); if (found) { draggedLine = found; QPointF lineCenter( @@ -259,11 +248,17 @@ void Canvas::mousePressEvent(QMouseEvent* event) dragOffset = scene - lineCenter; return; } + + Circle* found_circle = dynamic_cast(findAt(scene)); + if (found_circle) { + // TODO + return; + } } // ====================== Режим Horizontal/Vertical ====================== else if (mode == Mode::Horizontal || mode == Mode::Vertical) { - Line* found = findAt(scene); + Line* found = dynamic_cast(findAt(scene)); if (found) { // Проверка: если линия уже вертикальна, нельзя сделать её горизонтальной @@ -370,19 +365,46 @@ void Canvas::mousePressEvent(QMouseEvent* event) current_line->set_tag(obj_count++); // Завершаем создание линии - lines.append(current_line); curves.append(current_line); current_line = nullptr; mode = Mode::None; - after_constraint = true; } solve_for_canvas(); return; } + else if (mode == Mode::DrawingCircle) { + if (!current_circle) { + current_circle = new Circle(); + // Создаем координаты для центра окружности + double* x = new double(scene.x()); + double* y = new double(scene.y()); + + points.push_back(new Point(x, y, obj_count++)); + + // Добавляем параметры в солвер + params.push_back(x); + params.push_back(y); + + current_circle->center.x = x; + current_circle->center.y = y; + current_circle->center_ref = points[points.size() - 1]; + } + else { + double *r = new double(dist_P2P(QPointF(current_circle->center.get_X(), current_circle->center.get_Y()), QPointF(scene.x(), scene.y()))); + current_circle->rad = r; + + params.push_back(r); + curves.append(current_circle); + current_circle->set_tag(obj_count++); + current_circle = nullptr; + mode = Mode::None; + } + solve_for_canvas(); + } // ====================== Режим Parallel: задание параллельности ====================== else if (mode == Mode::Parallel) { - Line* found = findAt(scene); + Line* found = dynamic_cast(findAt(scene)); if (!found) { current_line = nullptr; @@ -460,20 +482,13 @@ void Canvas::mousePressEvent(QMouseEvent* event) Line* l1 = nullptr; Line* l2 = nullptr; - //for (Curve* curve : curves) { - // if (Line* l = dynamic_cast(curve)) { - // if (l->start_ref == firstPoint || l->end_ref == firstPoint) - // l1 = l; - // if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) - // l2 = l; - // } - //} - - for (Line* l : lines) { - if (l->start_ref == firstPoint || l->end_ref == firstPoint) - l1 = l; - if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) - l2 = l; + for (Curve* curve : curves) { + if (Line* l = dynamic_cast(curve)) { + if (l->start_ref == firstPoint || l->end_ref == firstPoint) + l1 = l; + if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) + l2 = l; + } } // Проверка на невозможность ограничения @@ -499,7 +514,7 @@ void Canvas::mousePressEvent(QMouseEvent* event) } else if (mode == Mode::Perpendicular) { - Line* found = findAt(scene); + Line* found = dynamic_cast(findAt(scene)); if (!found) { current_line = nullptr; @@ -643,31 +658,40 @@ void Canvas::paintEvent(QPaintEvent* event) // ====================== Отрисовка линий ====================== - // for (Curve* curve : curve){ - // if (Line* line = dynamic_cast(curve)) { - // ... - // } - // } - for (Line* line : lines) { - bool isSelected = (mode == Mode::Parallel && line == current_line); + for (Curve* curve : curves) { + if (Line* line = dynamic_cast(curve)) { + bool isSelected = (mode == Mode::Parallel && line == current_line); - // Настройка пера для линии - QPen linePen = isSelected ? QPen(Qt::red, 4) : QPen(Qt::black, 2); - p.setPen(linePen); + // Настройка пера для линии + QPen linePen = isSelected ? QPen(Qt::red, 4) : QPen(Qt::black, 2); + p.setPen(linePen); - // Рисуем линию - p.drawLine( - QPointF(*line->p1.x, *line->p1.y), - QPointF(*line->p2.x, *line->p2.y) - ); + // Рисуем линию + p.drawLine( + QPointF(*line->p1.x, *line->p1.y), + QPointF(*line->p2.x, *line->p2.y) + ); - // Рисуем конечные точки линии - QBrush pointBrush = isSelected ? QBrush(Qt::red) : QBrush(Qt::darkBlue); - p.setBrush(pointBrush); - p.setPen(Qt::NoPen); + // Рисуем конечные точки линии + QBrush pointBrush = isSelected ? QBrush(Qt::red) : QBrush(Qt::darkBlue); + p.setBrush(pointBrush); + p.setPen(Qt::NoPen); - p.drawEllipse(QPointF(*line->p1.x, *line->p1.y), 5, 5); - p.drawEllipse(QPointF(*line->p2.x, *line->p2.y), 5, 5); + p.drawEllipse(QPointF(*line->p1.x, *line->p1.y), 5, 5); + p.drawEllipse(QPointF(*line->p2.x, *line->p2.y), 5, 5); + } + else if (Circle* circle = dynamic_cast(curve)) { + + // Настройка пера для линии + QPen linePen = QPen(Qt::black, 2); + p.setPen(linePen); + + p.drawEllipse(QPointF(*circle->center.x, *circle->center.y), *circle->rad, *circle->rad); + QBrush pointBrush = QBrush(Qt::darkBlue); + p.setBrush(pointBrush); + p.setPen(Qt::NoPen); + p.drawEllipse(QPointF(*circle->center.x, *circle->center.y), 5, 5); + } } // ====================== Подсветка выбранной точки (режим Coincedent) ====================== @@ -781,19 +805,19 @@ void Canvas::leaveEvent(QEvent* event) #ifdef _DEBUG void Canvas::showObjectTag(QPointF pos) { - QPointF l = screenToLogical(pos); - Line* lineUnderCursor = findAt(l, 1.0); - if (lineUnderCursor && lineUnderCursor != draggedLine) { - QPointF p1(*lineUnderCursor->p1.x, *lineUnderCursor->p1.y); - QPointF p2(*lineUnderCursor->p2.x, *lineUnderCursor->p2.y); - QLineF info_line(p1, p2); - QString Text = QString("Line %1\nLength = %2mm") - .arg(lineUnderCursor->get_tag() + 1) - .arg(info_line.length()); - QToolTip::showText(mapToGlobal(pos.toPoint()), Text, this); - } - else - QToolTip::hideText(); + //QPointF l = screenToLogical(pos); + //Line* lineUnderCursor = findAt(l, 1.0); + //if (lineUnderCursor && lineUnderCursor != draggedLine) { + // QPointF p1(*lineUnderCursor->p1.x, *lineUnderCursor->p1.y); + // QPointF p2(*lineUnderCursor->p2.x, *lineUnderCursor->p2.y); + // QLineF info_line(p1, p2); + // QString Text = QString("Line %1\nLength = %2mm") + // .arg(lineUnderCursor->get_tag() + 1) + // .arg(info_line.length()); + // QToolTip::showText(mapToGlobal(pos.toPoint()), Text, this); + //} + //else + // QToolTip::hideText(); } #endif @@ -841,16 +865,13 @@ void Canvas::solve_for_canvas() } else { sys.applySolution(); - // for (Curve* curve : curve){ - // if (Line* line = dynamic_cast(curve)) { - // ... - // } - // } - for (Line* line : lines) { - if (abs(*line->p1.x - *line->p2.x) < EPS && abs(*line->p1.y - *line->p2.y) < EPS && after_constraint) { - sys.undoSolution(); - flag = true; - break; + for (Curve* curve : curves) { + if (Line* line = dynamic_cast(curve)) { + if (abs(*line->p1.x - *line->p2.x) < EPS && abs(*line->p1.y - *line->p2.y) < EPS && after_constraint) { + sys.undoSolution(); + flag = true; + break; + } } } } @@ -885,19 +906,15 @@ void Canvas::clearCanvas() delete pt; } - // for (Curve* curve : curve){ - // delete curve; - // } - - for (Line* line : lines) { - delete line; + for (Curve* curve : curves){ + delete curve; } + // Очистка контейнеров params.clear(); points.clear(); - lines.clear(); - // curves.clear(); + curves.clear(); // Очистка контейнеров ограничений parallelPairs.clear(); diff --git a/Canvas.h b/Canvas.h index 4df0b52..8661fcc 100644 --- a/Canvas.h +++ b/Canvas.h @@ -169,7 +169,7 @@ private: * @param tolerance Допуск поиска * @return Найденная линия или nullptr */ - Line* findAt(QPointF& pos, qreal tolerance = 5.0); + Curve* findAt(QPointF& pos, qreal tolerance = 5.0); /** * @brief Найти точку в указанной позиции @@ -255,9 +255,7 @@ private: // ====================== Данные геометрической системы ====================== System sys; ///< Геометрический солвер - QVector lines; ///< Завершённые линии - QVector circles; ///< Завершённые окружности - QVector curves; + QVector curves; ///< Геометрические кривые QVector points; ///< Все точки сцены std::vector params; ///< Все параметры, передаваемые в солвер @@ -270,6 +268,7 @@ private: // ====================== Временные данные для режимов ====================== Line* current_line{ nullptr }; ///< Текущая линия в режимах рисования/параллельности + Circle* current_circle{ nullptr }; Point* firstPoint{ nullptr }; ///< Первая точка в режиме совпадения Mode mode{ Mode::None }; ///< Текущий режим работы diff --git a/GCS/Geo.cpp b/GCS/Geo.cpp index c8eae86..5c7a3b5 100644 --- a/GCS/Geo.cpp +++ b/GCS/Geo.cpp @@ -149,7 +149,7 @@ void Line::set_tag(int _tag) { p2.set_tag(_tag); } -int Line::get_tag() +int Curve::get_tag() { return tag; } @@ -275,6 +275,11 @@ Circle* Circle::Copy() return crv; } +void Circle::set_tag(int _tag) { + tag = _tag; + center.set_tag(tag); +} + //------------arc int Arc::PushOwnParams(VEC_pD& pvec) { diff --git a/GCS/Geo.h b/GCS/Geo.h index 42e183d..2b5ca35 100644 --- a/GCS/Geo.h +++ b/GCS/Geo.h @@ -173,6 +173,8 @@ public: /// A base class for all curve-based objects (line, circle/arc, ellipse/arc). class Curve { +protected: + int tag; public: virtual ~Curve() {} @@ -212,12 +214,13 @@ public: // DeepSOIC: I haven't found a way to simply copy a curve object provided pointer to a curve // object. virtual Curve* Copy() = 0; + + void set_tag(int); + int get_tag(); }; class Line: public Curve { -private: - int tag; public: Line() {} @@ -238,7 +241,6 @@ public: Line* Copy() override; void set_tag(int); - int get_tag(); bool contains(QPointF, qreal tol) const; }; @@ -253,12 +255,14 @@ public: ~Circle() override {} Point center; + Point* center_ref; double* rad; DeriVector2 CalculateNormal(const Point& p, const double* derivparam = nullptr) const override; DeriVector2 Value(double u, double du, const double* derivparam = nullptr) const override; int PushOwnParams(VEC_pD& pvec) override; void ReconstructOnNewPvec(VEC_pD& pvec, int& cnt) override; Circle* Copy() override; + void set_tag(int); }; class Arc: public Circle From 85d8e614d870161b99bdfbb9ea48f7d6e852d51d Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Wed, 24 Dec 2025 21:24:46 +0300 Subject: [PATCH 4/4] =?UTF-8?q?=D0=93=D0=BE=D1=82=D0=BE=D0=B2=D0=B0=D1=8F?= =?UTF-8?q?=20=D0=BE=D0=BA=D1=80=D1=83=D0=B6=D0=BD=D0=BE=D1=81=D1=82=D1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Пока без наложения базовых ограничений --- Canvas.cpp | 94 ++++++++++++++++++++++++++++++++------------------ Canvas.h | 1 + DRAWer_2_0.cpp | 6 ++++ DRAWer_2_0.h | 2 ++ DRAWer_2_0.ui | 35 +++++++++++-------- 5 files changed, 91 insertions(+), 47 deletions(-) diff --git a/Canvas.cpp b/Canvas.cpp index 492fef6..f39bfb8 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -98,6 +98,16 @@ Curve* Canvas::findAt(QPointF& pos, qreal tolerance) return line; } } + else if (Circle* circle = dynamic_cast(curve)) { + QPointF center(*circle->center.x, *circle->center.y); + double radius = *circle->rad; + + double distToCenter = dist_P2P(center, pos); + // Проверяем, лежит ли точка вблизи окружности (с допуском) + if (std::abs(distToCenter - radius) <= tolerance) { + return circle; + } + } } return nullptr; } @@ -240,7 +250,7 @@ void Canvas::mousePressEvent(QMouseEvent* event) Line* found = dynamic_cast(findAt(scene)); if (found) { - draggedLine = found; + draggedCurve = found; QPointF lineCenter( (*found->p1.x + *found->p2.x) / 2.0, (*found->p1.y + *found->p2.y) / 2.0 @@ -251,7 +261,9 @@ void Canvas::mousePressEvent(QMouseEvent* event) Circle* found_circle = dynamic_cast(findAt(scene)); if (found_circle) { - // TODO + draggedCurve = found_circle; + QPointF center(*found_circle->center.x, *found_circle->center.y); + dragOffset = scene - center; return; } } @@ -401,6 +413,7 @@ void Canvas::mousePressEvent(QMouseEvent* event) mode = Mode::None; } solve_for_canvas(); + return; } // ====================== Режим Parallel: задание параллельности ====================== else if (mode == Mode::Parallel) { @@ -581,45 +594,60 @@ void Canvas::mouseMoveEvent(QMouseEvent* event) } } } - - solve_for_canvas(); } // ====================== Перемещение линии ====================== - else if (draggedLine) { - QPointF newCenter = UCS_POSITION - dragOffset; - QPointF oldCenter( - (*draggedLine->p1.x + *draggedLine->p2.x) / 2.0, - (*draggedLine->p1.y + *draggedLine->p2.y) / 2.0 - ); + else if (draggedCurve) { + if (Line* draggedLine = dynamic_cast(draggedCurve)) { + QPointF newCenter = UCS_POSITION - dragOffset; + QPointF oldCenter( + (*draggedLine->p1.x + *draggedLine->p2.x) / 2.0, + (*draggedLine->p1.y + *draggedLine->p2.y) / 2.0 + ); - // Вычисляем смещение - double dx = newCenter.x() - oldCenter.x(); - double dy = newCenter.y() - oldCenter.y(); + // Вычисляем смещение + double dx = newCenter.x() - oldCenter.x(); + double dy = newCenter.y() - oldCenter.y(); - // Перемещаем обе точки линии - Point* linePoints[2] = { draggedLine->start_ref, draggedLine->end_ref }; + // Перемещаем обе точки линии + Point* linePoints[2] = { draggedLine->start_ref, draggedLine->end_ref }; - for (int i = 0; i < 2; i++) { - Point* currentPoint = linePoints[i]; + for (int i = 0; i < 2; i++) { + Point* currentPoint = linePoints[i]; - *currentPoint->x += dx; - *currentPoint->y += dy; + *currentPoint->x += dx; + *currentPoint->y += dy; - // Обновляем совпадающие точки - for (Point* pair : points) { - if (pair != currentPoint && areCoincident(currentPoint, pair)) { - *pair->x = *currentPoint->x; - *pair->y = *currentPoint->y; + // Обновляем совпадающие точки + for (Point* pair : points) { + if (pair != currentPoint && areCoincident(currentPoint, pair)) { + *pair->x = *currentPoint->x; + *pair->y = *currentPoint->y; + } + } + } + } + else if (Circle* circle = dynamic_cast(draggedCurve)) { + QPointF newCenter = UCS_POSITION - dragOffset; + *circle->center.x = newCenter.x(); + *circle->center.y = newCenter.y(); + *circle->center_ref->x = newCenter.x(); + *circle->center_ref->y = newCenter.y(); + + // Также обновляем все совпадающие точки (если центр совпадает с другими точками через P2P) + for (Point* other : points) { + if (other != circle->center_ref && areCoincident(circle->center_ref, other)) { + *other->x = newCenter.x(); + *other->y = newCenter.y(); } } } - solve_for_canvas(); } #ifdef _DEBUG else showObjectTag(WIDGET_POSITION); #endif + solve_for_canvas(); } void Canvas::mouseReleaseEvent(QMouseEvent* event) @@ -631,8 +659,8 @@ void Canvas::mouseReleaseEvent(QMouseEvent* event) solve_for_canvas(); } - if (draggedLine) { - draggedLine = nullptr; + if (draggedCurve) { + draggedCurve = nullptr; solve_for_canvas(); } @@ -681,16 +709,16 @@ void Canvas::paintEvent(QPaintEvent* event) p.drawEllipse(QPointF(*line->p2.x, *line->p2.y), 5, 5); } else if (Circle* circle = dynamic_cast(curve)) { + p.setPen(QPen(Qt::black, 2)); + p.setBrush(Qt::NoBrush); - // Настройка пера для линии - QPen linePen = QPen(Qt::black, 2); - p.setPen(linePen); + p.drawEllipse(QPointF(*circle->center.x, *circle->center.y), + *circle->rad, *circle->rad); - p.drawEllipse(QPointF(*circle->center.x, *circle->center.y), *circle->rad, *circle->rad); - QBrush pointBrush = QBrush(Qt::darkBlue); - p.setBrush(pointBrush); + p.setBrush(QBrush(Qt::darkBlue)); p.setPen(Qt::NoPen); p.drawEllipse(QPointF(*circle->center.x, *circle->center.y), 5, 5); + p.setBrush(Qt::NoBrush); } } diff --git a/Canvas.h b/Canvas.h index 8661fcc..0f444cc 100644 --- a/Canvas.h +++ b/Canvas.h @@ -251,6 +251,7 @@ private: // ====================== Данные для перемещения объектов ====================== Point* draggedPoint{ nullptr }; ///< Точка, которую перемещают Line* draggedLine{ nullptr }; ///< Линия, которую перемещают + Curve* draggedCurve { nullptr }; QPointF dragOffset; ///< Смещение при начале перемещения // ====================== Данные геометрической системы ====================== diff --git a/DRAWer_2_0.cpp b/DRAWer_2_0.cpp index 7c62787..9a95dad 100644 --- a/DRAWer_2_0.cpp +++ b/DRAWer_2_0.cpp @@ -43,3 +43,9 @@ void DRAWer_2_0::on_Perpendicular_Button_clicked() ui.widget->changeMode(Mode::Perpendicular); } + +void DRAWer_2_0::on_Circle_Button_clicked() +{ + ui.widget->changeMode(Mode::DrawingCircle); +} + diff --git a/DRAWer_2_0.h b/DRAWer_2_0.h index a4e5f87..df1232a 100644 --- a/DRAWer_2_0.h +++ b/DRAWer_2_0.h @@ -24,6 +24,8 @@ private slots: void on_Perpendicular_Button_clicked(); + void on_Circle_Button_clicked(); + private: Ui::DRAWer_2_0Class ui; }; diff --git a/DRAWer_2_0.ui b/DRAWer_2_0.ui index 88e5956..66f3857 100644 --- a/DRAWer_2_0.ui +++ b/DRAWer_2_0.ui @@ -28,19 +28,6 @@ - - - - - 75 - 24 - - - - Line - - - @@ -58,6 +45,26 @@ + + + + + 75 + 24 + + + + Line + + + + + + + Circle + + + @@ -163,7 +170,7 @@ 0 0 776 - 21 + 22