diff --git a/.gitignore b/.gitignore index e612e3c..51b9afa 100644 --- a/.gitignore +++ b/.gitignore @@ -365,3 +365,5 @@ FodyWeavers.xsd /include /src *.json +*.txt +/build diff --git a/Canvas.cpp b/Canvas.cpp index 6d42e04..b01ae0b 100644 --- a/Canvas.cpp +++ b/Canvas.cpp @@ -9,6 +9,12 @@ void Canvas::changeMode(Mode _mode) mode = _mode; } +template +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(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(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(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; diff --git a/Canvas.h b/Canvas.h index 330d47f..d750778 100644 --- a/Canvas.h +++ b/Canvas.h @@ -24,6 +24,7 @@ enum class Mode : int // Удобный тип для хранения пары параллельных линий (порядок не важен) using LinePair = std::pair; +using PointPair = std::pair; // =================================================================== // Основной класс холста @@ -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 params; // все параметры, передаваемые в солвер std::set parallelPairs; // уже запараллеленные пары (защита от дублей) + std::set 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 }; // тег для новых ограничений }; \ No newline at end of file diff --git a/GCS/Geo.cpp b/GCS/Geo.cpp index c3a7683..c8eae86 100644 --- a/GCS/Geo.cpp +++ b/GCS/Geo.cpp @@ -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 { diff --git a/GCS/Geo.h b/GCS/Geo.h index e49c1fb..4ca9c41 100644 --- a/GCS/Geo.h +++ b/GCS/Geo.h @@ -64,6 +64,10 @@ public: void set_tag(int _tag) { tag = _tag; } + + int get_tag() { + return tag; + } }; using VEC_P = std::vector; @@ -227,6 +231,7 @@ public: Line* Copy() override; void set_tag(int); + int get_tag(); bool contains(QPointF, qreal tol = 10.0) const; };