This repository has been archived on 2026-05-28. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
DRAwer_2_0/Canvas.h
ParkSuMin cc1f891d90 P2P + Horizontal + Vertical
Очередное исправление багов
2025-12-15 18:53:12 +03:00

147 lines
6.7 KiB
C++
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#pragma once
#define WIDGET_POSITION event->pos()
#define UCS_POSITION screenToLogical(WIDGET_POSITION)
#include <QWidget>
#include <QMouseEvent>
#include <QPointF>
#include <QMessageBox>
#include <QToolTip>
#ifdef _DEBUG
#include <QDebug>
#endif
// GCS — геометрический солвер из FreeCAD
#include "GCS/Geo.h"
#include "GCS/GCS.h"
using namespace GCS;
// ===================================================================
// Типы и перечисления
// ===================================================================
/// Режимы работы с холстом
enum class Mode : int
{
None = 0, ///< Режим отсутствия действия
DrawingLine = 1, ///< Режим рисования линии
Parallel = 2, ///< Режим задания параллельности
Coincedent = 3, ///< Режим задания совпадения точек
Horizontal = 4, ///< Режим задания горизонтальности
Vertical = 5 ///< Режим задания вертикальности
};
/// Удобный тип для хранения пары параллельных линий (порядок не важен)
using LinePair = std::pair<Line*, Line*>;
/// Удобный тип для хранения пары точек (порядок не важен)
using PointPair = std::pair<Point*, Point*>;
// ===================================================================
// Основной класс холста
// ===================================================================
class Canvas : public QWidget
{
Q_OBJECT
public:
explicit Canvas(QWidget* parent = nullptr);
~Canvas() override;
/// Изменить текущий режим работы
void changeMode(Mode newMode);
protected:
// Обработчики событий Qt
void mousePressEvent(QMouseEvent* event) override;
void mouseMoveEvent(QMouseEvent* event) override;
void mouseReleaseEvent(QMouseEvent* event) override;
void paintEvent(QPaintEvent* event) override;
void leaveEvent(QEvent* event) override;
private:
#ifdef _DEBUG
void showObjectTag(QPointF pos);
#endif
QPointF screenToLogical(const QPointF& screenPos) const;
std::vector<Point*> getCoincidentGroup(Point* p);
// ====================== Методы поиска и выбора ======================
/// Найти линию под указанной позицией
Line* findAt(QPointF& pos, qreal tolerance = 5.0);
/// Найти точку в указанной позиции с заданной точностью
Point* findPointAt(QPointF position, qreal tolerance = 5.0);
/// Проверить, совпадают ли две точки (ограничение P2P)
bool areCoincident(Point* point1, Point* point2);
/// Проверить горизонтальность или вертикальность между двумя точками
/// @param mode: false - горизонтальность, true - вертикальность
bool areHorizontalVertical(Point* point1, Point* point2, bool mode);
/// Проверить, является ли линия горизонтальной
bool isLineHorizontal(Line* line);
/// Проверить, является ли линия вертикальной
bool isLineVertical(Line* line);
/// Проверить, являются ли две линии уже параллельными (дубликат ограничения)
bool areAlreadyParallel(Line* line1, Line* line2);
// ====================== Методы работы с ограничениями ======================
/// Удалить последние добавленные ограничения при ошибке солвера
void remove_constraints();
// ====================== Данные для перемещения объектов ======================
Point* draggedPoint{ nullptr }; ///< Точка, которую перемещают
Line* draggedLine{ nullptr }; ///< Линия, которую перемещают
QPointF dragOffset; ///< Смещение при начале перемещения
// ====================== Данные геометрической системы ======================
System sys; ///< Геометрический солвер
QVector<Line*> lines; ///< Завершённые линии
QVector<Point*> points; ///< Все точки сцены
std::vector<double*> params; ///< Все параметры, передаваемые в солвер
// ====================== Коллекции ограничений ======================
std::set<LinePair> parallelPairs; ///< Пары параллельных линий
std::set<PointPair> P2Ppairs; ///< Пары совпадающих точек
std::set<PointPair> HORIZ_pairs; ///< Пары точек горизонтальных линий
std::set<PointPair> VERT_pairs; ///< Пары точек вертикальных линий
// ====================== Временные данные для режимов ======================
Line* current_line{ nullptr }; ///< Текущая линия в режимах рисования/параллельности
Point* firstPoint{ nullptr }; ///< Первая точка в режиме совпадения
Mode mode{ Mode::None }; ///< Текущий режим работы
// ====================== Флаги состояния ======================
bool after_constraint{ false }; ///< Флаг, что только что добавлено ограничение
// ====================== Счётчики ======================
int obj_count{ 0 }; ///< Счётчик объектов (для тегов)
int constraints_count{ 0 }; ///< Счётчик ограничений (для тегов)
// ====================== Информация о последнем ограничении ======================
/// Структура для хранения информации о последнем добавленном ограничении
/// (используется для отката при ошибке солвера)
struct LastConstraint {
Mode mode{ Mode::None }; ///< Тип последнего ограничения
std::variant<LinePair, PointPair> data; ///< Данные ограничения
};
LastConstraint lastConstraint; ///< Информация о последнем добавленном ограничении
};