matrixtrigonometrygtk3cairorotational-matrices

Corners detection fails when textbox is rotated


enter image description here

After rotating the text box in the GTK drawing area, the four corners detection didn't work anymore as the x,y vertices were left to their original values. I used this code to update them but still doesn't work as you can see from the picture. The cursor shape changes when it's not hovering the top left circle handle.

static gboolean button_release_event(GtkWidget *widget, GdkEventButton *event, TextBox *textbox)
{
    if (event->button == GDK_BUTTON_PRIMARY)
    {
        textbox->button_pressed = FALSE;
        if (textbox->action == IS_ROTATING)
        {
            double dx = -textbox->width / 2;
            double dy = -textbox->height / 2;
            
            double cx = textbox->x - dx;
            double cy = textbox->y - dy;

            double a = atan2(dy,dx);
            double m = sqrt(dx * dx + dy * dy);
            double angle = a  + (textbox->angle * G_PI / 180.0);
            
            //Update the x,y coords after the rotation
            textbox->x = cx + m * cos(angle);
            textbox->y = cy + m * sin(angle);
            g_print("After the rotation: x,y %2.0f %2.0f\n",textbox->x,textbox->y);
        }
        textbox->action  = NONE;
        if (textbox->corner  != GDK_FLEUR)
            gdk_window_set_cursor(gtk_widget_get_window(widget), NULL);
    }

    return FALSE;
} 

This is the checking code:

    gint x,y;
    
    x = event->x * cos(-textbox->angle) - event->y * sin(-textbox->angle);
    y = event->y * sin(-textbox->angle) + event->y * cos(-textbox->angle);
    //Check if the mouse pointer is hovering the rotate circle
    if  (textbox->draw_rect && x >= textbox->x + (textbox->width/2) && x <= (textbox->x + (textbox->width/2)) + 5 
        && y>= textbox->y+textbox->height && y + 9 <= textbox->y+textbox->height + 22)
    {
        textbox->action = IS_ROTATING;
        textbox->corner  = GDK_EXCHANGE;
        gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new_for_display(gdk_display_get_default(),  textbox->corner ));
    }
    //If mouse pointer is inside the visible text frame change the cursor shape accordingly
    else if (!textbox->button_pressed && textbox->draw_rect && x >= textbox->x 
                    && x <= textbox->x + textbox->width && y >= textbox->y && y <= textbox->y + textbox->height)
    {
        if (x >= textbox->x && x <= textbox->x + 5 && y >= textbox->y && y <= textbox->y + 5)
        {
            textbox->action = IS_RESIZING;
            textbox->corner = GDK_TOP_LEFT_CORNER;
        }
        else if (x >= textbox->x + textbox->width - 3 && x <= textbox->x + textbox->width && y >= textbox->y && y <= textbox->y + 5)
        {
            textbox->corner = GDK_TOP_RIGHT_CORNER;
            textbox->action = IS_RESIZING;
        }
        else if (x >= textbox->x && x <= textbox->x + 5 &&  y >= textbox->y + textbox->height - 3 && y <= textbox->y + textbox->height)
        {
            textbox->corner = GDK_BOTTOM_LEFT_CORNER;
            textbox->action = IS_RESIZING;
        }
        else if (x >= textbox->x + textbox->width - 3 && x <= textbox->x + textbox->width && y >= textbox->y + textbox->height - 5 && y <= textbox->y + textbox->height)
        {
            textbox->corner = GDK_BOTTOM_RIGHT_CORNER;
            textbox->action = IS_RESIZING;
        }
        else
        {
            textbox->corner = GDK_FLEUR;
            textbox->action = IS_DRAGGING;
        }
        gdk_window_set_cursor(gtk_widget_get_window(widget), gdk_cursor_new_for_display(gdk_display_get_default(),  textbox->corner ));
    }

Where am I wrong?


Solution

  • The correct code to rotate the mouse coordinates is this one:

    static void transform_coords(TextBox *textbox, double x, double y, double *tx, double *ty)
    {
    double cx = textbox->x + textbox->width / 2;
    double cy = textbox->y + textbox->height / 2;
    
    // Translate to origin
    x -= cx;
    y -= cy;
    
    // Rotate
    double rx = x * cos(-textbox->angle) - y * sin(-textbox->angle);
    double ry = x * sin(-textbox->angle) + y * cos(-textbox->angle);
    
    // Translate back
    *tx = rx + cx;
    *ty = ry + cy;
    }