Как интерпретируются углы в QPainterPath ::arcTo?

#qt

#qt

Вопрос:

Я работаю над функцией графического редактора, в котором я редактирую дуги, и QPainterPath :: arcTo ведет себя не так, как я ожидал, когда фигура представляет собой эллипс; он работает так, как ожидалось, когда это круг.

На двух изображениях ниже показаны результаты. В первом случае я создал окружность, которую затем преобразовал в дугу с начальным начальным углом 45 и углом охвата 270. Пространство координат сцены является квадратным. Диагональные линии расположены под углом 45 градусов. Как и ожидалось, конечные точки дуги окружности находятся точно на диагональных линиях.

Во втором случае у меня есть эллипс, который преобразуется в дугу точно таким же образом с углами 45 и 270 градусов соответственно. Конечные точки дуги больше не попадают на диагональные линии, чего я не ожидаю.

В обоих случаях код чертежа:

 painter.arcTo (rect, 45, 270);
  

Ноль градусов находится в положении «3 часа», и я полагал, что указанный угол был измерен между ним и линией от центральной точки до точки на краю дуги. Очевидно, происходит что-то еще, чего я не понимаю и, похоже, не задокументировано в описании QPainter::arcTo.

Это проблема, потому что я пишу код для изменения формы дуги, и мне нужно иметь возможность работать с фоном, когда все, что у меня есть, это текущее положение мыши и центральная точка охватывающего прямоугольника. Прямо сейчас, когда я изменяю форму дуги, угол, который я вычисляю, является точным только при 0, 90, 180 и 270. Чем ближе я подхожу к промежуточным углам в 45 градусов, тем дальше мой угол.

Я получаю этот угол с помощью:

 QLineF (rect.center(), mouse_pos).angle ();
  

Опять же, для кругов это работает отлично. Для некруглых эллипсов это не так.

После написания этого я нашел эту прекрасную иллюстрацию, которая точно демонстрирует, с чем я имею дело. К сожалению, решение Postscript для меня бесполезно. Мне нужно знать, что делать, чтобы вычислить правильные углы.

Дуга окружности с начальным углом 45 и углом охвата 270

Эллиптическая дуга с начальным углом 45 и углом охвата 270

Ответ №1:

Я нашел свой ответ здесь. Как я и ожидал, мое понимание углов было неверным. Чтобы выполнить отслеживание мыши для изменения формы дуги, мне нужно найти пересечение отрезка прямой с эллипсом и работать в обратном направлении от параметрических уравнений эллипса, чтобы найти правильный угол.

Ответ №2:

Благодаря @goug я смог исправить аналогичную проблему с QPainterPath :: arcTo.

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

Вот код, который показывает, как обойти эту проблему.

 qreal startAngle = 10;
qreal endAngle = 60;

qreal radius1 = 30; // X-axis
qreal radius2 = 60; // Y-axis

QPointF center;
QRectF boundingRect(center.x() - radius1, center.y() - radius2, radius1*2, radius2*2);

if (!qFuzzyIsNull(endAngle) amp;amp;
        !VFuzzyComparePossibleNulls(endAngle, 90) amp;amp;
        !VFuzzyComparePossibleNulls(endAngle, 180) amp;amp;
        !VFuzzyComparePossibleNulls(endAngle, 270) amp;amp;
        !VFuzzyComparePossibleNulls(endAngle, 360))
{
  // Calculating correct end angle
  qreal endAngleRad = qDegreesToRadians(endAngle);
  endAngle = qRadiansToDegrees(qAtan2(radius1 * qSin(endAngleRad),
                                      radius2 * qCos(endAngleRad)));
}

QLineF startLine(center.x(), center.y(), center.x()   radius1, center.y());
QLineF endLine = startLine;

startLine.setAngle(startAngle);
endLine.setAngle(endAngle);
qreal sweepAngle = startLine.angleTo(endLine);

QPainterPath myPath;
myPath.arcTo(boundingRect, startAngle, sweepLength);