Juliette Marquis
Juliette Marquis

Reputation: 199

Transformations with Qt and C++

I am doing a program to draw an arc and move/rotate it according to the position of the mouse cursor :

initial position

This image illustrates the scene when the program is first run. The following images illustrates what is displayed after a mouse click. The mouse click happened at the top right point of the line.

position after mouse click

After getting the coordinates of the intersection point (between the line and the circle), I want to set the position of the center of the arc to the intersection point. But, as you can see, the arc is not where I wish it was. Strangely, when I draw a rectangle whose topLeft point is at the intersection point, it works :

enter image description here

I guess the problem has to be with scene/parent/item coordinates... But I can't find where :/

Here is a sample of the code : (DrawingScene inherits QGraphicsScene)

void DrawingScene::drawStates(){
    m_ellipse = new QGraphicsEllipseItem(80.0, 80.0,120.0,120.0);
    addItem(m_ellipse);
    m_arc = new GraphicArcItem(62.0, 62.0,50.0,50.0);
    m_arc->setParentItem(m_ellipse);
    m_arc->setStartAngle(0);
    m_arc->setSpanAngle(270 * 16);
    QLineF line_vertical(140.0,80.0,140.0,200.0);
    addLine(line_vertical);
    QLineF line_horizontal(80.0,140.0,200.0,140.0);
    addLine(line_horizontal);
    QLineF line(QPointF(62.0,62.0), QPointF(140.0,140.0));
    m_lineToCenter = new QGraphicsLineItem(line);
    addItem(m_lineToCenter);
}

void DrawingScene::mousePressEvent(QGraphicsSceneMouseEvent *event){
    p1 = event->scenePos();
    QLineF lineToCenter(QPointF(140.0,140.0), p1);
    m_lineToCenter->setLine(lineToCenter);
    QLineF horizontalLine(QPointF(140.0,140.0),QPointF(200.0,140.0));
    double angleBetweenLines = horizontalLine.angleTo(lineToCenter);
    double x = 60.0 * cos(angleBetweenLines * 3.14 / 180.0);
    double y = -60.0 * sin(angleBetweenLines * 3.14 / 180.0);
    QPointF intersectionPoint(x,y);
    QPointF topLeft = intersectionPoint + QPointF(140.0,140.0);
    addRect(QRectF(topLeft, QSizeF(60.0,60.0)));
    m_arc->setPos(topLeft);
}

Any help would be more than welcome :)

edit : Working code for moving the arc :

p1 = event->scenePos();
QLineF lineToCenter(QPointF(140.0,140.0), p1);//center of circle to mouse position
double angleBetweenPositions = lineToCenter.angleTo(m_lineToCenter->line()); 
m_lineToCenter->setLine(lineToCenter);
QLineF horizontalLine(QPointF(140.0,140.0),QPointF(200.0,140.0));
double angleBetweenLines = horizontalLine.angleTo(lineToCenter);

double x = 60.0 * cos(angleBetweenLines * 3.14 / 180.0);
double y = -60.0 * sin(angleBetweenLines * 3.14 / 180.0);
QPointF newPoint(x,y);
QPointF ellipse_center = m_ellipse->rect().center();
QPointF intersection_point = intersection_point + ellipse_center;
GraphicArcItem *arc2 = new GraphicArcItem(intersection_point.rx()- 25.0,
                                          intersection_point.ry() - 25.0,50.0,50.0);
addItem(arc2);
m_arc->setPos(intersection_point.rx()-85.0, intersection_point.ry() - 85.0);//why 85 ??

Code for the rotation :

m_arc->setCurrentRotation(m_arc->getCurrentRotation() + angleBetweenPositions);
m_arc->setTransformOriginPoint(m_arc->getCenter());
m_arc->setRotation(m_arc->getCurrentRotation());

Edit : Here are the key parts of the code solving the problem :

/*Return the center point of the arc in the parent coordinates*/
QPointF GraphicArcItem::getCenter(){
int xCenter = rect().x() + rect().width()/2;
int yCenter = rect().y() + rect().height()/2;
QPointF center = /*mapToParent(*/QPointF(xCenter,yCenter)/*)*/;
return center;
}

p1 = event->scenePos();
QPointF ellipse_center = m_ellipse->rect().center();
QLineF lineToCenter(ellipse_center, p1);//center of circle to mouse position
double angleBetweenPositions = lineToCenter.angleTo(m_lineToCenter->line());
QLineF horizontalLine(ellipse_center,QPointF(200.0,140.0));
double angleBetweenLines = horizontalLine.angleTo(lineToCenter);
double x = 60.0 * cos(angleBetweenLines * 3.14 / 180.0);
double y = -60.0 * sin(angleBetweenLines * 3.14 / 180.0);
QPointF newPoint(x,y);
QPointF intersection_point = newPoint + ellipse_center;
m_arc->setPos(intersection_point.rx() - 85.0, intersection_point.ry() - 85.0);
m_arc->setCurrentRotation(angleBetweenPositions);
QPointF rotation_center = m_arc->mapFromItem(m_arc, m_arc->getCenter());
m_arc->setTransformOriginPoint(rotation_center);
m_arc->setRotation(m_arc->getCurrentRotation());

Upvotes: 2

Views: 271

Answers (1)

scopchanov
scopchanov

Reputation: 8419

The rectangle and the arc have different parents (the scene is the parent of the rectangle and m_ellipse of the arc, hence the references of their coordinates are different. To test it just add a new arc/circle (different from m_arc and without using setParentItem(m_ellipse);) to the scene - it should have the correct screen position. To achieve the desired result I would suggest you to play with mapTo<something>/mapFrom<something> methods. I presume that mapToParent will do the trick, but you should check it anyway.

Upvotes: 1

Related Questions