P2P constraint fix
Но по-хорошему стоит придумать, как после P2P соединить линии одной точкой
This commit is contained in:
2
.gitignore
vendored
2
.gitignore
vendored
@@ -365,3 +365,5 @@ FodyWeavers.xsd
|
||||
/include
|
||||
/src
|
||||
*.json
|
||||
*.txt
|
||||
/build
|
||||
|
||||
45
Canvas.cpp
45
Canvas.cpp
@@ -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;
|
||||
|
||||
7
Canvas.h
7
Canvas.h
@@ -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 }; // тег для новых ограничений
|
||||
};
|
||||
@@ -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
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user