Фикс с удалением ограничений

А ещё сделали так, чтобы линия не могла быть горизонтальной и вертикальной одновременно
This commit is contained in:
2025-12-15 11:55:32 +03:00
parent d8487951e0
commit eb946e2e6a
2 changed files with 114 additions and 14 deletions

View File

@@ -53,6 +53,19 @@ bool Canvas::areHorizontalVertical(Point* p1, Point* p2, bool mode)
return HORIZ_pairs.count(makeOrderedPair<PointPair>(p1, p2)); return HORIZ_pairs.count(makeOrderedPair<PointPair>(p1, p2));
else else
return VERT_pairs.count(makeOrderedPair<PointPair>(p1, p2)); return VERT_pairs.count(makeOrderedPair<PointPair>(p1, p2));
}
bool Canvas::isLineHorizontal(Line* line)
{
if (!line || !line->start_ref || !line->end_ref) return false;
return HORIZ_pairs.count(makeOrderedPair<PointPair>(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<PointPair>(line->start_ref, line->end_ref));
} }
bool Canvas::areAlreadyParallel(Line* l1, Line* l2) bool Canvas::areAlreadyParallel(Line* l1, Line* l2)
@@ -60,6 +73,43 @@ bool Canvas::areAlreadyParallel(Line* l1, Line* l2)
return parallelPairs.count(makeOrderedPair<LinePair>(l1, l2)); return parallelPairs.count(makeOrderedPair<LinePair>(l1, l2));
} }
void Canvas::remove_constraints()
{
sys.clearByTag(constraints_count - 1);
switch (lastConstraint.mode) {
case Mode::Horizontal: {
if (auto* pair = std::get_if<PointPair>(&lastConstraint.data)) {
HORIZ_pairs.erase(*pair);
}
break;
}
case Mode::Vertical: {
if (auto* pair = std::get_if<PointPair>(&lastConstraint.data)) {
VERT_pairs.erase(*pair);
}
break;
}
case Mode::Parallel: {
if (auto* pair = std::get_if<LinePair>(&lastConstraint.data)) {
parallelPairs.erase(*pair);
}
break;
}
case Mode::Coincedent: {
if (auto* pair = std::get_if<PointPair>(&lastConstraint.data)) {
P2Ppairs.erase(*pair);
}
break;
}
default:
break;
}
lastConstraint.mode = Mode::None;
constraints_count--;
}
void Canvas::mousePressEvent(QMouseEvent* event) void Canvas::mousePressEvent(QMouseEvent* event)
{ {
QPointF scene = event->pos(); QPointF scene = event->pos();
@@ -92,18 +142,45 @@ void Canvas::mousePressEvent(QMouseEvent* event)
Line* found = findAt(scene); Line* found = findAt(scene);
if (found) { 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) { if (mode == Mode::Horizontal) {
sys.addConstraintHorizontal(*found, constraints_count++); sys.addConstraintHorizontal(*found, constraints_count++);
HORIZ_pairs.insert(makeOrderedPair<PointPair>(found->start_ref, found->end_ref)); auto pair = makeOrderedPair<PointPair>(found->start_ref, found->end_ref);
HORIZ_pairs.insert(pair);
lastConstraint.mode = Mode::Horizontal;
lastConstraint.data = pair;
} }
else { else {
sys.addConstraintVertical(*found, constraints_count++); sys.addConstraintVertical(*found, constraints_count++);
VERT_pairs.insert(makeOrderedPair<PointPair>(found->start_ref, found->end_ref)); auto pair = makeOrderedPair<PointPair>(found->start_ref, found->end_ref);
VERT_pairs.insert(pair);
lastConstraint.mode = Mode::Vertical;
lastConstraint.data = pair;
} }
update(); update();
after_constraint = true;
} }
mode = Mode::None; mode = Mode::None;
after_constraint = true;
} }
else if (mode == Mode::DrawingLine) { else if (mode == Mode::DrawingLine) {
@@ -189,12 +266,16 @@ void Canvas::mousePressEvent(QMouseEvent* event)
} }
if (!areAlreadyParallel(found, current_line)) { if (!areAlreadyParallel(found, current_line)) {
auto pair = makeOrderedPair<LinePair>(found, current_line);
sys.addConstraintParallel(*found, *current_line, constraints_count++); sys.addConstraintParallel(*found, *current_line, constraints_count++);
parallelPairs.insert(makeOrderedPair<LinePair>(found, current_line)); parallelPairs.insert(pair);
lastConstraint.mode = Mode::Parallel;
lastConstraint.data = pair;
current_line = nullptr; current_line = nullptr;
update();
mode = Mode::None; mode = Mode::None;
after_constraint = true; after_constraint = true;
update();
} }
else { else {
@@ -251,7 +332,11 @@ void Canvas::mousePressEvent(QMouseEvent* event)
} }
sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++); sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++);
P2Ppairs.insert(makeOrderedPair<PointPair>(clickedPoint, firstPoint)); auto pair = makeOrderedPair<PointPair>(clickedPoint, firstPoint);
P2Ppairs.insert(pair);
lastConstraint.mode = Mode::Coincedent;
lastConstraint.data = pair;
firstPoint = nullptr; firstPoint = nullptr;
mode = Mode::None; mode = Mode::None;
after_constraint = true; after_constraint = true;
@@ -338,8 +423,7 @@ void Canvas::paintEvent(QPaintEvent*)
} }
else if (res == SolveStatus::Failed && after_constraint){ else if (res == SolveStatus::Failed && after_constraint){
QMessageBox::warning(this, QString("Error!"), QString("Last constraint is unavailable!")); QMessageBox::warning(this, QString("Error!"), QString("Last constraint is unavailable!"));
sys.removeConstraint(sys.get_last_constraint()); remove_constraints();
constraints_count--;
} }
after_constraint = false; after_constraint = false;
} }
@@ -388,7 +472,6 @@ Canvas::Canvas(QWidget *parent)
: QWidget(parent) : QWidget(parent)
{ {
sys = System(); sys = System();
current_line = nullptr;
setMouseTracking(true); setMouseTracking(true);
setBackgroundRole(QPalette::Base); setBackgroundRole(QPalette::Base);
setAutoFillBackground(true); setAutoFillBackground(true);
@@ -396,19 +479,26 @@ Canvas::Canvas(QWidget *parent)
Canvas::~Canvas() Canvas::~Canvas()
{ {
for (Line* line : lines) {
delete line;
}
for (double* param : params) { for (double* param : params) {
delete param; delete param;
} }
lines.clear(); for (Point* pt : points) {
delete pt;
}
for (Line* line : lines) {
delete line;
}
params.clear(); params.clear();
points.clear(); points.clear();
lines.clear();
parallelPairs.clear(); parallelPairs.clear();
P2Ppairs.clear(); P2Ppairs.clear();
VERT_pairs.clear();
HORIZ_pairs.clear();
if (current_line) if (current_line)
delete current_line; delete current_line;

View File

@@ -54,6 +54,8 @@ private:
Point* findPointAt(QPointF, qreal tolerance = 5.0); Point* findPointAt(QPointF, qreal tolerance = 5.0);
bool areCoincident(Point*, Point*); bool areCoincident(Point*, Point*);
bool areHorizontalVertical(Point*, Point*, bool); bool areHorizontalVertical(Point*, Point*, bool);
bool isLineHorizontal(Line* line); // проверяет, горизонтальна ли линия
bool isLineVertical(Line* line); // проверяет, вертикальна ли линия
// ====================== Параллельность ====================== // ====================== Параллельность ======================
bool areAlreadyParallel(Line* l1, Line* l2); // проверка на дубликат bool areAlreadyParallel(Line* l1, Line* l2); // проверка на дубликат
@@ -62,6 +64,8 @@ private:
Line* draggedLine{ nullptr }; Line* draggedLine{ nullptr };
QPointF dragOffset; QPointF dragOffset;
// ====================== Работа с парами ограничений ======================
void remove_constraints();
// ====================== Данные сцены ====================== // ====================== Данные сцены ======================
System sys; // геометрический солвер System sys; // геометрический солвер
QVector<Line*> lines; // завершённые линии QVector<Line*> lines; // завершённые линии
@@ -80,4 +84,10 @@ private:
int obj_count{ 0 }; // тег для новых объектов int obj_count{ 0 }; // тег для новых объектов
int constraints_count{ 0 }; // тег для новых ограничений int constraints_count{ 0 }; // тег для новых ограничений
struct LastConstraint {
Mode mode{ Mode::None };
std::variant<LinePair, PointPair> data;
};
LastConstraint lastConstraint;
}; };