P2P constraint fix

Но по-хорошему стоит придумать, как после P2P соединить линии одной точкой
This commit is contained in:
2025-12-08 23:01:02 +03:00
parent a238b11db7
commit 24316cdd4f
5 changed files with 51 additions and 13 deletions

2
.gitignore vendored
View File

@@ -365,3 +365,5 @@ FodyWeavers.xsd
/include
/src
*.json
*.txt
/build

View File

@@ -9,6 +9,12 @@ void Canvas::changeMode(Mode _mode)
mode = _mode;
}
template <typename T, typename A, typename B>
T makeOrderedPair(A* obj1, B* obj2)
{
return (obj1->get_tag() < obj2->get_tag()) ? std::make_pair(obj1, obj2) : std::make_pair(obj2, obj1);
}
// TODO
Line* Canvas::findAt(QPointF& pos)
{
@@ -22,26 +28,41 @@ Line* Canvas::findAt(QPointF& pos)
Point* Canvas::findPointAt(QPointF pos, qreal tolerance)
{
Point* temp = nullptr;
for (Line* line : lines) {
QPointF p1(*line->p1.x, *line->p1.y);
QPointF p2(*line->p2.x, *line->p2.y);
if (dist_P2P(p1, pos) <= tolerance)
return &line->p1;
temp = &line->p1;
else if (dist_P2P(p2, pos) <= tolerance)
return &line->p2;
temp = &line->p2;
}
return nullptr;
return temp;
}
LinePair Canvas::makeOrderedPair(Line* l1, Line* l2)
bool Canvas::areCoincident(Point* p1, Point* p2, bool mode)
{
return (l1 < l2) ? std::make_pair(l1, l2) : std::make_pair(l2, l1);
int tag_0 = p1->get_tag(), tag_1 = p2->get_tag();
if (!mode){
return (tag_0 != tag_1 && *p1 == *p2);
}
else {
for (PointPair pair : P2Ppairs) {
int pair_tag_0 = pair.first->get_tag();
int pair_tag_1 = pair.second->get_tag();
if (pair_tag_0 == tag_0 && pair_tag_1 == tag_1 ||
pair_tag_0 == tag_1 && pair_tag_1 == tag_0)
return true;
}
return false;
}
}
bool Canvas::areAlreadyParallel(Line* l1, Line* l2)
{
return parallelPairs.count(makeOrderedPair(l1, l2)) > 0;
return parallelPairs.count(makeOrderedPair<LinePair>(l1, l2)) > 0;
}
void Canvas::mousePressEvent(QMouseEvent* event)
@@ -138,7 +159,7 @@ void Canvas::mousePressEvent(QMouseEvent* event)
if (!areAlreadyParallel(found, current_line)) {
sys.addConstraintParallel(*found, *current_line, constraints_count++);
parallelPairs.insert(makeOrderedPair(found, current_line));
parallelPairs.insert(makeOrderedPair<LinePair>(found, current_line));
current_line = nullptr;
update();
mode = Mode::None;
@@ -164,7 +185,6 @@ void Canvas::mousePressEvent(QMouseEvent* event)
else if (mode == Mode::Coincedent) {
Point* clickedPoint = findPointAt(scene);
if (!clickedPoint) {
firstPoint = nullptr;
update();
@@ -189,14 +209,17 @@ void Canvas::mousePressEvent(QMouseEvent* event)
if (&l->p1 == clickedPoint || &l->p2 == clickedPoint) l2 = l;
}
if (l1 == l2) {
if (l1 == l2 ||
(areCoincident(firstPoint, clickedPoint, true)))
{
QMessageBox::warning(this, QString("NO!"), QString("P2P failed"));
firstPoint = nullptr;
update();
return;
}
sys.addConstraintP2PCoincident(*firstPoint, *clickedPoint, constraints_count++);
sys.addConstraintP2PCoincident(*clickedPoint, *firstPoint, constraints_count++);
P2Ppairs.insert(makeOrderedPair<PointPair>(clickedPoint, firstPoint));
firstPoint = nullptr;
mode = Mode::None;
after_constraint = true;
@@ -313,6 +336,8 @@ Canvas::~Canvas()
lines.clear();
params.clear();
points.clear();
parallelPairs.clear();
P2Ppairs.clear();
if (current_line)
delete current_line;

View File

@@ -24,6 +24,7 @@ enum class Mode : int
// Удобный тип для хранения пары параллельных линий (порядок не важен)
using LinePair = std::pair<Line*, Line*>;
using PointPair = std::pair<Point*, Point*>;
// ===================================================================
// Основной класс холста
@@ -49,9 +50,8 @@ private:
// ====================== Поиск и выбор ======================
Line* findAt(QPointF&); // ищет линию под курсором
Point* findPointAt(QPointF, qreal tolerance = 10.0);
bool areCoincident(Point*, Point*, bool mode = false);
// ====================== Параллельность ======================
LinePair makeOrderedPair(Line* l1, Line* l2);
bool areAlreadyParallel(Line* l1, Line* l2); // проверка на дубликат
// ====================== Перемещение ======================
@@ -65,6 +65,7 @@ private:
std::vector<double*> params; // все параметры, передаваемые в солвер
std::set<LinePair> parallelPairs; // уже запараллеленные пары (защита от дублей)
std::set<PointPair> P2Ppairs;
Line* current_line{ nullptr };
Point* firstPoint{ nullptr };
@@ -72,5 +73,5 @@ private:
bool after_constraint{ false };
int obj_count{ 0 }; // тег для новых объектов
int constraints_count{ 0 }; // тег для новых ограничений
int constraints_count{ 0 }; // тег для новых ограничений
};

View File

@@ -149,6 +149,11 @@ void Line::set_tag(int _tag) {
p2.set_tag(_tag);
}
int Line::get_tag()
{
return tag;
}
// TODO
bool Line::contains(QPointF pos, qreal tol) const
{

View File

@@ -64,6 +64,10 @@ public:
void set_tag(int _tag) {
tag = _tag;
}
int get_tag() {
return tag;
}
};
using VEC_P = std::vector<Point>;
@@ -227,6 +231,7 @@ public:
Line* Copy() override;
void set_tag(int);
int get_tag();
bool contains(QPointF, qreal tol = 10.0) const;
};