Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Vladimir от Май 25, 2016, 11:55



Название: [РЕШЕНО] Попадание точки в коридор
Отправлено: Vladimir от Май 25, 2016, 11:55
Доброго дня! Вопрос такого плана, можно ли как-то средствами Qt хитро определить попадает ли красная точка в зеленый коридор?
Рисование осуществляется:
Код:
painter.setPen(QPen(colorAlpha,curWidth,pStyle,Qt::FlatCap));
painter.setCompositionMode(mode);
painter.drawPolyline(points);

Координаты желтых точек известны, может возможно как-то получить координаты синих, зная толщину линии? а затем засунуть их в QPolygon в правильном порядке, а там уже алгоритм попадания точки в полигон известен. Рисуется все на QWidget, средствами QPainter! Модуль рисования большой и уже реализован, поэтому конкретного переделывания не хотелось бы, скажем на QGraphicsScene, но возможно сценой можно как-то посчитать в фоне это, либо на крайняк математически как это можно рассчитать.. Возникла мысль обрабатывать цвет пикселя, но коридор может быть не видим, а обработка все равно должна вестись..так что скорее всего нет. В общем какие будут мысли?)


Название: Re: Попадание точки в коридор
Отправлено: Igors от Май 25, 2016, 12:18
Код
C++ (Qt)
void CalcBluePt( const QPolygonF & poly, int index, int lineWidth, QPointF bluePt[2] )
{
 QVector2D dir;
 const QPointF & base = poly[index];
 if (index > 0)
   dir += QVector2D(base - poly[index - 1]).normalized():
 if (index < poly.size() - 1)
   dir += QVector2D(poly[index + 1] - base).normalized():
 dir.normalize();
 dir *= lineWidth;
 QPointF ofs(-dir.y(), dir.x());
 bluePt[0] = base + ofs;
 bluePt[1] = base - ofs;
}
Писал прямо здесь, возможны ошибки синнтаксиса


Название: Re: Попадание точки в коридор
Отправлено: Swa от Май 25, 2016, 12:27
По желтым точкам строим список линий QList<QLine>, из красной точки (R) опускаем перпендикуляр на каждый отрезок и получаем точку (P) на отрезке. Если точка P не найдена, то этот отрезок отбрасываем. Дальше, если расстояние между R и P меньше половины толщины коридора (curWidth/2) то красная точка находится внутри.


Название: Re: Попадание точки в коридор
Отправлено: Igors от Май 25, 2016, 12:41
По желтым точкам строим список линий QList<QLine>, из красной точки (R) опускаем перпендикуляр на каждый отрезок и получаем точку (P) на отрезке. Если точка P не найдена, то этот отрезок отбрасываем.
На "стыках" есть точки которые не проецируются ни на один из отрезков (точнее проекция оказывается за пределами отрезка).

Поэтому наверное все-таки средствами Qt, построить QPainterPath


Название: Re: Попадание точки в коридор
Отправлено: Vladimir от Май 25, 2016, 12:44
Код
C++ (Qt)
void CalcBluePt( const QPolygonF & poly, int index, int lineWidth, QPointF bluePt[2] )
{
 QVector2D dir;
 const QPointF & base = poly[index];
 if (index > 0)
   dir += QVector2D(base - poly[index - 1]).normalized():
 if (index < poly.size() - 1)
   dir += QVector2D(poly[index + 1] - base).normalized():
 dir.normalize();
 dir *= lineWidth;
 QPointF ofs(-dir.y(), dir.x());
 bluePt[0] = base + ofs;
 bluePt[1] = base - ofs;
}
Писал прямо здесь, возможны ошибки синнтаксиса

Круто! Вопросик по параметрам ф-ции const QPolygonF & poly - это выходной полигон описывающий линию заданной толщины?;  int index - это индекс чего?; QPointF bluePt[2] - это координаты синих точек? так я же их не знаю, как мне их на вход подать?

Или же эта ф-ция возвращает координаты синих точек, получая на вход координаты желтых точек и толщину линии??


Название: Re: Попадание точки в коридор
Отправлено: Vladimir от Май 25, 2016, 13:50
Все разобрался!! Есть в такой реализации своя особенность (см. картинку), но мне было важнее нарисовать равноудаленный коридор от группы точек, так что зеленый можно убирать, а оставить только красный!  :)

Igors, спасибо большое!!!


Название: Re: Попадание точки в коридор
Отправлено: Igors от Май 25, 2016, 16:00
Все разобрался!! Есть в такой реализации своя особенность (см. картинку),
Ну вообще-то неточность/ошибка, а не "особенность" :) Надо еще поделить на косинус
Код
C++ (Qt)
void CalcBluePt( const QPolygonF & poly, int index, qreal halfWidth, QPointF bluePt[2] )
{
 QVector2D dir, dir1, dir2;
 const QPointF & base = poly[index];
 qreal dot = 1.0;
 if (index == 0)  
   dir = QVector2D(poly[index + 1] - base).normalized();
 else
   if (index == poly.size() - 1)
     dir = QVector2D(base - poly[index - 1]).normalized();
   else {
     dir1 = QVector2D(poly[index + 1] - base).normalized();
     dir2 = QVector2D(base - poly[index - 1]).normalized();
     dir = (dir1 + dir2).normalized();
     dot = QVector2D::dotProduct(dir, dir2);
   }
 dir *= halfWidth / dot;
 QPointF ofs(-dir.y(), dir.x());
 bluePt[0] = base + ofs;
 bluePt[1] = base - ofs;
}
 
Так правда не выходит "скошенный уголок", там получится больше кода

А QPainterPath смотрели? По смыслу он самое экономичное решение (по крайней мере по объему кода)


Название: Re: [РЕШЕНО] Попадание точки в коридор
Отправлено: Vladimir от Май 25, 2016, 16:29
QPainterPath для описания коридора по синим точкам вместо полигона? нет, не смотрел. вроде код работает как надо, но пока проверил только в тестовом варианте и пока все гуд. второй вариант, кстати, не работает.. получается что-то типо (см. картинку) :) и да, там надо было брать половину halfWidth.


Название: Re: [РЕШЕНО] Попадание точки в коридор
Отправлено: Igors от Май 25, 2016, 17:22
.. второй вариант, кстати, не работает.. получается что-то типо (см. картинку) :)
Да, тут я маленько насвистел  :) подправил


Название: Re: [РЕШЕНО] Попадание точки в коридор
Отправлено: Vladimir от Май 26, 2016, 09:59
Как говорится идеальный - враг хорошего)  :)


Название: Re: [РЕШЕНО] Попадание точки в коридор
Отправлено: Igors от Май 26, 2016, 11:30
Ничего, еще подправим (ошибка была с normalized).