LINUX.ORG.RU

[Qt] Площадные инструменты. Площадь пересечения.

 


0

0

I. Требуются инструмент, рисующий прямоугольники. Также требуются выделяющие инструменты (овал, прямоугольник). Принцип действия одинаков — юзер тыкает кнопкой мыши по View, растягивает нечто, видит как оно изменяется, отпускает кнопку и мы получаем в своё распоряжение заданный QRectF (как я понимаю, с овалами также лучше работать через QRectF).

То есть работать с этим делом предполагается как-то так (по аналогии с QRubberBand):

    void Widget::mousePressEvent(QMouseEvent *event)
    {
        origin = event->pos();
        if (!myInstrument)
            myInstrument = new MyInstrument(MyInstrument::НУЖНАЯ_ФОРМА, this);
        myInstrument->setGeometry(QRect(origin, QSize()));
        myInstrument->show();
    }

    void Widget::mouseMoveEvent(QMouseEvent *event)
    {
        myInstrument->setGeometry(QRect(origin, event->pos()).normalized());
    }

    void Widget::mouseReleaseEvent(QMouseEvent *event)
    {
        myInstrument->hide();
        // делаем, что надо и удаляем myInstrument
    }

Если я верно понимаю, в Qt из подобного есть только прямоугольное выделение — QRubberBand. Но оно умеет рисовать только прямоугольники и отрезки. То есть надо бы унаследовать и добавить нужные формы, но сколько я ни медитировал на код этого виджета, я так и не понял, где там вообще рисуется прямоугольник. Что нужно сделать, чтобы оно рисовало овалы (и вообще возможно ли это)?

II. Ещё требуется выделение-лассо (точнее, полигональное выделение) — юзер расставляет точки, соединяет начальную точку с конечной и мы получаем в своё распоряжение полигон (как в гимпе, только без возможности рисования кривых). Как быть, от чего идти? От QGraphicsItem?

III. На сцене расположены прямоугольнички. Требуется функция, которая возвращала бы ссылки на все прямоугольники, которые более чем половиной площади попадают в заданную фигуру (в моём случае в элипс или полигон). Это нужно для выделения. Представляю себе так:

void MyGraphicsScene::setSelectionArea ( const QPainterPath & path, const QTransform & deviceTransform )
{
  // Находим все фигуры, которые перекаются c selectionArea() методом IntersectsItemShape и методом ContainsItemShape. Вычитаем второе из первого, для полученного списка обычной математикой находим площадь пересечения, дальше всё ясно
}

Далее работа идёт через стандартный QList<QGraphicsItem *> MyGraphicsScene::selectedItems () const.

Есть ли более изящное решение? В частности, хотелось бы как-то определять площадь пересечения средствами Qt, а не своими алгоритмами (которые надо делать отдельно для элипсов и полигонов).

★★★★★

Последнее исправление: Obey-Kun (всего исправлений: 2)

Если есть какой-нибудь (в идеале небольшой) проект, где подобное реализовано, дайте название, пожалуйста.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

kolourpaint посмотри, там может быть что-то полезное

anonymous
()

Чёрт, неужели нет способа определить площадь QPainterPath? Ну хоть библиотека какая.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

Определять площадь фигур, ограниченных кривыми второго порядка? Qt это же не математический пакет.

anonymous
()
Ответ на: комментарий от anonymous

выходит, буду делать так:

Сначала с помощью разницы в selectionArea() методом IntersectsItemShape и методом ContainsItemShape находятся прямоугольнички, пересекающие границу выделения.

Для круга: для каждого из этих прямоугольников находится обычной математикой площадь пересечения с кругом (решение элементарной системы уравнений)

Для многоугольника. Для каждого из этих прямоугольников с помощью QPainterPath::intersected ( const QPainterPath & p ) находим path пересечения прямоугольника и полигона, далее оно переводится стандартным способом в массив полигонов, далее посчитать суммарную площадь — не проблема. Можно было бы сделать и проще, но следует учитывать, что многоугольник не обязательно выпуклый.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

вообще, лучше бы запретить юзеру делать невыпуклые многоугольники, т.к. они в задаче всё равно не особо нужны

Obey-Kun ★★★★★
() автор топика

[Qt] Беспощадные инструменты.

>Требуется функция, которая возвращала бы ссылки на все прямоугольники, которые более чем половиной площади попадают в заданную фигуру

Вот что тебе действительно нужно, так это упростить задачу. (Извини, если ты не это хотел услышать :)

pathfinder ★★★★
()

>Требуется функция, которая возвращала бы ссылки на все прямоугольники, которые более чем половиной площади попадают в заданную фигуру

Может отрендерить фигуру в низком разрешении где-то в буфере и посчитать число закрашенных пикселей попадающих в прямоугольник.

Ну и так для каждого прямоугольника.

pathfinder ★★★★
()
Ответ на: [Qt] Беспощадные инструменты. от pathfinder

> Вот что тебе действительно нужно, так это упростить задачу. (Извини, если ты не это хотел услышать :)

Вряд ли стоит упрощать. Сам посмотри. Юзер делает модель грунтов, создавая сетку из прямоугольных блоков. И тут ему надо, например, сделать трубу — дырку в грунтах. Он выделяет круг и жмакает Del. Можешь сам порисовать на бумаге и проверить — круг с небольшим радиусом (около 6 ячеек) лучше получается при учёте площади пересечения.

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от pathfinder

странный метод, хотя попробовать можно

ещё метод Монте-Карло радует, когда наносятся случайные точки внутри прямоугольника и смотрится, сколько % из них попало внутрь пересекающей фигуры :).

Obey-Kun ★★★★★
() автор топика
Ответ на: комментарий от Obey-Kun

В случае картинки все точки (пиксели) уже нанесены. Осталось их подсчитать, как и предложено выше.

anonymous
()
Ответ на: комментарий от Obey-Kun

>странный метод, хотя попробовать можно

Почему странный? Нормальный метод. Нет, ну если ты хочешь долгой и страстной любви с компьютером, то могу предложить другой подход - через BSP деревья. Вот источник вдохновения http://forum.sources.ru/index.php?showtopic=216741

pathfinder ★★★★
()
Ответ на: комментарий от pathfinder

Сказано же, что может быть и круг. Поэтому не может быть никакого «двоичного» разделения. Границы разделения задаются кусками кривых второго порядка. Тут проще пиксели подсчитать.

anonymous
()
Ответ на: комментарий от anonymous

>Сказано же, что может быть и круг.

Я про вариант с многоугольником имел в виду. Для больших кайфов круг и эллипс можно представить многоугольником.

pathfinder ★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.