From 5a1ab90730817783169af432e3d9ba46270baa8f Mon Sep 17 00:00:00 2001 From: ParkSuMin Date: Thu, 25 Dec 2025 19:27:36 +0300 Subject: [PATCH] =?UTF-8?q?=D0=9E=D0=B1=D1=80=D0=B0=D0=B1=D0=BE=D1=82?= =?UTF-8?q?=D1=87=D0=B8=D0=BA=D0=B8=20=D0=BA=D0=BD=D0=BE=D0=BF=D0=BE=D0=BA?= =?UTF-8?q?=20=D0=B2=D1=8B=D0=B4=D0=B5=D0=BB=D0=B5=D0=BD=D1=8B=20=D0=B2=20?= =?UTF-8?q?=D0=BE=D1=82=D0=B4=D0=B5=D0=BB=D1=8C=D0=BD=D1=8B=D0=B5=20=D1=81?= =?UTF-8?q?=D1=83=D1=89=D0=BD=D0=BE=D1=81=D1=82=D0=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Canvas.cpp | 875 ++++++++++++++++++++++++++++------------------------- Canvas.h | 12 + System.h | 20 +- 3 files changed, 478 insertions(+), 429 deletions(-) diff --git a/Canvas.cpp b/Canvas.cpp index 631426c..f372633 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -223,6 +223,12 @@ void Canvas::remove_constraint(int tag) } break; } + case Mode::Tangent: { + if (auto* pair = std::get_if(&info.data)) { + tangentPairs.erase(*pair); + } + break; + } default: break; } @@ -237,426 +243,41 @@ void Canvas::mousePressEvent(QMouseEvent* event) { QPointF scene = UCS_POSITION; -#ifdef _DEBUG + #ifdef _DEBUG qDebug() << "Scene point in" << scene.x() << scene.y(); -#endif + #endif - // ====================== Режим None: перемещение объектов ====================== - if (mode == Mode::None) { - Point* p = findPointAt(scene); - if (p) { - draggedPoint = p; - getCoincidentGroup(draggedPoint); - dragOffset = scene - QPointF(*p->x, *p->y); - return; - } - - Line* found = CURVE_AS_LINE(findAt(scene)); - if (found) { - draggedCurve = found; - QPointF lineCenter( - (*found->p1.x + *found->p2.x) / 2.0, - (*found->p1.y + *found->p2.y) / 2.0 - ); - dragOffset = scene - lineCenter; - return; - } - - Circle* found_circle = CURVE_AS_CIRCLE(findAt(scene)); - if (found_circle) { - draggedCurve = found_circle; - QPointF center(*found_circle->center.x, *found_circle->center.y); - dragOffset = scene - center; - return; - } - } - - // ====================== Режим Horizontal/Vertical ====================== - else if (mode == Mode::Horizontal || mode == Mode::Vertical) { - Line* found = CURVE_AS_LINE(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++); - auto pair = makeOrderedPair(found->start_ref, found->end_ref); - HORIZ_pairs.insert(pair); - C_Info[constraints_count - 1] = { Mode::Horizontal, pair }; - } - else { - sys.addConstraintVertical(*found, constraints_count++); - auto pair = makeOrderedPair(found->start_ref, found->end_ref); - VERT_pairs.insert(pair); - C_Info[constraints_count - 1] = { Mode::Vertical, pair }; - } - solve_for_canvas(); - after_constraint = true; - } - mode = Mode::None; - } - - // ====================== Режим DrawingLine: рисование линий ====================== - else if (mode == Mode::DrawingLine) { - if (!current_line) { - // Первый клик: создаем новую линию - current_line = new Line(); - - // Создаем координаты для точек линии - double* x1 = new double(scene.x()); - double* y1 = new double(scene.y()); - double* x2 = new double(scene.x()); - double* y2 = new double(scene.y()); - - // Добавляем параметры в солвер - params.push_back(x1); - params.push_back(y1); - - // Создаем точки и привязываем к линии - points.push_back(new Point(x1, y1, obj_count++)); - points.push_back(new Point(x2, y2, obj_count++)); - - current_line->p1.x = x1; - current_line->p1.y = y1; - current_line->p2.x = x2; - current_line->p2.y = y2; - current_line->start_ref = points[points.size() - 2]; - current_line->end_ref = points[points.size() - 1]; - } - else { - // Второй клик: завершаем рисование линии - *current_line->p2.x = scene.x(); - *current_line->p2.y = scene.y(); - - // Проверка минимальной длины линии - double len = sqrt(pow(*current_line->p2.x - *current_line->p1.x, 2) + - pow(*current_line->p2.y - *current_line->p1.y, 2)); - - if (len < 10) { - // Линия слишком короткая - отменяем создание - delete current_line; - current_line = nullptr; - - // Удаляем созданные точки и параметры - delete points.back(); - points.pop_back(); - delete points.back(); - points.pop_back(); - delete params.back(); - params.pop_back(); - delete params.back(); - params.pop_back(); - - mode = Mode::None; - QMessageBox::critical(this, "WHOOPS", - "Sorry, your line is very short", QMessageBox::Ok); - solve_for_canvas(); - return; - } - - // Добавляем координаты второй точки в параметры - params.push_back(current_line->p2.x); - params.push_back(current_line->p2.y); - - current_line->set_tag(obj_count++); - // Завершаем создание линии - curves.append(current_line); - current_line = nullptr; - mode = Mode::None; - } - 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(); - return; - } - // ====================== Режим Parallel: задание параллельности ====================== - else if (mode == Mode::Parallel) { - Line* found = CURVE_AS_LINE(findAt(scene)); - - if (!found) { - current_line = nullptr; - solve_for_canvas(); - return; - } - - // Первый клик: выбираем первую линию - if (!current_line) { - current_line = found; - solve_for_canvas(); - return; - } - - // Повторный клик на ту же линию: сброс выбора - if (found == current_line) { - current_line = nullptr; - solve_for_canvas(); - return; - } - - // Второй клик на другую линию: добавляем ограничение параллельности - if (!areAlreadyParallel(found, current_line)) { - auto pair = makeOrderedPair(found, current_line); - sys.addConstraintParallel(*found, *current_line, constraints_count++); - parallelPairs.insert(pair); - C_Info[constraints_count - 1] = { Mode::Parallel, pair }; - - current_line = nullptr; - mode = Mode::None; - after_constraint = true; - solve_for_canvas(); - } - else { - // Линии уже параллельны - сообщаем об ошибке -#ifdef _DEBUG - qDebug() << "Line" << current_line << "and" << found << "are parallel. Abort!"; -#endif - - QMessageBox::warning(this, - QString("Wrong"), - QString("Parallel lines can not be more parallel!"), - QMessageBox::Ok - ); - current_line = nullptr; - solve_for_canvas(); - return; - } - } - - // ====================== Режим Coincedent: совпадение точек ====================== - else if (mode == Mode::Coincedent) { - Point* clickedPoint = findPointAt(scene); - if (!clickedPoint) { - firstPoint = nullptr; - solve_for_canvas(); - return; - } - - // Первый клик: выбираем первую точку - if (!firstPoint) { - firstPoint = clickedPoint; - solve_for_canvas(); - return; - } - - // Повторный клик на ту же точку: сброс выбора - if (clickedPoint == firstPoint) { - firstPoint = nullptr; - solve_for_canvas(); - return; - } - - // Находим линии, к которым принадлежат точки - Line* l1 = nullptr; - Line* l2 = nullptr; - - for (Curve* curve : curves) { - if (Line* l = CURVE_AS_LINE(curve)) { - if (l->start_ref == firstPoint || l->end_ref == firstPoint) - l1 = l; - if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) - l2 = l; - } - } - - // Проверка на невозможность ограничения - if ((l1 == l2 && l1 && l2) || areCoincident(firstPoint, clickedPoint)) { - QMessageBox::critical(this, QString("NO!"), QString("P2P failed")); - firstPoint = nullptr; - mode = Mode::None; - solve_for_canvas(); - return; - } - - // Добавляем ограничение совпадения точек - sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++); - auto pair = makeOrderedPair(clickedPoint, firstPoint); - P2Ppairs.insert(pair); - C_Info[constraints_count - 1] = { Mode::Coincedent, pair }; - - firstPoint = nullptr; - mode = Mode::None; - after_constraint = true; - solve_for_canvas(); - return; - } - - else if (mode == Mode::Perpendicular) { - Line* found = CURVE_AS_LINE(findAt(scene)); - - if (!found) { - current_line = nullptr; - solve_for_canvas(); - return; - } - - // Первый клик: выбираем первую линию - if (!current_line) { - current_line = found; - solve_for_canvas(); - return; - } - - // Повторный клик на ту же линию: сброс выбора - if (found == current_line) { - current_line = nullptr; - solve_for_canvas(); - return; - } - - if (!areAlreadyPerpendicular(found, current_line)) { - auto pair = makeOrderedPair(found, current_line); - sys.addConstraintPerpendicular(*found, *current_line, constraints_count++); - perpendicularPairs.insert(pair); - C_Info[constraints_count - 1] = { Mode::Perpendicular, pair }; - - current_line = nullptr; - mode = Mode::None; - after_constraint = true; - solve_for_canvas(); - } - else { - - QMessageBox::warning(this, - QString("Wrong"), - QString("Perpendicular lines can not be more perpendicular!"), - QMessageBox::Ok - ); - current_line = nullptr; - solve_for_canvas(); - return; - } - } - - else if (mode == Mode::Tangent) { - // Ищем любой объект под курсором: линия или окружность - Curve* selected = findAt(scene); - - if (!selected) { - current_curve = nullptr; - update(); - return; - } - - // Если кликнули по уже выбранному объекту — сброс - if (current_curve && selected == current_curve) { - current_curve = nullptr; - update(); - return; - } - - // Первый выбор - if (!current_curve) { - current_curve = selected; - update(); // подсветим выбранный объект - return; - } - - // Второй выбор — теперь у нас два объекта - Curve* first = current_curve; - Curve* second = selected; - - // Проверка на уже существующее ограничение касательности - if (areAlreadyTangent(first, second)) { - QMessageBox::warning(this, "Ошибка", - "Эти объекты уже касательны!", QMessageBox::Ok); - current_curve = nullptr; - update(); - return; - } - - QString message; - bool constraintAdded = false; - - // Вариант 1: Линия → Окружность - if (Line* line = dynamic_cast(first)) { - if (Circle* circle = dynamic_cast(second)) { - sys.addConstraintTangent(*line, *circle, constraints_count++); - constraintAdded = true; - } - } - // Вариант 2: Окружность → Линия - else if (Circle* circle = dynamic_cast(first)) { - if (Line* line = dynamic_cast(second)) { - sys.addConstraintTangent(*line, *circle, constraints_count++); // порядок Line, Circle - constraintAdded = true; - } - } - // Вариант 3: Окружность → Окружность - if (Circle* c1 = dynamic_cast(first)) { - if (Circle* c2 = dynamic_cast(second)) { - sys.addConstraintTangent(*c1, *c2, constraints_count++); - constraintAdded = true; - } - } - - // Если комбинация недопустима - if (!constraintAdded) { - message = "Недопустимая комбинация объектов для касания!\n" - "Поддерживаются: линия-окружность или окружность-окружность."; - QMessageBox::warning(this, "Ошибка", message, QMessageBox::Ok); - } - else { - // Сохраняем информацию об ограничении (для undo и удаления) - auto orderedPair = makeOrderedPair(first, second); - tangentPairs.insert(orderedPair); - C_Info[constraints_count - 1] = { Mode::Tangent, orderedPair }; - after_constraint = true; - } - - // Сброс режима и выделения - current_curve = nullptr; - mode = Mode::None; - solve_for_canvas(); - update(); + switch (mode) + { + case Mode::None: + ON_NONE(&scene); + break; + case Mode::DrawingLine: + ON_LINE(&scene); + break; + case Mode::Parallel: + ON_PARALLEL(&scene); + break; + case Mode::Coincedent: + ON_P2P(&scene); + break; + case Mode::Horizontal: + ON_HORIZ_VERT(&scene); + break; + case Mode::Vertical: + ON_HORIZ_VERT(&scene); + break; + case Mode::Perpendicular: + ON_PERPENDICULAR(&scene); + break; + case Mode::DrawingCircle: + ON_CIRCLE(&scene); + break; + case Mode::Tangent: + ON_TANGENT(&scene); + break; + default: + break; } } @@ -1074,4 +695,420 @@ void Canvas::clearCanvas() update(); groups.clear(); -} \ No newline at end of file +} + +void Canvas::ON_NONE(QPointF* scene) +{ + Point* p = findPointAt(*scene); + if (p) { + draggedPoint = p; + getCoincidentGroup(draggedPoint); + dragOffset = *scene - QPointF(*p->x, *p->y); + return; + } + + Line* found = CURVE_AS_LINE(findAt(*scene)); + if (found) { + draggedCurve = found; + QPointF lineCenter( + (*found->p1.x + *found->p2.x) / 2.0, + (*found->p1.y + *found->p2.y) / 2.0 + ); + dragOffset = *scene - lineCenter; + return; + } + + Circle* found_circle = CURVE_AS_CIRCLE(findAt(*scene)); + if (found_circle) { + draggedCurve = found_circle; + QPointF center(*found_circle->center.x, *found_circle->center.y); + dragOffset = *scene - center; + return; + } + + return; +} + +void Canvas::ON_LINE(QPointF* pos) +{ + QPointF scene = *pos; + + if (!current_line) { + // Первый клик: создаем новую линию + current_line = new Line(); + + // Создаем координаты для точек линии + double* x1 = new double(scene.x()); + double* y1 = new double(scene.y()); + double* x2 = new double(scene.x()); + double* y2 = new double(scene.y()); + + // Добавляем параметры в солвер + params.push_back(x1); + params.push_back(y1); + + // Создаем точки и привязываем к линии + points.push_back(new Point(x1, y1, obj_count++)); + points.push_back(new Point(x2, y2, obj_count++)); + + current_line->p1.x = x1; + current_line->p1.y = y1; + current_line->p2.x = x2; + current_line->p2.y = y2; + current_line->start_ref = points[points.size() - 2]; + current_line->end_ref = points[points.size() - 1]; + } + else { + // Второй клик: завершаем рисование линии + *current_line->p2.x = scene.x(); + *current_line->p2.y = scene.y(); + + // Проверка минимальной длины линии + double len = sqrt(pow(*current_line->p2.x - *current_line->p1.x, 2) + + pow(*current_line->p2.y - *current_line->p1.y, 2)); + + if (len < 10) { + // Линия слишком короткая - отменяем создание + delete current_line; + current_line = nullptr; + + // Удаляем созданные точки и параметры + delete points.back(); + points.pop_back(); + delete points.back(); + points.pop_back(); + delete params.back(); + params.pop_back(); + delete params.back(); + params.pop_back(); + + mode = Mode::None; + QMessageBox::critical(this, "WHOOPS", + "Sorry, your line is very short", QMessageBox::Ok); + solve_for_canvas(); + return; + } + + // Добавляем координаты второй точки в параметры + params.push_back(current_line->p2.x); + params.push_back(current_line->p2.y); + + current_line->set_tag(obj_count++); + // Завершаем создание линии + curves.append(current_line); + current_line = nullptr; + mode = Mode::None; + } + solve_for_canvas(); + return; +} +void Canvas::ON_CIRCLE(QPointF* pos) +{ + QPointF scene = *pos; + 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(); + return; +} + +void Canvas::ON_PARALLEL(QPointF* scene) +{ + Line* found = CURVE_AS_LINE(findAt(*scene)); + + if (!found) { + current_line = nullptr; + solve_for_canvas(); + return; + } + + // Первый клик: выбираем первую линию + if (!current_line) { + current_line = found; + solve_for_canvas(); + return; + } + + // Повторный клик на ту же линию: сброс выбора + if (found == current_line) { + current_line = nullptr; + solve_for_canvas(); + return; + } + + // Второй клик на другую линию: добавляем ограничение параллельности + if (!areAlreadyParallel(found, current_line)) { + auto pair = makeOrderedPair(found, current_line); + sys.addConstraintParallel(*found, *current_line, constraints_count++); + parallelPairs.insert(pair); + C_Info[constraints_count - 1] = { Mode::Parallel, pair }; + + current_line = nullptr; + mode = Mode::None; + after_constraint = true; + solve_for_canvas(); + } + else { + // Линии уже параллельны - сообщаем об ошибке + QMessageBox::warning(this, + QString("Wrong"), + QString("Parallel lines can not be more parallel!"), + QMessageBox::Ok + ); + current_line = nullptr; + solve_for_canvas(); + return; + } +} +void Canvas::ON_PERPENDICULAR(QPointF* scene) +{ + Line* found = CURVE_AS_LINE(findAt(*scene)); + + if (!found) { + current_line = nullptr; + solve_for_canvas(); + return; + } + + // Первый клик: выбираем первую линию + if (!current_line) { + current_line = found; + solve_for_canvas(); + return; + } + + // Повторный клик на ту же линию: сброс выбора + if (found == current_line) { + current_line = nullptr; + solve_for_canvas(); + return; + } + + if (!areAlreadyPerpendicular(found, current_line)) { + auto pair = makeOrderedPair(found, current_line); + sys.addConstraintPerpendicular(*found, *current_line, constraints_count++); + perpendicularPairs.insert(pair); + C_Info[constraints_count - 1] = { Mode::Perpendicular, pair }; + + current_line = nullptr; + mode = Mode::None; + after_constraint = true; + solve_for_canvas(); + } + else { + QMessageBox::warning(this, + QString("Wrong"), + QString("Perpendicular lines can not be more perpendicular!"), + QMessageBox::Ok + ); + current_line = nullptr; + solve_for_canvas(); + return; + } +} +void Canvas::ON_P2P(QPointF* scene) +{ + Point* clickedPoint = findPointAt(*scene); + if (!clickedPoint) { + firstPoint = nullptr; + solve_for_canvas(); + return; + } + + // Первый клик: выбираем первую точку + if (!firstPoint) { + firstPoint = clickedPoint; + solve_for_canvas(); + return; + } + + // Повторный клик на ту же точку: сброс выбора + if (clickedPoint == firstPoint) { + firstPoint = nullptr; + solve_for_canvas(); + return; + } + + // Находим линии, к которым принадлежат точки + Line* l1 = nullptr; + Line* l2 = nullptr; + + for (Curve* curve : curves) { + if (Line* l = CURVE_AS_LINE(curve)) { + if (l->start_ref == firstPoint || l->end_ref == firstPoint) + l1 = l; + if (l->start_ref == clickedPoint || l->end_ref == clickedPoint) + l2 = l; + } + } + + // Проверка на невозможность ограничения + if ((l1 == l2 && l1 && l2) || areCoincident(firstPoint, clickedPoint)) { + QMessageBox::critical(this, QString("NO!"), QString("P2P failed")); + firstPoint = nullptr; + mode = Mode::None; + solve_for_canvas(); + return; + } + + // Добавляем ограничение совпадения точек + sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++); + auto pair = makeOrderedPair(clickedPoint, firstPoint); + P2Ppairs.insert(pair); + C_Info[constraints_count - 1] = { Mode::Coincedent, pair }; + + firstPoint = nullptr; + mode = Mode::None; + after_constraint = true; + solve_for_canvas(); + return; +} +void Canvas::ON_TANGENT(QPointF* scene) +{ + // Ищем любой объект под курсором: линия или окружность + Curve* selected = findAt(*scene); + + if (!selected) { + current_curve = nullptr; + update(); + return; + } + + // Если кликнули по уже выбранному объекту — сброс + if (current_curve && selected == current_curve) { + current_curve = nullptr; + update(); + return; + } + + // Первый выбор + if (!current_curve) { + current_curve = selected; + update(); // подсветим выбранный объект + return; + } + + // Второй выбор — теперь у нас два объекта + Curve* first = current_curve; + Curve* second = selected; + + // Проверка на уже существующее ограничение касательности + if (areAlreadyTangent(first, second)) { + QMessageBox::warning(this, "Ошибка", + "Эти объекты уже касательны!", QMessageBox::Ok); + current_curve = nullptr; + update(); + return; + } + + bool constraintAdded = false; + + // Вариант 1: Линия → Окружность + if (Line* line = dynamic_cast(first)) { + if (Circle* circle = dynamic_cast(second)) { + sys.addConstraintTangent(*line, *circle, constraints_count++); + constraintAdded = true; + } + } + // Вариант 2: Окружность → Линия + else if (Circle* circle = dynamic_cast(first)) { + if (Line* line = dynamic_cast(second)) { + sys.addConstraintTangent(*line, *circle, constraints_count++); // порядок Line, Circle + constraintAdded = true; + } + } + // Вариант 3: Окружность → Окружность + if (Circle* c1 = dynamic_cast(first)) { + if (Circle* c2 = dynamic_cast(second)) { + sys.addConstraintTangent(*c1, *c2, constraints_count++); + constraintAdded = true; + } + } + + // Если комбинация недопустима + if (!constraintAdded) { + QString message = "Недопустимая комбинация объектов для касания!\n" + "Поддерживаются: линия-окружность или окружность-окружность."; + QMessageBox::warning(this, "Ошибка", message, QMessageBox::Ok); + } + else { + // Сохраняем информацию об ограничении (для undo и удаления) + auto orderedPair = makeOrderedPair(first, second); + tangentPairs.insert(orderedPair); + C_Info[constraints_count - 1] = { Mode::Tangent, orderedPair }; + after_constraint = true; + } + + // Сброс режима и выделения + current_curve = nullptr; + mode = Mode::None; + solve_for_canvas(); +} +void Canvas::ON_HORIZ_VERT(QPointF* scene) +{ + Line* found = CURVE_AS_LINE(findAt(*scene)); + + if (found) { + // Проверка: если линия уже вертикальна, нельзя сделать её горизонтальной + if (mode == Mode::Horizontal && isLineVertical(found)) { + QMessageBox::warning(this, + QString("Невозможно"), + QString("Эта линия уже вертикальна и не может быть горизонтальной!"), + QMessageBox::Ok + ); + mode = Mode::None; + return; + } + + // Проверка: если линия уже горизонтальна, нельзя сделать её вертикальной + else 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++); + auto pair = makeOrderedPair(found->start_ref, found->end_ref); + HORIZ_pairs.insert(pair); + C_Info[constraints_count - 1] = { Mode::Horizontal, pair }; + } + else { + sys.addConstraintVertical(*found, constraints_count++); + auto pair = makeOrderedPair(found->start_ref, found->end_ref); + VERT_pairs.insert(pair); + C_Info[constraints_count - 1] = { Mode::Vertical, pair }; + } + solve_for_canvas(); + after_constraint = true; + } + mode = Mode::None; + return; +} diff --git a/Canvas.h b/Canvas.h index a5a5909..9c5489b 100644 --- a/Canvas.h +++ b/Canvas.h @@ -207,6 +207,18 @@ private: */ void clearCanvas(); + // ===================== Обработчики кнопок ============================== + void ON_NONE(QPointF*); + + void ON_LINE(QPointF*); + void ON_CIRCLE(QPointF*); + + void ON_PARALLEL(QPointF*); + void ON_PERPENDICULAR(QPointF*); + void ON_P2P(QPointF*); + void ON_TANGENT(QPointF*); + void ON_HORIZ_VERT(QPointF*); + // ====================== Данные для перемещения объектов ====================== Point* draggedPoint{ nullptr }; ///< Точка, которую перемещают Line* draggedLine{ nullptr }; ///< Линия, которую перемещают diff --git a/System.h b/System.h index 0a0c6fb..cd5d1de 100644 --- a/System.h +++ b/System.h @@ -9,6 +9,15 @@ #include "GCS/GCS.h" using namespace GCS; +/// Удобный тип для хранения пары линий (порядок не важен) +using LinePair = std::pair; + +/// Удобный тип для хранения пары точек (порядок не важен) +using PointPair = std::pair; + +/// Удобный тип для хранения пары кривых (порядок не важен) +using CurvePair = std::pair; + #include #include #include @@ -61,13 +70,4 @@ struct ConstraintInfo { // =================================================================== // Типы и перечисления -// =================================================================== - -/// Удобный тип для хранения пары линий (порядок не важен) -using LinePair = std::pair; - -/// Удобный тип для хранения пары точек (порядок не важен) -using PointPair = std::pair; - -/// Удобный тип для хранения пары кривых (порядок не важен) -using CurvePair = std::pair; \ No newline at end of file +// =================================================================== \ No newline at end of file