diff --git a/Canvas.cpp b/Canvas.cpp index 793a1ef..4fe2876 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -53,6 +53,19 @@ bool Canvas::areHorizontalVertical(Point* p1, Point* p2, bool mode) return HORIZ_pairs.count(makeOrderedPair(p1, p2)); else return VERT_pairs.count(makeOrderedPair(p1, p2)); + +} + +bool Canvas::isLineHorizontal(Line* line) +{ + if (!line || !line->start_ref || !line->end_ref) return false; + return HORIZ_pairs.count(makeOrderedPair(line->start_ref, line->end_ref)); +} + +bool Canvas::isLineVertical(Line* line) +{ + if (!line || !line->start_ref || !line->end_ref) return false; + return VERT_pairs.count(makeOrderedPair(line->start_ref, line->end_ref)); } bool Canvas::areAlreadyParallel(Line* l1, Line* l2) @@ -60,6 +73,43 @@ bool Canvas::areAlreadyParallel(Line* l1, Line* l2) return parallelPairs.count(makeOrderedPair(l1, l2)); } +void Canvas::remove_constraints() +{ + sys.clearByTag(constraints_count - 1); + + switch (lastConstraint.mode) { + case Mode::Horizontal: { + if (auto* pair = std::get_if(&lastConstraint.data)) { + HORIZ_pairs.erase(*pair); + } + break; + } + case Mode::Vertical: { + if (auto* pair = std::get_if(&lastConstraint.data)) { + VERT_pairs.erase(*pair); + } + break; + } + case Mode::Parallel: { + if (auto* pair = std::get_if(&lastConstraint.data)) { + parallelPairs.erase(*pair); + } + break; + } + case Mode::Coincedent: { + if (auto* pair = std::get_if(&lastConstraint.data)) { + P2Ppairs.erase(*pair); + } + break; + } + default: + break; + } + + lastConstraint.mode = Mode::None; + constraints_count--; +} + void Canvas::mousePressEvent(QMouseEvent* event) { QPointF scene = event->pos(); @@ -92,18 +142,45 @@ void Canvas::mousePressEvent(QMouseEvent* event) Line* found = findAt(scene); if (found) { + if (mode == Mode::Horizontal && isLineVertical(found)) { + QMessageBox::warning(this, + QString("Невозможно"), + QString("Эта линия уже вертикальна и не может быть горизонтальной!"), + QMessageBox::Ok + ); + mode = Mode::None; + return; + } + + // Проверка: если линия уже горизонтальна, нельзя сделать её вертикальной + if (mode == Mode::Vertical && isLineHorizontal(found)) { + QMessageBox::warning(this, + QString("Невозможно"), + QString("Эта линия уже горизонтальна и не может быть вертикальной!"), + QMessageBox::Ok + ); + mode = Mode::None; + return; + } + if (mode == Mode::Horizontal) { sys.addConstraintHorizontal(*found, constraints_count++); - HORIZ_pairs.insert(makeOrderedPair(found->start_ref, found->end_ref)); + auto pair = makeOrderedPair(found->start_ref, found->end_ref); + HORIZ_pairs.insert(pair); + lastConstraint.mode = Mode::Horizontal; + lastConstraint.data = pair; } else { sys.addConstraintVertical(*found, constraints_count++); - VERT_pairs.insert(makeOrderedPair(found->start_ref, found->end_ref)); + auto pair = makeOrderedPair(found->start_ref, found->end_ref); + VERT_pairs.insert(pair); + lastConstraint.mode = Mode::Vertical; + lastConstraint.data = pair; } update(); + after_constraint = true; } mode = Mode::None; - after_constraint = true; } else if (mode == Mode::DrawingLine) { @@ -189,12 +266,16 @@ void Canvas::mousePressEvent(QMouseEvent* event) } if (!areAlreadyParallel(found, current_line)) { + auto pair = makeOrderedPair(found, current_line); sys.addConstraintParallel(*found, *current_line, constraints_count++); - parallelPairs.insert(makeOrderedPair(found, current_line)); + parallelPairs.insert(pair); + lastConstraint.mode = Mode::Parallel; + lastConstraint.data = pair; + current_line = nullptr; - update(); mode = Mode::None; after_constraint = true; + update(); } else { @@ -251,7 +332,11 @@ void Canvas::mousePressEvent(QMouseEvent* event) } sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++); - P2Ppairs.insert(makeOrderedPair(clickedPoint, firstPoint)); + auto pair = makeOrderedPair(clickedPoint, firstPoint); + P2Ppairs.insert(pair); + lastConstraint.mode = Mode::Coincedent; + lastConstraint.data = pair; + firstPoint = nullptr; mode = Mode::None; after_constraint = true; @@ -338,8 +423,7 @@ void Canvas::paintEvent(QPaintEvent*) } else if (res == SolveStatus::Failed && after_constraint){ QMessageBox::warning(this, QString("Error!"), QString("Last constraint is unavailable!")); - sys.removeConstraint(sys.get_last_constraint()); - constraints_count--; + remove_constraints(); } after_constraint = false; } @@ -388,7 +472,6 @@ Canvas::Canvas(QWidget *parent) : QWidget(parent) { sys = System(); - current_line = nullptr; setMouseTracking(true); setBackgroundRole(QPalette::Base); setAutoFillBackground(true); @@ -396,19 +479,26 @@ Canvas::Canvas(QWidget *parent) Canvas::~Canvas() { - for (Line* line : lines) { - delete line; - } - for (double* param : params) { delete param; } - lines.clear(); + for (Point* pt : points) { + delete pt; + } + + for (Line* line : lines) { + delete line; + } + params.clear(); points.clear(); + lines.clear(); + parallelPairs.clear(); P2Ppairs.clear(); + VERT_pairs.clear(); + HORIZ_pairs.clear(); if (current_line) delete current_line; diff --git a/Canvas.h b/Canvas.h index c129e6a..ec40cd3 100644 --- a/Canvas.h +++ b/Canvas.h @@ -54,6 +54,8 @@ private: Point* findPointAt(QPointF, qreal tolerance = 5.0); bool areCoincident(Point*, Point*); bool areHorizontalVertical(Point*, Point*, bool); + bool isLineHorizontal(Line* line); // проверяет, горизонтальна ли линия + bool isLineVertical(Line* line); // проверяет, вертикальна ли линия // ====================== Параллельность ====================== bool areAlreadyParallel(Line* l1, Line* l2); // проверка на дубликат @@ -62,6 +64,8 @@ private: Line* draggedLine{ nullptr }; QPointF dragOffset; + // ====================== Работа с парами ограничений ====================== + void remove_constraints(); // ====================== Данные сцены ====================== System sys; // геометрический солвер QVector lines; // завершённые линии @@ -80,4 +84,10 @@ private: int obj_count{ 0 }; // тег для новых объектов int constraints_count{ 0 }; // тег для новых ограничений + + struct LastConstraint { + Mode mode{ Mode::None }; + std::variant data; + }; + LastConstraint lastConstraint; }; \ No newline at end of file