Search code examples
c++qtqt5qpainter

How to rotate a line 45 degrees on key press with qt5?


I'm trying to rotate a line 45 degrees or horizontal or vertical when the shift key is being held.

This is being done in qt5 on c++ using the open source easy paint project on github linked here.

My problem is that I am unable to rotate it 45 degrees. I have been able to rotate vertical and horizontal.

This question was marked as a duplicate of another question I asked about the click handler here: Shift key click in qt?

My issue is no longer with the click handler as that question is answered, accepted and solved. This question is not a duplicate

My issue now is with the rotation logic for 45 degrees exclusively.

My code is below:

void LineInstrument::paint(ImageArea &imageArea, bool isSecondaryColor, bool)
{
    QPainter painter(imageArea.getImage());
    if(isSecondaryColor)
    {
        painter.setPen(QPen(DataSingleton::Instance()->getSecondaryColor(),
                            DataSingleton::Instance()->getPenSize() * imageArea.getZoomFactor(),
                            Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    }
    else
    {
        painter.setPen(QPen(DataSingleton::Instance()->getPrimaryColor(),
                            DataSingleton::Instance()->getPenSize() * imageArea.getZoomFactor(),
                            Qt::SolidLine, Qt::RoundCap, Qt::RoundJoin));
    }

    if(mStartPoint != mEndPoint) // here is where the line is drawn 
    {
        int deltaX, deltaY;
        // my modifications start here
        if (QGuiApplication::queryKeyboardModifiers().testFlag(Qt::ShiftModifier)) { // check if shift key is active
            // Compute change in x and change in y with absolute value to prevent faulty logic
            deltaX = abs(mEndPoint.x() - mStartPoint.x());
            deltaY = abs(mEndPoint.y() - mStartPoint.y());

            if (deltaX > deltaY){
                // transform to a horizontal line
                mEndPoint.setY(mStartPoint.y()); // rotate 180 making a horizontal line
            }
            else if (deltaX < deltaY){
                // transform to a vertical line 
                mEndPoint.setX(mStartPoint.x()); // rotate 90 making a vertical line
            }
            else if(deltaX == deltaY){
                // transform to a 45 degree line
                double pi = acos(-1); // Initialize pi
                double angle = 45 / 180.0 * pi; // sets angle to 45 degrees but in radians
                double LineLength = sqrt((pow(deltaX, 2) + pow(deltaY, 2))); // finds the distance of the line
                mEndPoint.setX(cos(angle)*LineLength + mStartPoint.x()); 
                mEndPoint.setY(sin(angle)*LineLength + mStartPoint.y());
            }
            else{
                // Not a special line do nothing
            }
            painter.drawLine(mStartPoint, mEndPoint); // let the line be drawn
        }// and end here
        painter.drawLine(mStartPoint, mEndPoint); // draw normal line if shift is not pressed 
    }

    if(mStartPoint == mEndPoint)
    {
        painter.drawPoint(mStartPoint);
    }
    imageArea.setEdited(true);
        //int rad(DataSingleton::Instance()->getPenSize() + round(sqrt((mStartPoint.x() - mEndPoint.x()) *
         //                                                            (mStartPoint.x() - mEndPoint.x()) +
          //                                                          (mStartPoint.y() - mEndPoint.y()) *
           //                                                          (mStartPoint.y() - mEndPoint.y()))));
      //mPImageArea->update(QRect(mStartPoint, mEndPoint).normalized().adjusted(-rad, -rad, +rad, +rad));
    painter.end();
    imageArea.update();
}

Solution

  • Suprisingly the code that I have works properly. It's just that for it to rotate properly at 45 degrees the coordinates being equivalent must be pinpoint and EXACT.

    It was difficult to even simulate for my demonstration but it works correctly.