how to get the end point of a translated QPolygon

1.5k Views Asked by At

I'm trying to draw an arrow so I just referred to the example code where we can draw arrows:

http://doc.qt.io/qt-5/qtwidgets-graphicsview-elasticnodes-edge-cpp.html

I decided to draw using the same formula and tried like:

theCurrentLine->setP1(QPointF(0, 0)  );
theCurrentLine->setP2((theLineVector));
p->drawLine(*theCurrentLine);

double angle = ::acos(theCurrentLine->dx() / theCurrentLine->length());
if (theCurrentLine->dy() >= 0)
    angle = TwoPi - angle;

QPointF sourcePoint = QPointF(0,0);

QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * theArrowSize,
                                              cos(angle + Pi / 3) * theArrowSize);
QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * theArrowSize,
                                              cos(angle + Pi - Pi / 3) * theArrowSize);

p->drawPolygon(QPolygonF() << theCurrentLine->p1() << sourceArrowP1 << sourceArrowP2);

but now I want to draw the line after the arrow head polygon gets drawn.

How can I change the P1() value of the theCurrentLine which can start after the polygon as currently the polygon(arrowHead) and the line start at the same point? I need to start the line after the arrow head is drawn. The reason is sometimes if the pen width increases the arrow head looks smaller than the line.

2

There are 2 best solutions below

2
On BEST ANSWER

You can get the point at index in QPolygon.

 QPoint QPolygon::point ( int index ) const

It would be easy when you know how many points there are. And Qt documentation is your friend.

And you could use count(), for example:

 QPoint lastPoint = myPolygon.point(myPolygon.count() - 1);

Just give a name to your polygon, and you'll be fine.

Edit: Latest version of these codes should solve your problem. I thought I need to give an example. You need to add the points in this order:

 QPolygon myPolygon;
 myPolygon.setPoint(0, sourceArrowP1);
 myPolygon.setPoint(1, theCurrentLine->p1());
 myPolygon.setPoint(2, sourceArrowP2);
 p->drawPolygon(myPolygon);
 QPoint lastPoint;
 lastPoint = myPolygon.point(myPolygon.count() - 1);

You need to draw the line between last and first points. Here:

 p->drawLine(myPolygon.point(0, myPolygon.point(myPolygon.count() - 1));

If you want your arrow head to be filled with color, you need to use QPainterPath instead of QPolygon:

 QPen pen(Qt::black); //Or whatever color you want
 pen.setWidthF(10); //Or whatever size you want your lines to be
 QBrush brush(Qt::red); //Or whatever color you want to fill the arrow head
 p->setPen(pen);
 p->setBrush(brush);
 QPainterPath arrow(sourceArrowP1);
 arrow.lineTo(theCurrentLine->p1());
 arrow.lineTo(sourceArrowP2);
 arrow.lineTo(sourceArrowP1); //This returns to the first point. You might eliminate this line if you want to.
 p->drawPath(arrow);
4
On

My actual implementation:

theCurrentLine->setP1(QPointF(0, 0)  );  // arrow line coordinates
theCurrentLine->setP2((theLineVector));
double angle = ::acos(theCurrentLine->dx() / theCurrentLine->length());  // angle of the current Line
if (theCurrentLine->dy() >= 0)
    angle = TwoPi - angle;

// getting arrow head points to be drawn
QPointF sourcePoint = QPointF(0,0);

QPointF sourceArrowP1 = sourcePoint + QPointF(sin(angle + Pi / 3) * theArrowSize,
                                              cos(angle + Pi / 3) * theArrowSize);
QPointF sourceArrowP2 = sourcePoint + QPointF(sin(angle + Pi - Pi / 3) * theArrowSize,
                                              cos(angle + Pi - Pi / 3) * theArrowSize);

p->drawPolygon(QPolygonF() << theCurrentLine->p1() << sourceArrowP1 << sourceArrowP2);

// to find the center point in the arrow head right
QLineF perpLine = QLineF(theCurrentLine->p1(), theCurrentLine->p2());
QLineF arrowheadWidth = QLineF(sourceArrowP1, sourceArrowP2);

QPointF originPoint;
QLineF::IntersectType res = perpLine.intersect(arrowheadWidth, &originPoint);

theCurrentLine->setP1(originPoint);
p->drawLine(*theCurrentLine);

If anyone knows a much better way to implement this (I'm sure there will be), please correct me.