PDA

View Full Version : QPainter drawArc question



kloopa
28th December 2015, 06:22
Hi. I'm trying to use QPainter drawArc(const QRectF & rectangle, int startAngle, int spanAngle) for arc drawing.
And have a problem with it.
I have a coordinates of 3 arc points A, B, C.
A - arc start point
B - arc end point
C - arc center with known radius (10).

Question. How to calculate rectangle, startAngle and spanAngle for this arc?

11595

ChrisW67
30th December 2015, 07:38
The rectangle is the rectangle that would contain the entire circle if drawn completely, and you get the angles with basic trigonometry:

QPointF const A(6.31, 5.773);
QPointF const B(20.53, 19.836);
QPointF const C(13.42, 12.805);
double const radius(10.0);

QRectF const r(C.x() - radius, C.y() - radius, radius * 2, radius * 2);
double const startAngle = 16 * atan2(A.y() - C.y(), A.x() - C.x()) * 180.0 / M_PI;
double const endAngle = 16 * atan2(B.y() - C.y(), B.x() - C.x()) * 180.0 / M_PI;
double const spanAngle = endAngle - startAngle;

QImage img(500, 500, QImage::Format_RGB32);
img.fill(Qt::white);
QPainter p(&img);
p.scale(10.0, 10.0);
p.setPen(Qt::red);
p.drawRect(r);
p.setPen(Qt::black);
p.drawArc(r, startAngle, spanAngle);
p.end();
img.save("test.png");

You might need to tweak this for some cases

kloopa
2nd January 2016, 06:20
Thank you for reply! It works.
How to draw clockwise and counter-clockwise? (using drawArc and arcTo)
How to calculate sweepLength for QPainterPath.arcTo?

ChrisW67
2nd January 2016, 20:36
Experiment with swapping A and B and changing the sign of the spanAngle.
If you want to draw the shortest arc between two points and spanAngle is greater than 180 degrees (+ve or -ve) then you need to add/subtract 360 degrees to the spanAngle (changes the sign and hence drawing direction).

The angle for arcTo is calculated the same way without the 16 multiplier used by QPainter.

kloopa
11th January 2016, 14:01
ChrisW67, Can you recommend me how to draw all known arcs :) using your code? Arcs may be more than (+-)180, full circle(360). I tried top play with code myself many times, but without result.

For example, i'm reading file with coordinates:

START: X143.178 Y82.461
LINE-TO: X13.178 Y82.461
ARC-TO[Clockwise]: X2.278 Y93.361 cX13.178 cY93.361
LINE-TO: X2.278 Y151.361
ARC-TO[Clockwise]: X13.178 Y162.261 cX13.178 cY151.361
LINE-TO: X143.178 Y162.261
ARC-TO[Clockwise]: X154.078 Y151.361 cX143.178 cY151.361

Where cX, cY arc center coordinates. Arcs may drawing counter clockwise.

I want to see like this:

11631

Now i see:

11632

ChrisW67
11th January 2016, 20:11
Everything you need is in my earlier post http://www.qtcentre.org/threads/64705-QPainter-drawArc-question?p=286095#post286095
Read the docs for QPainter::drawArc() to understand how span angle determines the drawing direction.

kloopa
12th January 2016, 07:29
For clockwise / counter-clockwise drawing question solved.
But arcs still incorrect. I think problem when calculating angles. Because angles may be + or -.
My program reading coordinates form TXT file (file generated by other software from DXF format, where 0 degree at 12 o'clock).

Part of my code (Python3):


def arcAngles(self, a, b, c):
startAngle = 16*atan2(a.y() - c.y(), a.x() - c.x())*180 / pi
endAngle = 16*atan2(b.y() - c.y(), b.x() - c.x())*180 / pi

spanAngle = abs(endAngle) - abs(startAngle)

#Clocksiwe
if self.direction == -1:
if spanAngle > 0:
spanAngle = -spanAngle

print("START: " + str(startAngle / 16) + "\nEND: " + str(endAngle / 16) + "\nSPAN: " + str(spanAngle / 16))
angles = {'start': startAngle, 'end': endAngle, 'span': spanAngle}

return angles


Result:



=====1st Arc====
START: -90.0
END: 180.0
SPAN: -90.0
LastPoint: PyQt5.QtCore.QPointF(13.178, 82.461)
EndPoint: PyQt5.QtCore.QPointF(2.278, 93.361)

=====2nd Arc====
START: 180.0
END: 90.0
SPAN: -90.0
LastPoint: PyQt5.QtCore.QPointF(2.278, 151.361)
EndPoint: PyQt5.QtCore.QPointF(13.178, 162.261)

=====3rd Arc====
START: 90.0
END: 0.0
SPAN: -90.0
LastPoint: PyQt5.QtCore.QPointF(143.178, 162.261)
EndPoint: PyQt5.QtCore.QPointF(154.078, 151.361)


Drawing result:
11633

I tried to solve this by manipulation with offset (90 degree), but still not solved.

Substracting offset from angles:



offset = 90*16

if startAngle < 0:
startAngle -= -offset
else:
startAngle -= offset

if endAngle < 0:
endAngle -= -offset
else:
endAngle -= offset


When substract offset from angles i see:

11636

Add offset to angles:



offset = 90*16

if startAngle < 0:
startAngle += -offset
else:
startAngle += offset

if endAngle < 0:
endAngle += -offset
else:
endAngle += offset


When adding offset to angles i see:

11637