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
T

135 lines
6.4 KiB
C++

#pragma once
#include <QWidget>
#include <QMouseEvent>
#include <QPointF>
#include <QMessageBox>
#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;
private:
// ====================== Методы поиска и выбора ======================
/// Найти линию под указанной позицией
Line* findAt(QPointF& position);
/// Найти точку в указанной позиции с заданной точностью
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; ///< Информация о последнем добавленном ограничении
};