Perpendicular #7

Merged
ParkSuMin merged 5 commits from Perpendicular into master 2025-12-15 20:46:36 +01:00
5 changed files with 88 additions and 44 deletions
Showing only changes of commit 72c0c24318 - Show all commits

View File

@@ -1,4 +1,6 @@
#include "Canvas.h"
#define WIDGET_POSITION event->pos()
#define UCS_POSITION screenToLogical(WIDGET_POSITION)
// ===================================================================
// Вспомогательные функции
@@ -181,6 +183,12 @@ void Canvas::remove_constraint(int tag)
}
break;
}
case Mode::Perpendicular: {
if (auto* pair = std::get_if<LinePair>(&info.data)) {
perpendicularPairs.erase(*pair);
}
break;
}
default:
break;
}
@@ -259,7 +267,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
VERT_pairs.insert(pair);
C_Info[constraints_count - 1] = { Mode::Vertical, pair };
}
update();
solve_for_canvas();
after_constraint = true;
}
mode = Mode::None;
@@ -320,7 +328,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
mode = Mode::None;
QMessageBox::critical(this, "WHOOPS",
"Sorry, your line is very short", QMessageBox::Ok);
update();
solve_for_canvas();
return;
}
@@ -335,7 +343,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
obj_count++;
after_constraint = true;
}
update();
solve_for_canvas();
return;
}
@@ -345,21 +353,21 @@ void Canvas::mousePressEvent(QMouseEvent* event)
if (!found) {
current_line = nullptr;
update();
solve_for_canvas();
return;
}
// Первый клик: выбираем первую линию
if (!current_line) {
current_line = found;
update();
solve_for_canvas();
return;
}
// Повторный клик на ту же линию: сброс выбора
if (found == current_line) {
current_line = nullptr;
update();
solve_for_canvas();
return;
}
@@ -373,7 +381,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
current_line = nullptr;
mode = Mode::None;
after_constraint = true;
update();
solve_for_canvas();
}
else {
// Линии уже параллельны - сообщаем об ошибке
@@ -387,7 +395,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
QMessageBox::Ok
);
current_line = nullptr;
update();
solve_for_canvas();
return;
}
}
@@ -397,21 +405,21 @@ void Canvas::mousePressEvent(QMouseEvent* event)
Point* clickedPoint = findPointAt(scene);
if (!clickedPoint) {
firstPoint = nullptr;
update();
solve_for_canvas();
return;
}
// Первый клик: выбираем первую точку
if (!firstPoint) {
firstPoint = clickedPoint;
update();
solve_for_canvas();
return;
}
// Повторный клик на ту же точку: сброс выбора
if (clickedPoint == firstPoint) {
firstPoint = nullptr;
update();
solve_for_canvas();
return;
}
@@ -430,7 +438,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
QMessageBox::critical(this, QString("NO!"), QString("P2P failed"));
firstPoint = nullptr;
mode = Mode::None;
update();
solve_for_canvas();
return;
}
@@ -443,7 +451,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
firstPoint = nullptr;
mode = Mode::None;
after_constraint = true;
update();
solve_for_canvas();
return;
}
@@ -452,21 +460,21 @@ void Canvas::mousePressEvent(QMouseEvent* event)
if (!found) {
current_line = nullptr;
update();
solve_for_canvas();
return;
}
// Первый клик: выбираем первую линию
if (!current_line) {
current_line = found;
update();
solve_for_canvas();
return;
}
// Повторный клик на ту же линию: сброс выбора
if (found == current_line) {
current_line = nullptr;
update();
solve_for_canvas();
return;
}
@@ -474,11 +482,12 @@ void Canvas::mousePressEvent(QMouseEvent* event)
auto pair = makeOrderedPair<LinePair>(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;
update();
solve_for_canvas();
}
else {
@@ -488,7 +497,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
QMessageBox::Ok
);
current_line = nullptr;
update();
solve_for_canvas();
return;
}
}
@@ -500,6 +509,9 @@ void Canvas::mouseMoveEvent(QMouseEvent* event)
if (draggedPoint) {
QPointF pos = UCS_POSITION - dragOffset;
*draggedPoint->x = pos.x();
*draggedPoint->y = pos.y();
// TODO
for (Point* pair : points) {
if (areCoincident(draggedPoint, pair)) {
@@ -525,9 +537,16 @@ void Canvas::mouseMoveEvent(QMouseEvent* event)
}
}
*draggedPoint->x = pos.x();
*draggedPoint->y = pos.y();
update();
for (Point* other : points) {
if (areHorizontalVertical(draggedPoint, other, true)) {
*other->x = pos.x();
}
if (areHorizontalVertical(draggedPoint, other, false)) {
*other->y = pos.y();
}
}
solve_for_canvas();
}
// ====================== Перемещение линии ======================
@@ -559,7 +578,7 @@ void Canvas::mouseMoveEvent(QMouseEvent* event)
}
}
}
update();
solve_for_canvas();
}
#ifdef _DEBUG
else
@@ -573,12 +592,12 @@ void Canvas::mouseReleaseEvent(QMouseEvent* event)
if (draggedPoint) {
draggedPoint = nullptr;
update();
solve_for_canvas();
}
if (draggedLine) {
draggedLine = nullptr;
update();
solve_for_canvas();
}
}
@@ -599,23 +618,6 @@ void Canvas::paintEvent(QPaintEvent* event)
p.drawLine(-5, 0, 5, 0);
p.drawLine(0, -5, 0, 5);
// ====================== Решение системы уравнений ======================
if (!params.empty()) {
int res = sys.solve(params);
if (res == SolveStatus::Success || res == SolveStatus::Converged) {
sys.applySolution();
}
else if (res == SolveStatus::Failed && after_constraint) {
// Ошибка решения: удаляем последнее добавленное ограничение
QMessageBox::warning(this, QString("Error!"),
QString("Last constraint is unavailable!"));
remove_constraint(constraints_count - 1);
constraints_count--;
}
after_constraint = false;
}
// ====================== Отрисовка линий ======================
for (Line* line : lines) {
bool isSelected = (mode == Mode::Parallel && line == current_line);
@@ -708,3 +710,30 @@ std::vector<Point*> Canvas::getCoincidentGroup(Point* p)
}
return group;
}
void Canvas::solve_for_canvas()
{
bool flag = false;
int res = sys.solve(params);
if (res != SolveStatus::Success && res != SolveStatus::Converged) {
flag = true;
}
else {
sys.applySolution();
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;
}
}
}
if (flag) {
QMessageBox::warning(this, QString("Error!"), QString("Last constraint is unavailable!"));
remove_constraint(constraints_count - 1);
constraints_count--;
}
after_constraint = false;
update();
}

View File

@@ -1,7 +1,5 @@
#pragma once
#define WIDGET_POSITION event->pos()
#define UCS_POSITION screenToLogical(WIDGET_POSITION)
constexpr auto EPS = 1e-9;
#include <QWidget>
#include <QMouseEvent>
@@ -148,4 +146,6 @@ private:
std::variant<LinePair, PointPair> data;
};
std::map<int, ConstraintInfo> C_Info;
void solve_for_canvas();
};

View File

@@ -40,3 +40,9 @@ void DRAWer_2_0::on_Vertical_Button_clicked()
ui.widget->changeMode(Mode::Vertical);
}
void DRAWer_2_0::on_Perpendicular_Button_clicked()
{
ui.widget->changeMode(Mode::Perpendicular);
}

View File

@@ -22,6 +22,8 @@ private slots:
void on_Vertical_Button_clicked();
void on_Perpendicular_Button_clicked();
private:
Ui::DRAWer_2_0Class ui;
int counter;

View File

@@ -52,6 +52,13 @@
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="Perpendicular_Button">
<property name="text">
<string>Perpendicular</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="P2P_Button">
<property name="minimumSize">