From 95f99575e256e304d9a6c71a0ea80e5bd3f4f4c5 Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Wed, 24 Dec 2025 20:36:54 +0300 Subject: [PATCH] =?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