Russian Qt Forum

Qt => 2D и 3D графика => Тема начата: Max Payne от Апрель 06, 2011, 01:13



Название: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 06, 2011, 01:13
Есть набор QGraphicsItem`ов на сцене и прямая один конец которой вращается вокруг другого, как луч раара, при этом пересекаясь с другими элементами. Подскажите как можно найти точку пересечения елементов с прямой, не проверяя при этом каждую точку прямой на то принадлежит она элементу с которым пересекается... Заранее спасибо


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Mikhail от Апрель 06, 2011, 07:34
Используй
bool QGraphicsItem::collidesWithItem ( const QGraphicsItem * other, Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const
и
QList<QGraphicsItem *> QGraphicsItem::collidingItems ( Qt::ItemSelectionMode mode = Qt::IntersectsItemShape ) const

Твоя линия должна быть QGraphicsLineItem или наследована от него.


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 06, 2011, 08:03
Так я могу определить столкновение, но как определить точку, в которой линия коснулась к другому айтему?


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 08, 2011, 12:44
Никто не сталкивался с такой проблемой? Нид хелп, подскажите, кто делал что то подобное.


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Igors от Апрель 08, 2011, 13:07
Так я могу определить столкновение, но как определить точку, в которой линия коснулась к другому айтему?
Если это есть в Qt - хорошо, но почему "и это" должно здесь быть?  :) Собственно Вас "точка" не интересует, надо определить "угол радара" при котором будет касание. Напр

Радар стоит в точке (0, 0) угол отсчитывается против часовой стрелки. Айтем круг с центром в точке (sx, sy) и радиусом R. Тогда

Код
C++ (Qt)
float distance = sqrt(sx * sx + sy * sy);
if (distance >= R) return; // радар внутри круга  
 
float delta_angle = asin(R / distance);
float mid_angle = atan2(sy, sx);
float angle1 = mid_angle - delta_angle;  // первый угол (в радианах)
float angle2 = mid_angle + delta_angle;  // второй
 
Для айтема "полигон" еще проще. Ну и чего ждем?


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: madRoger от Апрель 08, 2011, 13:42
Если все-таки нужна точка пересечения, можно попробовать перейти от QGraphicsItem к QRegion и воспользоваться методом QRegion::intersected для определения общей части двух объектов. При минимальном шаге радара эта общая часть будет стремиться к точке.


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Igors от Апрель 08, 2011, 13:51
Если все-таки нужна точка пересечения, можно попробовать перейти от QGraphicsItem к QRegion и воспользоваться методом QRegion::intersected для определения общей части двух объектов. При минимальном шаге радара эта общая часть будет стремиться к точке.
Если все-таки нужна, то проще найти ее по теореме Пифагора. Для примера выше

Код
C++ (Qt)
float dist2 = distance * cos(delta_angle);
inters_x = dist2 * cos(angle1);
inters_y = dist2 * sin(angle1);
 



Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 17, 2011, 10:06
Цитировать
Радар стоит в точке (0, 0) угол отсчитывается против часовой стрелки. Айтем круг с центром в точке (sx, sy) и радиусом R. Тогда

Код
C++ (Qt)
float distance = sqrt(sx * sx + sy * sy);
if (distance >= R) return; // радар внутри круга 
 
float delta_angle = asin(R / distance);
float mid_angle = atan2(sy, sx);
float angle1 = mid_angle - delta_angle;  // первый угол (в радианах)
float angle2 = mid_angle + delta_angle;  // второй
 
Для айтема "полигон" еще проще. Ну и чего ждем?

Во-первых, айтем это многоугольник , при чем не правильный и даже имея QPainterPath, нужно перебирать все его отрезки
и каждый проверять на пересечение с линией.

Я пробовал вот так:
Код:
QPointF Arthur::intersectPoint(QGraphicsItem *it)
{
    bool first = true;
    QPointF t1, t2, t3;
    QPainterPath h = it->shape();
    for (int i = 1; i< h.elementCount(); i++)
    {
        if (!first)
        {
            t1 = h.elementAt(i);
            continue;
        }
        t2 = h.elementAt(i);

        QLineF l1 (it->mapToScene(t1),it->mapToScene(t2));
        if(Linne->intersect(l1, &t3) == 2)
        {
            break;
        }
        t1 = t2;
    }
   
    sc->addRect(t3.x(),t3.y(),150,150,QPen(),QBrush(QColor(Qt::red))); // Этот QRect рисует черт знает где , а не в точке пересечения...
   
}

Функция QLineF::intersect(QLineF&, *QPointF) точку возвращать должна в координатах сцены?
Народ нид хелп, подскажите хоть в какую сторону копать ...


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 17, 2011, 10:08
У меня линия движется ( вращается вокруг стационарной точки) это не влияет точку возвращаемую QLineF::intersect(QLineF&, *QPointF) ?


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Igors от Апрель 17, 2011, 10:20
Во-первых, айтем это многоугольник , при чем не правильный и даже имея QPainterPath, нужно перебирать все его отрезки
и каждый проверять на пересечение с линией.
Школьный курс геометрии здесь гораздо более полезен чем "изыскивание нужных ф-ций/классов"  :)
Зачем перебирать отрезки? Для полигона касание луча всегда будет хотя бы в одной из точек, их и перебирайте
Код
C++ (Qt)
float angle = atan2(point.y, point.x);
 
Так находите 2 точки что соответствуют минимальному и максимальному углам. Потом надо только проверить какая ближайшая - ну разберетесь


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Max Payne от Апрель 17, 2011, 10:28
Обьясните пожалуйста я не понял Вас... У меня есть QPainterPath который был трансформирован (поворот смещение и т.д.) Я могу перебирать поочереди все отрезки и проверять их на пересечение, иначе ни как, я не знаю как он трансформирован, и в какую сторону был повернут, я могу лишь найти центр его boundingRect(), и все...


Название: Re: Пересечение QGraphicsItem`ов
Отправлено: Igors от Апрель 17, 2011, 10:48
Обьясните пожалуйста я не понял Вас... У меня есть QPainterPath который был трансформирован (поворот смещение и т.д.) Я могу перебирать поочереди все отрезки и проверять их на пересечение, иначе ни как, я не знаю как он трансформирован, и в какую сторону был повернут, я могу лишь найти центр его boundingRect(), и все...
Ну Вы же точки извлекаете и переводите в координаты сцены - ну и находите 2 точки с минимальным/максимальным углом, отрезки-то Вам зачем? Не забудьте вычесть координаты центра радара если он не в точке (0, 0)